Index: doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/barrier.cfa
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/barrier.cfa	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/barrier.cfa	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,144 @@
+#include <locks.hfa>
+#include <fstream.hfa>
+#include <stdio.h>
+#include <channel.hfa>
+#include <thread.hfa>
+#include <time.hfa>
+#include <string.h>
+
+size_t total_operations = 0;
+int Processors = 1, Tasks = 1, BarrierSize = 2;
+
+typedef channel( int ) Channel;
+
+Channel * barWait;
+Channel * entryWait;
+owner_lock o;
+
+bool done = false;
+size_t tasks_done = 0;
+
+static inline void flushBarrier() {
+    for ( j; BarrierSize ) {
+        insert( *entryWait, -1 );
+        insert( *barWait, -1 );
+    }
+}
+
+static inline void initBarrier() {
+    for ( j; BarrierSize )
+        insert( *entryWait, j );
+}
+
+static inline void barrier() {
+    int ticket = remove( *entryWait );
+    if ( ticket == -1 ) {
+		insert( *entryWait, -1 );
+		return;
+	}
+    if ( ticket == BarrierSize - 1 ) {
+		for ( j; BarrierSize - 1 )
+            insert( *barWait, j );
+        return;
+	}
+    ticket = remove( *barWait );
+    if ( ticket == -1 ) {
+		insert( *barWait, -1 );
+		return;
+	}
+
+	// last one out
+	if ( BarrierSize == 1 || ticket == BarrierSize - 2 ) {
+		for ( j; BarrierSize )
+            insert( *entryWait, j );
+	}
+}
+
+thread Task {};
+static inline void ?{}( Task & p, cluster & clu ) {
+    ((thread &)p){ clu };
+}
+void main(Task & this) {
+    size_t runs = 0;
+    for ( ;; ) {
+        if ( done ) break;
+        barrier();
+        runs++;
+    }
+    lock(o);
+    total_operations += runs;
+    // sout | "P: " | runs;
+    unlock(o);
+}
+
+
+int main( int argc, char * argv[] ) {
+    switch ( argc ) {
+	  case 3:
+		if ( strcmp( argv[2], "d" ) != 0 ) {			// default ?
+			BarrierSize = atoi( argv[2] );
+            if ( Processors < 1 ) goto Usage;
+		} // if
+	  case 2:
+		if ( strcmp( argv[1], "d" ) != 0 ) {			// default ?
+			Processors = atoi( argv[1] );
+			if ( Processors < 1 ) goto Usage;
+		} // if
+	  case 1:											// use defaults
+		break;
+	  default:
+	  Usage:
+		sout | "Usage: " | argv[0]
+             | " [ processors (> 0) | 'd' (default " | Processors
+			 | ") ] [ BarrierSize (> 0) | 'd' (default " | BarrierSize
+			 | ") ]" ;
+		exit( EXIT_FAILURE );
+	} // switch
+    Tasks = Processors;
+    if ( Tasks < BarrierSize )
+        Tasks = BarrierSize;
+
+    size_t Clusters = 1;
+    // create a cluster
+    cluster clus[Clusters];
+    processor * proc[Processors];
+    for ( i; Processors ) {
+        (*(proc[i] = malloc())){clus[i % Clusters]};
+    }
+
+    Channel entry{ 2 * BarrierSize };
+    Channel wait{ 2 * BarrierSize };
+
+    entryWait = &entry;
+    barWait = &wait;
+
+    initBarrier();
+    // sout | "Processors: " | Processors | " ProdsPerChan: " | Producers | " ConsPerChan: " | Consumers | "Channels: " | Channels | " Channel Size: " | ChannelSize;
+
+    // sout | "start";
+    Task * t[Tasks];
+
+    for ( i; Tasks ) {
+        (*(t[i] = malloc())){ clus[i % Clusters] };
+    }
+
+    sleep(10`s);
+    done = true;
+
+    // sout | "sleep";
+
+    flushBarrier();
+
+    for ( i; Tasks ) {
+        delete(t[i]);
+    }
+    
+    sout | total_operations;
+    // print_stats_now( *active_cluster(), CFA_STATS_READY_Q);
+
+    for ( i; Processors ) {
+        delete(proc[i]);
+    }
+    // sout | "done";
+    return 0;
+}
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/churn.cfa
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/churn.cfa	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/churn.cfa	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,164 @@
+#include <locks.hfa>
+#include <fstream.hfa>
+#include <stdio.h>
+#include <string.h>
+#include "channel.hfa"
+#include <thread.hfa>
+#include <time.hfa>
+#include <stats.hfa>
+size_t Processors = 1, Channels = 4, Producers = 1, Consumers = 1, ChannelSize = 128;
+
+owner_lock o;
+
+size_t total_operations = 0;
+size_t cons_check = 0, prod_check = 0;
+
+channel( size_t ) * channels;
+thread Consumer {};
+bool cons_done = false, prod_done = false;
+volatile int cons_done_count = 0;
+
+void getRandArray( int * chanIndices ) {
+    for ( int i = 0; i < Channels; i++ ) {
+        chanIndices[i] = i;
+    }
+    for ( int i = 0; i < Channels; i++ ) {
+        int loc_1 = prng() % Channels;
+        int loc_2 = prng() % Channels;
+        int temp = chanIndices[ loc_1 ];
+        chanIndices[ loc_1 ] = chanIndices[ loc_2 ];
+        chanIndices[ loc_2 ] = temp;
+    }
+}
+
+void main(Consumer & this) {
+    size_t i = 0;
+    size_t runs = 0;
+    size_t my_check = 0;
+    int chanIndices[Channels];
+    getRandArray( chanIndices );
+    
+    for ( ;;i++ ) {
+        if ( cons_done ) break;
+        size_t j = remove( channels[ chanIndices[ i % Channels ] ] );
+        my_check = my_check ^ j;
+        if ( !prod_done ) runs++;
+    }
+    lock(o);
+    total_operations += runs;
+    cons_done_count++;
+    cons_check = cons_check ^ my_check;
+    // sout | "Cons: " | runs;
+    unlock(o);
+}
+
+thread Producer {};
+
+void main(Producer & this) {
+    size_t i = 0;
+    size_t runs = 0;
+    size_t my_check = 0;
+    int chanIndices[Channels];
+    getRandArray( chanIndices );
+    for ( ;;i++ ) {
+        if ( prod_done ) break;
+        insert( channels[ chanIndices[ i % Channels ] ], i );
+        my_check = my_check ^ i;
+        runs++;
+    }
+    lock(o);
+    total_operations += runs;
+    prod_check = prod_check ^ my_check;
+    // sout | "Prods: " | runs;
+    unlock(o);
+}
+
+
+int main( int argc, char *argv[] ) {
+    switch( argc ) {
+      case 4:
+		if ( strcmp( argv[3], "d" ) != 0 ) {			// default ?
+			if ( atoi( argv[3] ) < 1 ) goto Usage;
+			ChannelSize = atoi( argv[3] );
+		} // if
+      case 3:
+		if ( strcmp( argv[2], "d" ) != 0 ) {			// default ?
+			if ( atoi( argv[2] ) < 1 ) goto Usage;
+			Channels = atoi( argv[2] );
+		} // if
+      case 2:
+		if ( strcmp( argv[1], "d" ) != 0 ) {			// default ?
+			if ( atoi( argv[1] ) < 1 ) goto Usage;
+			Processors = atoi( argv[1] );
+		} // if
+	  case 1:											// use defaults
+		break;
+	  default:
+	  Usage:
+		sout | "Usage: " | argv[0]
+             | " [ processors > 0 | d ]"
+             | " [ producers > 0 | d ]"
+             | " [ consumers > 0 | d ]"
+             | " [ channels > 0 | d ]";
+		exit( EXIT_FAILURE );
+    }
+    processor p[Processors - 1];
+    channels = anew( Channels );
+    Producers = Processors / 2;
+    Consumers = Processors / 2;
+
+    // sout | "Processors: " | Processors | " Producers: " | Producers | " Consumers: " | Consumers | "Channels: " | Channels | " Channel Size: " | ChannelSize;
+
+    for ( i; Channels ) {
+        channels[i]{ ChannelSize };
+    }
+
+    // sout | "start";
+    {   
+        Consumer c[Consumers];
+        {
+            Producer p[Producers];
+            sleep(10`s);
+            prod_done = true;
+            // sout | "sleep";
+        }
+        // sout | "prods";
+        cons_done = true;
+        // for ( i; Channels ) {
+        //     if ( get_count( channels[i] ) < Consumers ){
+        //         for ( j; Consumers ) insert( channels[i], 0 );
+        //     }
+        // }
+        while( cons_done_count != Consumers ) {
+            for ( i; Channels ) {
+                if ( has_waiters( channels[i] ) ){
+                    insert( channels[i], 0 );
+                }
+            }
+        }
+    }
+    // sout | "cons";
+
+    for ( i; Channels ) {
+        for ( ;; ) {
+            if ( get_count( channels[i] ) > 0 ) {
+                size_t j = remove( channels[ i ] );
+                cons_check = cons_check ^ j;
+            } else break;
+        }
+    }
+
+    adelete( channels );
+
+    if ( cons_check != prod_check )
+        sout | "CHECKSUM MISMATCH !!!";
+    // print_stats_now( *active_cluster(), CFA_STATS_READY_Q);
+
+    // for ( i; Processors ) {
+    //     delete(proc[i]);
+    // }
+
+    sout | total_operations;
+    // print_stats_now( *active_cluster(), CFA_STATS_READY_Q );
+    return 0;
+}
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/contend.cfa
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/contend.cfa	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/contend.cfa	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,213 @@
+#include <locks.hfa>
+#include <fstream.hfa>
+#include <stdio.h>
+#include <channel.hfa>
+#include <thread.hfa>
+#include <time.hfa>
+#include <string.h>
+
+// user defines this
+// #define BIG 1
+
+owner_lock o;
+
+size_t total_operations = 0;
+
+struct bigObject {
+    size_t a;
+    size_t b;
+    size_t c;
+    size_t d;
+    size_t e;
+    size_t f;
+    size_t g;
+    size_t h;
+};
+
+void ?{}( bigObject & this, size_t i ) with(this) { a = i; b = i; c = i; d = i; e = i; f = i; g = i; h = i; }
+void ?{}( bigObject & this ) { this{0}; }
+
+#ifdef BIG
+typedef channel( bigObject ) Channel;
+#else
+typedef channel( size_t ) Channel;
+#endif
+
+Channel * channels;
+
+bool cons_done = false, prod_done = false;
+volatile int cons_done_count = 0;
+size_t cons_check = 0, prod_check = 0;
+
+thread Consumer {
+    size_t i;
+};
+static inline void ?{}( Consumer & c, size_t i, cluster & clu ) {
+    ((thread &)c){ clu };
+    c.i = i; 
+}
+void main(Consumer & this) {
+    size_t runs = 0;
+    size_t my_check = 0;
+    for ( ;; ) {
+        if ( cons_done ) break;
+        #ifdef BIG
+        bigObject j = remove( channels[ this.i ] );
+        my_check = my_check ^ (j.a + j.b + j.c + j.d + j.d + j.e + j.f + j.g + j.h);
+        #else
+        size_t j = remove( channels[ this.i ] );
+        my_check = my_check ^ j;
+        #endif
+        
+        if ( !prod_done ) runs++;
+    }
+    lock(o);
+    total_operations += runs;
+    cons_done_count++;
+    cons_check = cons_check ^ my_check;
+    // sout | "C: " | runs;
+    unlock(o);
+}
+
+thread Producer {
+    size_t i;
+};
+static inline void ?{}( Producer & p, size_t i, cluster & clu ) {
+    ((thread &)p){ clu };
+    p.i = i;
+}
+void main(Producer & this) {
+    size_t runs = 0;
+    size_t my_check = 0;
+    size_t my_id = this.i;
+    for ( ;; ) {
+        if ( prod_done ) break;
+        #ifdef BIG
+        bigObject j{(size_t)runs};
+        insert( channels[ my_id ], j );
+        my_check = my_check ^ (j.a + j.b + j.c + j.d + j.d + j.e + j.f + j.g + j.h);
+        #else
+        insert( channels[ my_id ], (size_t)runs );
+        my_check = my_check ^ ((size_t)runs);
+        #endif
+        runs++;
+    }
+    lock(o);
+    total_operations += runs;
+    prod_check = prod_check ^ my_check;
+    // sout | "P: " | runs;
+    unlock(o);
+}
+
+static inline int test( size_t Processors, size_t Channels, size_t Producers, size_t Consumers, size_t ChannelSize ) {
+    size_t Clusters = 1;
+    // create a cluster
+    cluster clus[Clusters];
+    processor * proc[Processors];
+    for ( i; Processors ) {
+        (*(proc[i] = malloc())){clus[i % Clusters]};
+    }
+
+    channels = aalloc( Channels );
+
+    // sout | "Processors: " | Processors | " ProdsPerChan: " | Producers | " ConsPerChan: " | Consumers | "Channels: " | Channels | " Channel Size: " | ChannelSize;
+    
+    for ( i; Channels ) {
+        channels[i]{ ChannelSize };
+    }
+
+    // sout | "start";
+    Consumer * c[Consumers * Channels];
+    Producer * p[Producers * Channels];
+
+    for ( j; Channels ) {
+        for ( i; Producers ) {
+            (*(p[i] = malloc())){ j, clus[j % Clusters] };
+        }
+
+        for ( i; Consumers ) {
+            (*(c[i] = malloc())){ j, clus[j % Clusters] };
+        }
+    }
+
+    sleep(10`s);
+    prod_done = true;
+
+    for ( i; Producers * Channels ) {
+        delete(p[i]);
+    }
+
+    // sout | "prods";
+    cons_done = true;
+    while( cons_done_count != Consumers * Channels ) {
+        for ( i; Channels ) {
+            if ( has_waiters( channels[i] ) ){
+                #ifdef BIG
+                bigObject b{0};
+                insert( channels[i], b );
+                #else
+                insert( channels[i], 0 );
+                #endif
+            }
+        }
+    }
+
+    // sout | "cons";
+    for ( i; Consumers * Channels ) {
+        delete(c[i]);
+    }
+
+    // sout | "flush";
+    for ( i; Channels ) {
+        for ( ;; ) {
+            if ( get_count( channels[i] ) > 0 ) {
+                #ifdef BIG
+                bigObject j = remove( channels[ i ] );
+                cons_check = cons_check ^ (j.a + j.b + j.c + j.d + j.d + j.e + j.f + j.g + j.h);
+                #else
+                size_t j = remove( channels[ i ] );
+                cons_check = cons_check ^ j;
+                #endif
+            } else break;
+        }
+    }
+
+    adelete( channels );
+    sout | total_operations;
+    if ( cons_check != prod_check )
+        sout | "CHECKSUM MISMATCH !!!";
+    // print_stats_now( *active_cluster(), CFA_STATS_READY_Q);
+
+    for ( i; Processors ) {
+        delete(proc[i]);
+    }
+    // sout | "done";
+    return 0;
+}
+
+int main( int argc, char * argv[] ) {
+    size_t Processors = 1, Channels = 1, Producers = 1, Consumers = 1, ChannelSize = 128;
+    switch ( argc ) {
+	  case 3:
+		if ( strcmp( argv[2], "d" ) != 0 ) {			// default ?
+			ChannelSize = atoi( argv[2] );
+		} // if
+	  case 2:
+		if ( strcmp( argv[1], "d" ) != 0 ) {			// default ?
+			Processors = atoi( argv[1] );
+			if ( Processors < 1 ) goto Usage;
+		} // if
+	  case 1:											// use defaults
+		break;
+	  default:
+	  Usage:
+		sout | "Usage: " | argv[0]
+             | " [ processors (> 0) | 'd' (default " | Processors
+			 | ") ] [ channel size (>= 0) | 'd' (default " | ChannelSize
+			 | ") ]" ;
+		exit( EXIT_FAILURE );
+	} // switch
+    Producers = Processors / 2;
+    Consumers = Processors / 2;
+    test(Processors, Channels, Producers, Consumers, ChannelSize);
+}
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/daisy_chain.cfa
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/daisy_chain.cfa	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/daisy_chain.cfa	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,77 @@
+#include <locks.hfa>
+#include <fstream.hfa>
+#include <stdio.h>
+#include <channel.hfa>
+#include <thread.hfa>
+#include <time.hfa>
+#include <string.h>
+
+size_t total_operations = 0;
+size_t Processors = 1, Tasks = 1;
+
+owner_lock o;
+
+// typedef channel_base( int, exp_backoff_then_block_lock ) Channel;
+typedef channel( int ) Channel;
+
+Channel * chain;
+
+bool done = false;
+
+thread Task {};
+void main(Task & this) {
+    size_t runs = 0;
+    for ( ;; ) {
+        if ( done ) break;
+        remove( *chain );
+        insert( *chain, 0 );
+        runs++;
+    }
+    lock( o );
+    total_operations += runs;
+    unlock( o );
+}
+
+
+int main( int argc, char * argv[] ) {
+    switch ( argc ) {
+	  case 3:
+		if ( strcmp( argv[2], "d" ) != 0 ) {			// default ?
+			Tasks = atoi( argv[2] );
+            if ( Tasks < 1 ) goto Usage;
+		} // if
+	  case 2:
+		if ( strcmp( argv[1], "d" ) != 0 ) {			// default ?
+			Processors = atoi( argv[1] );
+			if ( Processors < 1 ) goto Usage;
+		} // if
+	  case 1:											// use defaults
+		break;
+	  default:
+	  Usage:
+		sout | "Usage: " | argv[0]
+             | " [ processors (> 0) | 'd' (default " | Processors
+			 | ") ] [ channel size (>= 0) | 'd' (default " | Tasks
+			 | ") ]" ;
+		exit( EXIT_FAILURE );
+	} // switch
+    Tasks = Processors;
+    processor proc[Processors - 1];
+
+    Channel chainChan{ 2 * Tasks };
+
+    insert( chainChan, 0 );
+
+    chain = &chainChan;    
+    {
+        Task t[Tasks];
+        sleep(10`s);
+        done = true;
+        for ( j; Tasks )
+            insert( chainChan, 0 );
+    }
+    
+    sout | total_operations;
+
+    return 0;
+}
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/hot_potato.cfa
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/hot_potato.cfa	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/hot_potato.cfa	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,86 @@
+#include <locks.hfa>
+#include <fstream.hfa>
+#include <stdio.h>
+#include <channel.hfa>
+#include <thread.hfa>
+#include <time.hfa>
+#include <string.h>
+
+size_t total_operations = 0;
+size_t Processors = 1, Tasks = 1;
+
+owner_lock o;
+
+// typedef channel_base( int, exp_backoff_then_block_lock ) Channel;
+typedef channel( int ) Channel;
+
+Channel * chain;
+
+bool done = false;
+int id_counter = 0;
+thread Task { int id; int right; };
+static inline void ?{}( Task & this ) with(this) {
+    id = __atomic_fetch_add( &id_counter, 1, __ATOMIC_SEQ_CST );
+    right = (id + 1) % Tasks;
+}
+void main(Task & this) with(this) {
+    size_t runs = 0;
+    int my_id = id;
+    int my_right = right;
+    for ( ;; ) {
+        if ( done ) break;
+        remove( chain[my_id] );
+        insert( chain[my_right], 0 );
+        runs++;
+    }
+    lock( o );
+    total_operations += runs;
+    unlock( o );
+}
+
+
+int main( int argc, char * argv[] ) {
+    switch ( argc ) {
+	  case 3:
+		if ( strcmp( argv[2], "d" ) != 0 ) {			// default ?
+			Tasks = atoi( argv[2] );
+            if ( Tasks < 1 ) goto Usage;
+		} // if
+	  case 2:
+		if ( strcmp( argv[1], "d" ) != 0 ) {			// default ?
+			Processors = atoi( argv[1] );
+			if ( Processors < 1 ) goto Usage;
+		} // if
+	  case 1:											// use defaults
+		break;
+	  default:
+	  Usage:
+		sout | "Usage: " | argv[0]
+             | " [ processors (> 0) | 'd' (default " | Processors
+			 | ") ] [ channel size (>= 0) | 'd' (default " | Tasks
+			 | ") ]" ;
+		exit( EXIT_FAILURE );
+	} // switch
+    Tasks = Processors;
+    processor proc[Processors - 1];
+
+    chain = aalloc( Tasks );
+    for ( i; Tasks ) {
+        chain[i]{ 3 };
+    }
+
+    insert( chain[0], 0 );
+    {
+        Task t[Tasks];
+        sleep(10`s);
+        done = true;
+        for ( j; Tasks )
+            insert( chain[j], 0 );
+    }
+    
+    sout | total_operations;
+
+    adelete(chain);
+
+    return 0;
+}
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/ping_pong.cfa
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/ping_pong.cfa	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/ping_pong.cfa	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,62 @@
+#include <locks.hfa>
+#include <fstream.hfa>
+#include <stdio.h>
+#include <channel.hfa>
+#include <thread.hfa>
+#include <time.hfa>
+#include <string.h>
+
+size_t total_operations = 0;
+
+// typedef channel_base( int, exp_backoff_then_block_lock ) Channel;
+typedef channel( int ) Channel;
+
+Channel * ping;
+Channel * pong;
+
+bool done = false;
+
+thread Pong {};
+void main(Pong & this) {
+    for ( ;; ) {
+        if ( done ) break;
+        insert( *ping, 0 );
+        remove( *pong );
+    }
+}
+
+thread Ping {};
+void main(Ping & this) {
+    size_t runs = 0;
+    for ( ;; ) {
+        if ( done ) break;
+        remove( *ping );
+        insert( *pong, 1 );
+        total_operations++;
+    }
+}
+
+
+int main( int argc, char * argv[] ) {
+    processor proc[1];
+
+    Channel pingChan{ 2 };
+    Channel pongChan{ 2 };
+
+    ping = &pingChan;
+    pong = &pongChan;
+    
+    {
+        Ping pi;
+        Pong po;
+        sleep(10`s);
+        done = true;
+        insert( *pong, 2 );
+        insert( *ping, 2 );
+    }
+    
+    sout | total_operations;
+
+    // sout | "done";
+    return 0;
+}
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/pub_sub.cfa
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/pub_sub.cfa	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/cfa/pub_sub.cfa	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,168 @@
+#include <locks.hfa>
+#include <fstream.hfa>
+#include <stdio.h>
+#include <channel.hfa>
+#include <thread.hfa>
+#include <time.hfa>
+#include <string.h>
+#include <mutex_stmt.hfa>
+
+size_t total_operations = 0;
+size_t Processors = 1, Tasks = 1;
+
+typedef channel( size_t ) Channel;
+
+channel( int ) * barWait;
+channel( int ) * entryWait;
+int BarrierSize = 1;
+static inline void flushBarrier() {
+    for ( j; BarrierSize ) {
+        insert( *entryWait, -1 );
+        insert( *barWait, -1 );
+    }
+}
+
+static inline void initBarrier() {
+    for ( j; BarrierSize )
+        insert( *entryWait, j );
+}
+
+static inline void barrier() {
+    int ticket = remove( *entryWait );
+    if ( ticket == -1 ) {
+		insert( *entryWait, -1 );
+		return;
+	}
+    if ( ticket == BarrierSize - 1 ) {
+		for ( j; BarrierSize - 1 )
+            insert( *barWait, j );
+        return;
+	}
+    ticket = remove( *barWait );
+    if ( ticket == -1 ) {
+		insert( *barWait, -1 );
+		return;
+	}
+
+	// last one out
+	if ( BarrierSize == 1 || ticket == BarrierSize - 2 ) {
+		for ( j; BarrierSize )
+            insert( *entryWait, j );
+	}
+}
+
+Channel ** chans;
+owner_lock o;
+
+bool done = false;
+size_t tasks_done = 0;
+
+thread Task { size_t id; };
+static inline void ?{}( Task & p, size_t i, cluster & clu ) {
+    ((thread &)p){ clu };
+    p.id = i;
+}
+void main(Task & this) with(this) {
+    size_t runs = 0;
+    size_t my_id = id;
+    for ( ;; ) {
+        if ( done ) break;
+
+        // publish
+        for ( i; Tasks ) {
+            insert(*chans[my_id], i);
+        }
+
+        // subscribe
+        for ( i; Tasks ) {
+            remove( *chans[i] );
+        }
+        barrier();
+        runs++;
+    }
+    lock(o);
+    total_operations += runs;
+    // sout | "P: " | runs;
+    unlock(o);
+}
+
+
+int main( int argc, char * argv[] ) {
+    switch ( argc ) {
+	  case 3:
+		if ( strcmp( argv[2], "d" ) != 0 ) {			// default ?
+			Tasks = atoi( argv[2] );
+            if ( Tasks < 1 ) goto Usage;
+		} // if
+	  case 2:
+		if ( strcmp( argv[1], "d" ) != 0 ) {			// default ?
+			Processors = atoi( argv[1] );
+			if ( Processors < 1 ) goto Usage;
+		} // if
+	  case 1:											// use defaults
+		break;
+	  default:
+	  Usage:
+		sout | "Usage: " | argv[0]
+             | " [ processors (> 0) | 'd' (default " | Processors
+			 | ") ] [ Tasks (> 0) | 'd' (default " | Tasks
+			 | ") ]" ;
+		exit( EXIT_FAILURE );
+	} // switch
+    Tasks = Processors;
+    BarrierSize = Tasks;
+
+    size_t Clusters = 1;
+    // create a cluster
+    cluster clus[Clusters];
+    processor * proc[Processors];
+    for ( i; Processors ) {
+        (*(proc[i] = malloc())){clus[i % Clusters]};
+    }
+
+    chans = aalloc( Tasks );
+    for ( i; Tasks ) {
+        chans[i] = malloc();
+        (*chans[i]){ 2 * Tasks };
+    }
+        
+
+    // setup barrier
+    channel(int) entry{ 2 * BarrierSize };
+    channel(int) wait{ 2 * BarrierSize };
+    entryWait = &entry;
+    barWait = &wait;
+    initBarrier();
+
+    // sout | "Processors: " | Processors | " ProdsPerChan: " | Producers | " ConsPerChan: " | Consumers | "Channels: " | Channels | " Channel Size: " | ChannelSize;
+
+    // sout | "start";
+    Task * t[Tasks];
+
+    for ( i; Tasks ) {
+        (*(t[i] = malloc())){ i, clus[i % Clusters] };
+    }
+
+    sleep(10`s);
+    done = true;
+
+    for ( i; Tasks )
+        for ( j; Tasks )
+            insert(*chans[i], j);
+
+    flushBarrier();
+
+    for ( i; Tasks ) {
+        delete(t[i]);
+    }
+    
+    sout | total_operations;
+    // print_stats_now( *active_cluster(), CFA_STATS_READY_Q);
+
+    for ( i; Processors ) {
+        delete(proc[i]);
+    }
+    adelete( chans );
+    // sout | "done";
+    return 0;
+}
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/data/nasus.txt
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/data/nasus.txt	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/data/nasus.txt	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,68 @@
+5
+2 4 8 16 24 32
+CFA Go 
+contend: 
+CFA:
+cores	throughput (entries)
+2	551286815
+2	551571851
+2	552609970
+2	550645159
+2	551408217
+4	401548741
+4	399726800
+4	400805457
+4	400374246
+4	400036245
+8	83833131
+8	85215809
+8	78675522
+8	77117062
+8	78952724
+16	45757611
+16	43434187
+16	43167191
+16	38760778
+16	38089187
+24	49974858
+24	43920833
+24	34870886
+24	38659096
+24	50407137
+32	45780022
+32	35247189
+32	33644070
+32	45037228
+32	41352523
+Go:
+cores	throughput (entries)
+2	311586714
+2	317443340
+2	306943968
+2	313532129
+2	319176028
+4	239546403
+4	237102189
+4	236127253
+4	238228033
+4	238143975
+8	106047415
+8	115591180
+8	109898737
+8	120893507
+8	114025063
+16	40950543
+16	38709696
+16	48643203
+16	48749849
+16	36154667
+24	41250340
+24	32248479
+24	34967215
+24	30199179
+24	42352113
+32	37012621
+32	42679904
+32	36861891
+32	42289651
+32	42185180
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/data/pyke.txt
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/data/pyke.txt	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/data/pyke.txt	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,68 @@
+5
+2 4 8 16 24 32
+CFA Go 
+contend: 
+CFA:
+cores	throughput (entries)
+2	329449063
+2	337588767
+2	361434457
+2	358608413
+2	347994204
+4	149531302
+4	144861313
+4	155833698
+4	148693619
+4	147357220
+8	56837894
+8	55492836
+8	58486345
+8	61065249
+8	57501460
+16	40610682
+16	41502618
+16	40547457
+16	42161859
+16	41104030
+24	38892695
+24	37659117
+24	38517375
+24	39237104
+24	38905810
+32	34053774
+32	33262537
+32	34182192
+32	35591452
+32	33701109
+Go:
+cores	throughput (entries)
+2	262695836
+2	259522629
+2	264620424
+2	263513756
+2	261709432
+4	195640947
+4	198914691
+4	198331166
+4	199846909
+4	194256135
+8	84136662
+8	83617598
+8	82212468
+8	81249230
+8	83531222
+16	37690664
+16	32904283
+16	37513686
+16	36389425
+16	36887196
+24	31560865
+24	30341279
+24	31687458
+24	30711777
+24	30421494
+32	29845150
+32	30053899
+32	29871808
+32	29625722
+32	30007528
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/genPlots
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/genPlots	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/genPlots	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,3 @@
+#!/bin/bash -
+python3 plotData.py data/nasus.txt nasus_
+python3 plotData.py data/pyke.txt pyke_
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/go/barrier/barrier.go
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/go/barrier/barrier.go	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/go/barrier/barrier.go	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,125 @@
+package main
+
+import (
+	"fmt"
+	"sync"
+	"time"
+	"runtime"
+	"os"
+	"strconv"
+)
+
+var Processors, Tasks, BarrierSize int = 1, 1, 2
+var done bool = false;
+var total_operations uint64 = 0
+var m sync.Mutex
+
+var taskJoin chan int = make(chan int, Tasks + 1)
+
+var barWait chan int = make(chan int, 2 * BarrierSize)
+var entryWait chan int = make(chan int, 2 * BarrierSize)
+
+func initBarrier() {
+	for j := 0; j < BarrierSize; j++ {
+		entryWait <- j
+	}
+}
+
+func barrier() {
+	ticket := <-entryWait
+	if ( ticket == -1 ) {
+		entryWait <- -1
+		return
+	}
+	if ( ticket == BarrierSize - 1 ) {
+		for j := 0; j < BarrierSize - 1; j++ {
+			barWait <- j
+		}
+	} else {
+		ticket = <- barWait
+		if ( ticket == -1 ) {
+			barWait <- -1
+			return
+		}
+	}
+
+	// last one out
+	if ( BarrierSize == 1 || ticket == BarrierSize - 2 ) {
+		for j := 0; j < BarrierSize; j++ {
+			entryWait <- j
+		}
+	}
+}
+
+func task() {
+	var count uint64 = 0
+	for {
+		if done { break }
+		barrier()
+		count++
+	}
+	m.Lock()
+	total_operations += count
+	// fmt.Print("C: ",count)
+	m.Unlock()
+	taskJoin <- 0
+}
+
+func usage() {
+	fmt.Printf( "Usage: %v " +
+		"[ processors (> 0) | 'd' (default %v) ] " +
+		"[ BarrierSize (> 0) | 'd' (default %v) ]\n",
+		os.Args[0], Processors, BarrierSize );
+	os.Exit( 1 );
+}
+
+func main() {
+	switch len( os.Args ) {
+		case 3:
+			if os.Args[2] != "d" {							// default ?
+				BarrierSize, _ = strconv.Atoi( os.Args[2] )
+				if BarrierSize < 1 { usage(); }
+			} // if
+		fallthrough
+		case 2:
+			if os.Args[1] != "d" {							// default ?
+				Processors, _ = strconv.Atoi( os.Args[1] )
+				if Processors < 1 { usage(); }
+			} // if
+		case 1:											// use defaults
+		default:
+		usage();
+	} // switch
+	runtime.GOMAXPROCS( Processors );
+	Tasks = Processors
+
+	if ( Tasks < BarrierSize ) {
+        Tasks = BarrierSize
+	}
+
+	// fmt.Println("Processors: ",Processors," Channels: ",Channels," ProdsPerChan: ",ProdsPerChan," ConsPerChan: ",ConsPerChan," Channel Size: ",ChannelSize)
+	taskJoin = make(chan int, Tasks + 1)
+	barWait = make(chan int, 2 * BarrierSize)
+	entryWait = make(chan int, 2 * BarrierSize)
+	initBarrier()
+
+	for j := 0; j < Tasks; j++ {
+		go task()
+	}
+		
+	// wait 10 seconds
+	time.Sleep(time.Second * 10)
+	// fmt.Println("prod done\n")
+	done = true
+
+	for j := 0; j < BarrierSize; j++ {
+		barWait <- -1
+		entryWait <- -1
+	}
+
+	for j := 0; j < Tasks; j++ {
+		<-taskJoin
+	}
+
+    fmt.Println(total_operations)
+}
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/go/barrier/go.mod
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/go/barrier/go.mod	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/go/barrier/go.mod	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,3 @@
+module barrier
+
+go 1.18
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/go/churn/churn.go
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/go/churn/churn.go	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/go/churn/churn.go	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,156 @@
+package main
+
+import (
+	"fmt"
+	"sync"
+	"math/rand"
+	"time"
+	"runtime"
+	"os"
+	"strconv"
+)
+
+var Processors, Channels, Producers, Consumers, ChannelSize int = 1, 4, 1, 1, 128
+var cons_done, prod_done bool = false, false;
+var total_operations, cons_check, prod_check uint64 = 0, 0, 0
+var m sync.Mutex
+
+var prodJoin chan int = make(chan int, Producers + 1)
+var consJoin chan int = make(chan int, Consumers + 1)
+
+func getRandArray() []int {
+	chanIndices := make( [] int, Channels )
+	for i := 0; i < Channels; i += 1 {
+		chanIndices[i] = i
+	}
+	for i := 0; i < Channels; i += 1 {
+		var loc_1 int  = rand.Intn(Channels) % Channels
+        var loc_2 int  = rand.Intn(Channels) % Channels;
+        var temp int = chanIndices[loc_1]
+        chanIndices[loc_1] = chanIndices[loc_2]
+        chanIndices[loc_2] = temp
+	}
+	return chanIndices
+}
+
+func consumer( chans [] chan uint64 ) {
+	var count uint64 = 0
+	var checksum uint64 = 0
+	var i int = 0
+	chanIndices := getRandArray()
+	for {
+		if cons_done { break }
+		j := <- chans[ chanIndices[ i ] ]
+		i = (i + 1) % Channels
+		checksum = checksum ^ j
+		if ! prod_done { count++ }
+	}
+	m.Lock()
+	total_operations += count
+	cons_check = cons_check ^ checksum
+	m.Unlock()
+	consJoin <- 0
+}
+
+func producer( chans [] chan uint64 ) {
+	var count uint64 = 0
+	var i int = 0
+	var checksum uint64 = 0
+	chanIndices := getRandArray()
+	for {
+		if prod_done { break }
+		chans[ chanIndices[ i ] ] <- count
+		i = (i + 1) % Channels
+		checksum = checksum ^ count
+		count++
+	}
+	m.Lock()
+	total_operations += count
+	prod_check = prod_check ^ checksum
+	m.Unlock()
+	prodJoin <- 0
+}
+
+func usage() {
+	fmt.Printf( "Usage: %v " +
+		"[ processors (> 0) | 'd' (default %v) ] " +
+		"[ ChannelSize (> 0) | 'd' (default %v) ]\n",
+		os.Args[0], Processors, ChannelSize );
+	os.Exit( 1 );
+}
+
+func main() {
+	switch len( os.Args ) {
+		case 3:
+			if os.Args[2] != "d" {							// default ?
+				Channels, _ = strconv.Atoi( os.Args[2] )
+					if Channels < 0 { usage(); }
+			} // if
+		fallthrough
+		case 2:
+			if os.Args[1] != "d" {							// default ?
+				Processors, _ = strconv.Atoi( os.Args[1] )
+				if Processors < 1 { usage(); }
+			} // if
+		case 1:											// use defaults
+		default:
+		usage();
+	} // switch
+	runtime.GOMAXPROCS( Processors );
+	Producers = Processors /2
+	Consumers = Processors /2
+
+	// fmt.Println("Processors: ",Processors," Channels: ",Channels," Prods: ",Producers," Cons: ",Consumers," Channel Size: ",ChannelSize)
+
+	chans := make( [] chan uint64, Channels )
+	for i := range chans {
+		chans[i] = make(chan uint64, ChannelSize)
+	}
+
+	for j := 0; j < Consumers; j++ {
+		go consumer( chans )
+	}
+
+	for j := 0; j < Producers; j++ {
+		go producer( chans )
+	}
+
+	// wait 10 seconds
+	time.Sleep(time.Second * 10)
+	prod_done = true
+
+	for j := 0; j < Producers; j++ {
+		<-prodJoin
+	}
+
+	cons_done = true
+
+	for i := range chans {
+		for j := 0; j < Consumers; j++ {
+			select {
+				case chans[i] <- 0:
+					
+				default:
+					break
+			}
+		}
+	}
+	for j := 0; j < Consumers; j++{
+		<-consJoin
+	}
+	for i := range chans {
+		L: for {
+			select {
+				case k := <-chans[i]:
+					cons_check = cons_check ^ k
+				default:
+					break L
+			}
+		}
+	}
+	if cons_check != prod_check {
+		fmt.Println("\nChecksum mismatch: Cons: %d, Prods: %d", cons_check, prod_check)
+	}
+
+    fmt.Println(total_operations)
+}
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/go/churn/go.mod
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/go/churn/go.mod	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/go/churn/go.mod	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,3 @@
+module churn
+
+go 1.18
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/go/contend/contend.go
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/go/contend/contend.go	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/go/contend/contend.go	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,132 @@
+package main
+
+import (
+	"fmt"
+	"sync"
+	"time"
+	"runtime"
+	"os"
+	"strconv"
+)
+
+var Processors, Channels, ProdsPerChan, ConsPerChan, ChannelSize int = 1, 1, 1, 1, 128
+var cons_done, prod_done bool = false, false;
+var total_operations, cons_check, prod_check uint64 = 0, 0, 0
+var m sync.Mutex
+
+var prodJoin chan int = make(chan int, ProdsPerChan * Channels + 1)
+var consJoin chan int = make(chan int, ConsPerChan * Channels + 1)
+
+func consumer( channel chan uint64 ) {
+	var count uint64 = 0
+	var checksum uint64 = 0
+	for {
+		if cons_done { break }
+		j := <- channel
+		checksum = checksum ^ j
+		if ! prod_done { count++ }
+	}
+	m.Lock()
+	total_operations += count
+	cons_check = cons_check ^ checksum
+	// fmt.Print("C: ",count)
+	m.Unlock()
+	consJoin <- 0
+}
+
+func producer( channel chan uint64 ) {
+	var count uint64 = 0
+	var checksum uint64 = 0
+	for {
+		if prod_done { break }
+		checksum = checksum ^ count
+		channel <- count
+		count++
+	}
+	m.Lock()
+	total_operations += count
+	prod_check = prod_check ^ checksum
+	// fmt.Print("P: ",count, " ")
+	m.Unlock()
+	prodJoin <- 0
+}
+
+func usage() {
+	fmt.Printf( "Usage: %v " +
+		"[ processors (> 0) | 'd' (default %v) ] " +
+		"[ ChannelSize (> 0) | 'd' (default %v) ]\n",
+		os.Args[0], Processors, ChannelSize );
+	os.Exit( 1 );
+}
+
+func main() {
+	switch len( os.Args ) {
+		case 3:
+			if os.Args[2] != "d" {							// default ?
+				ChannelSize, _ = strconv.Atoi( os.Args[2] )
+					if ChannelSize < 0 { usage(); }
+			} // if
+		fallthrough
+		case 2:
+			if os.Args[1] != "d" {							// default ?
+				Processors, _ = strconv.Atoi( os.Args[1] )
+				if Processors < 1 { usage(); }
+			} // if
+		case 1:											// use defaults
+		default:
+		usage();
+	} // switch
+	runtime.GOMAXPROCS( Processors );
+	ProdsPerChan = Processors /2
+	ConsPerChan = Processors / 2
+
+	// fmt.Println("Processors: ",Processors," Channels: ",Channels," ProdsPerChan: ",ProdsPerChan," ConsPerChan: ",ConsPerChan," Channel Size: ",ChannelSize)
+	
+	chans := make( [] chan uint64, Channels )
+	for i := range chans {
+		chans[i] = make(chan uint64, ChannelSize)
+	}
+	for i := range chans {
+		for j := 0; j < ProdsPerChan; j++ {
+			go producer( chans[i] )
+		}
+
+		for j := 0; j < ConsPerChan; j++ {
+			go consumer( chans[i] )
+		}
+	}
+		
+
+	// wait 10 seconds
+	time.Sleep(time.Second * 10)
+	// fmt.Println("prod done\n")
+	prod_done = true
+	for j := 0; j < ProdsPerChan * Channels ; j++ {
+		<-prodJoin
+	}
+	// fmt.Println("cons done\n")
+	cons_done = true
+	for i := range chans {
+		L: for {
+			select {
+				case k := <-chans[i]:
+					cons_check = cons_check ^ k
+				default:
+					break L
+			}
+		}
+	}
+	for i := range chans {
+		close(chans[i])
+	}
+
+	for j := 0; j < ConsPerChan * Channels; j++{
+		<-consJoin
+	}
+	
+	
+	if cons_check != prod_check {
+		fmt.Println("\nChecksum mismatch: Cons: %d, Prods: %d", cons_check, prod_check)
+	}
+    fmt.Println(total_operations)
+}
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/go/contend/go.mod
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/go/contend/go.mod	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/go/contend/go.mod	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,3 @@
+module contend
+
+go 1.18
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/go/daisy_chain/daisy_chain.go
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/go/daisy_chain/daisy_chain.go	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/go/daisy_chain/daisy_chain.go	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,70 @@
+package main
+
+import (
+	"fmt"
+	"time"
+	"runtime"
+	"sync"
+	"os"
+	"strconv"
+)
+
+var done bool = false;
+var total_operations uint64 = 0
+var Processors int = 1
+var m sync.Mutex
+
+var taskJoin chan int = make(chan int, 2)
+var chain chan int = make(chan int, 2 )
+
+func Task() {
+	var count uint64 = 0 
+	for {
+		if done { break }
+		<-chain
+		chain<-0
+		count++;
+	}
+	
+	m.Lock()
+	total_operations += count
+	m.Unlock()
+	taskJoin <- 0
+}
+
+func main() {
+	switch len( os.Args ) {
+		case 2:
+			if os.Args[1] != "d" {							// default ?
+				Processors, _ = strconv.Atoi( os.Args[1] )
+			} // if
+		case 1:											// use defaults
+		default:
+			fmt.Printf( "Invalid args" );
+			os.Exit( 1 );
+	} // switch
+	runtime.GOMAXPROCS( Processors );
+
+	taskJoin= make(chan int, Processors)
+	chain= make(chan int, 2 * Processors )
+	
+	chain <- 0
+
+	for i := 0; i < Processors; i++ {
+		go Task()
+	}
+		
+	// wait 10 seconds
+	time.Sleep(time.Second * 10)
+	// fmt.Println("prod done\n")
+	done = true
+
+	for i := 0; i < Processors; i++ {
+		chain <- 0
+	}
+	for i := 0; i < Processors; i++ {
+		<-taskJoin
+	}
+
+    fmt.Println(total_operations)
+}
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/go/daisy_chain/go.mod
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/go/daisy_chain/go.mod	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/go/daisy_chain/go.mod	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,3 @@
+module daisy_chain
+
+go 1.18
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/go/hot_potato/go.mod
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/go/hot_potato/go.mod	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/go/hot_potato/go.mod	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,3 @@
+module hot_potato
+
+go 1.18
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/go/hot_potato/hot_potato.go
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/go/hot_potato/hot_potato.go	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/go/hot_potato/hot_potato.go	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,72 @@
+package main
+
+import (
+	"fmt"
+	"time"
+	"runtime"
+	"sync"
+	"os"
+	"strconv"
+)
+
+var done bool = false;
+var total_operations uint64 = 0
+var Processors int = 1
+var m sync.Mutex
+
+var taskJoin chan int = make(chan int, 2)
+
+func Task( chans [] chan uint64, id int ) {
+	var count uint64 = 0
+	right := (id + 1) % Processors
+	for {
+		if done { break }
+		<-chans[id]
+		chans[right]<-0
+		count++;
+	}
+	m.Lock()
+	total_operations += count
+	m.Unlock()
+	taskJoin <- 0
+}
+
+func main() {
+	switch len( os.Args ) {
+		case 2:
+			if os.Args[1] != "d" {							// default ?
+				Processors, _ = strconv.Atoi( os.Args[1] )
+			} // if
+		case 1:											// use defaults
+		default:
+			fmt.Printf( "Invalid args" );
+			os.Exit( 1 );
+	} // switch
+	runtime.GOMAXPROCS( Processors );
+
+	taskJoin = make(chan int, Processors)
+	chans := make( [] chan uint64, Processors )
+	for i := range chans {
+		chans[i] = make(chan uint64, 3)
+	}
+
+	chans[0] <- 0
+
+	for i := 0; i < Processors; i++ {
+		go Task( chans, i )
+	}
+		
+	// wait 10 seconds
+	time.Sleep(time.Second * 10)
+	// fmt.Println("prod done\n")
+	done = true
+
+	for i := 0; i < Processors; i++ {
+		chans[i] <- 0
+	}
+	for i := 0; i < Processors; i++ {
+		<-taskJoin
+	}
+
+    fmt.Println(total_operations)
+}
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/go/ping_pong/go.mod
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/go/ping_pong/go.mod	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/go/ping_pong/go.mod	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,3 @@
+module ping_pong
+
+go 1.18
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/go/ping_pong/ping_pong.go
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/go/ping_pong/ping_pong.go	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/go/ping_pong/ping_pong.go	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,54 @@
+package main
+
+import (
+	"fmt"
+	"time"
+	"runtime"
+)
+
+var done bool = false;
+var total_operations uint64 = 0
+
+var taskJoin chan int = make(chan int, 2)
+
+var ping chan int = make(chan int, 2 )
+var pong chan int = make(chan int, 2 )
+
+func Ping() {
+	for {
+		if done { break }
+		pong <- 1
+		<-ping
+	}
+	taskJoin <- 0
+}
+
+func Pong() {
+	for {
+		if done { break }
+		<-pong
+		ping <- 0
+		total_operations++
+	}
+	taskJoin <- 0
+}
+
+func main() {
+	runtime.GOMAXPROCS( 2 );
+
+	go Ping()
+	go Pong()
+		
+	// wait 10 seconds
+	time.Sleep(time.Second * 10)
+	// fmt.Println("prod done\n")
+	done = true
+
+	ping <- 2
+	pong <- 2
+
+	<-taskJoin
+	<-taskJoin
+
+    fmt.Println(total_operations)
+}
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/go/pub_sub/go.mod
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/go/pub_sub/go.mod	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/go/pub_sub/go.mod	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,3 @@
+module pub_sub
+
+go 1.18
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/go/pub_sub/pub_sub.go
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/go/pub_sub/pub_sub.go	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/go/pub_sub/pub_sub.go	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,145 @@
+package main
+
+import (
+	"fmt"
+	"sync"
+	"time"
+	"runtime"
+	"os"
+	"strconv"
+)
+
+var Processors, Tasks int = 1, 1
+var BarrierSize int = 2
+var done bool = false;
+var total_operations uint64 = 0
+var m sync.Mutex
+
+var taskJoin chan int = make(chan int, Tasks + 1)
+
+var barWait chan int = make(chan int, 2 * BarrierSize)
+var entryWait chan int = make(chan int, 2 * BarrierSize)
+
+func flushBarrier() {
+	for j := 0; j < BarrierSize; j++ {
+		barWait <- -1
+		entryWait <- -1
+	}
+}
+
+func initBarrier() {
+	for j := 0; j < BarrierSize; j++ {
+		entryWait <- j
+	}
+}
+
+func barrier() {
+	ticket := <-entryWait
+	if ( ticket == -1 ) {
+		entryWait <- -1
+		return
+	}
+	if ( ticket == BarrierSize - 1 ) {
+		for j := 0; j < BarrierSize - 1; j++ {
+			barWait <- j
+		}
+	} else {
+		ticket = <- barWait
+		if ( ticket == -1 ) {
+			barWait <- -1
+			return
+		}
+	}
+
+	// last one out
+	if ( BarrierSize == 1 || ticket == BarrierSize - 2 ) {
+		for j := 0; j < BarrierSize; j++ {
+			entryWait <- j
+		}
+	}
+}
+
+func task( chans [] chan uint64 ) {
+	var count uint64 = 0
+	for {
+		if done { break }
+		for j := 0; j < Tasks; j++ {
+			chans[j] <- 0
+		}
+
+		for j := 0; j < Tasks; j++ {
+			<- chans[j]
+		}
+		barrier()
+		count++
+	}
+	m.Lock()
+	total_operations += count
+	// fmt.Print("C: ",count)
+	m.Unlock()
+	taskJoin <- 0
+}
+
+func usage() {
+	fmt.Printf( "Usage: %v " +
+		"[ processors (> 0) | 'd' (default %v) ] " +
+		"[ BarrierSize (> 0) | 'd' (default %v) ]\n",
+		os.Args[0], Processors, BarrierSize );
+	os.Exit( 1 );
+}
+
+func main() {
+	switch len( os.Args ) {
+		case 3:
+			if os.Args[2] != "d" {							// default ?
+				Tasks, _ = strconv.Atoi( os.Args[2] )
+				if Tasks < 1 { usage(); }
+			} // if
+		fallthrough
+		case 2:
+			if os.Args[1] != "d" {							// default ?
+				Processors, _ = strconv.Atoi( os.Args[1] )
+				if Processors < 1 { usage(); }
+			} // if
+		case 1:											// use defaults
+		default:
+		usage();
+	} // switch
+	runtime.GOMAXPROCS( Processors );
+	Tasks = Processors
+	BarrierSize = Tasks
+
+	// fmt.Println("Processors: ",Processors," Channels: ",Channels," ProdsPerChan: ",ProdsPerChan," ConsPerChan: ",ConsPerChan," Channel Size: ",ChannelSize)
+	taskJoin = make(chan int, Tasks + 1)
+	barWait = make(chan int, 2 * BarrierSize)
+	entryWait = make(chan int, 2 * BarrierSize)
+	initBarrier()
+
+	chans := make( [] chan uint64, Tasks )
+	for i := range chans {
+		chans[i] = make(chan uint64, 2 * Tasks)
+	}
+
+	for j := 0; j < Tasks; j++ {
+		go task( chans )
+	}
+		
+	// wait 10 seconds
+	time.Sleep(time.Second * 10)
+	// fmt.Println("prod done\n")
+	done = true
+
+	for i := 0; i < Tasks; i++ {
+		for j := 0; j < Tasks; j++ {
+			chans[i] <- 0
+		}
+	}
+
+	flushBarrier()
+	
+	for j := 0; j < Tasks; j++ {
+		<-taskJoin
+	}
+
+    fmt.Println(total_operations)
+}
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/plotData.py
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/plotData.py	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/plotData.py	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,157 @@
+import os
+import sys
+import time
+import itertools
+import matplotlib.pyplot as plt
+import matplotlib.ticker as ticks
+import math
+from scipy import stats as st
+import numpy as np
+from enum import Enum
+from statistics import median
+
+import matplotlib
+matplotlib.use("pgf")
+matplotlib.rcParams.update({
+    "pgf.texsystem": "pdflatex",
+    'font.family': 'serif',
+    'text.usetex': True,
+    'pgf.rcfonts': False,
+    'font.size': 16
+})
+marker = itertools.cycle(('o', 's', 'D', 'x', 'p', '^', 'h', '*', 'v' ))
+
+def sci_format(x, pos):
+    return '{:.1e}'.format(x).replace('+0', '')
+
+readfile = open(sys.argv[1], "r")
+
+machineName = ""
+
+if len(sys.argv) > 2:
+    machineName = sys.argv[2]
+
+# first line has num times per experiment
+line = readfile.readline()
+numTimes = int(line)
+
+# second line has processor args
+line = readfile.readline()
+procs = []
+for val in line.split():
+    procs.append(int(val))
+
+# 3rd line has number of variants
+line = readfile.readline()
+names = line.split()
+numVariants = len(names)
+
+lines = (line.rstrip() for line in readfile) # All lines including the blank ones
+lines = (line for line in lines if line) # Non-blank lines
+
+class Bench(Enum):
+    Unset = 0
+    Contend = 1
+    Zero = 2
+    Barrier = 3
+    Churn = 4
+    Daisy_Chain = 5
+    Hot_Potato = 6
+    Pub_Sub = 7
+
+nameSet = False
+currBench = Bench.Unset # default val
+count = 0
+procCount = 0
+currVariant = 0
+experiment_duration = 10.0
+name = ""
+title = ""
+var_name = ""
+sendData = [0.0 for j in range(numVariants)]
+data = [[0.0 for i in range(len(procs))] for j in range(numVariants)]
+bars = [[[0.0 for i in range(len(procs))],[0.0 for k in range(len(procs))]] for j in range(numVariants)]
+tempData = [0.0 for i in range(numTimes)]
+for idx, line in enumerate(lines):
+    # print(line)
+    
+    if currBench == Bench.Unset:
+        if line == "contend:":
+            name = "Channel_Contention"
+            title = "Channel Contention"
+            currBench = Bench.Contend
+        elif line == "zero:":
+            name = "Zero"
+            currBench = Bench.Zero
+        elif line == "barrier:":
+            name = "Barrier"
+            currBench = Bench.Barrier
+        elif line == "churn:":
+            name = "Churn"
+            currBench = Bench.Churn
+        elif line == "daisy_chain:":
+            name = "Daisy_Chain"
+            currBench = Bench.Daisy_Chain
+        elif line == "hot_potato:":
+            name = "Hot_Potato"
+            currBench = Bench.Hot_Potato
+        elif line == "pub_sub:":
+            name = "Pub_Sub"
+            currBench = Bench.Pub_Sub
+        else:
+            print("Expected benchmark name")
+            print("Line: " + line)
+            sys.exit()
+        continue
+
+    if line[0:5] == "cores":
+        continue
+
+    if not nameSet:
+        nameSet = True
+        continue
+    
+    lineArr = line.split()
+    tempData[count] = float(lineArr[-1]) / experiment_duration
+    count += 1
+    if count == numTimes:
+        currMedian = median( tempData )
+        data[currVariant][procCount] = currMedian
+        lower, upper = st.t.interval(0.95, numTimes - 1, loc=np.mean(tempData), scale=st.sem(tempData))
+        bars[currVariant][0][procCount] = currMedian - lower
+        bars[currVariant][1][procCount] = upper - currMedian
+        count = 0
+        procCount += 1
+
+        if procCount == len(procs):
+            procCount = 0
+            nameSet = False
+            currVariant += 1
+
+            if currVariant == numVariants:
+                fig, ax = plt.subplots(layout='constrained')
+                if title != "":
+                    plt.title(title + " Benchmark")
+                    title = ""
+                else:
+                    plt.title(name + " Benchmark")
+                plt.ylabel("Throughput (channel operations per second)")
+                plt.xlabel("Cores")
+                ax.yaxis.set_major_formatter(ticks.FuncFormatter(sci_format))
+                for idx, arr in enumerate(data):
+                    plt.errorbar( procs, arr, [bars[idx][0], bars[idx][1]], capsize=2, marker=next(marker) )
+                marker = itertools.cycle(('o', 's', 'D', 'x', 'p', '^', 'h', '*', 'v' )) 
+                # plt.yscale("log")
+                # plt.ylim(1, None)
+                # ax.get_yaxis().set_major_formatter(ticks.ScalarFormatter())
+                # else:
+                #     plt.ylim(0, None)
+                plt.xticks(procs)
+                ax.legend(names)
+                # fig.savefig("plots/" + machineName + name + ".png")
+                plt.savefig("plots/" + machineName + name + ".pgf")
+                fig.clf()
+
+                # reset
+                currBench = Bench.Unset
+                currVariant = 0
Index: doc/theses/colby_parsons_MMath/benchmarks/channels/run
===================================================================
--- doc/theses/colby_parsons_MMath/benchmarks/channels/run	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
+++ doc/theses/colby_parsons_MMath/benchmarks/channels/run	(revision f945fa7ba076d346ab1aa115747f79712d70331d)
@@ -0,0 +1,223 @@
+#!/bin/bash -
+
+false=0; true=1
+
+# Usage: arch [ hostname ] returns hostname, cores, startcore
+#
+#   Define machine architecture based on starting socket, CPUs (cores) per socket, number of
+#   sockets, has hyperthreading.
+
+start=0
+
+arch() {
+	hostname=${1:-`hostname`}			# return value
+	hashyper=${true}					# assume machine has hyperthreads
+	if [ "${hostname}" = "plg2" ] ; then
+		startsocket=${start}
+		cps=16							# coresPerSocket
+		sockets=2
+		hashyper=${false}				# has no hyperthreads
+	elif [ "${hostname}" = "nasus" ] ; then
+		startsocket=${start}
+		cps=64							# coresPerSocket
+		sockets=2
+	elif [ "${hostname}" = "pyke" ] ; then
+		startsocket=${start}
+		cps=24							# coresPerSocket
+		sockets=2
+	elif [ "${hostname}" = "jax" ] ; then
+		startsocket=${start}
+		cps=24							# coresPerSocket
+		sockets=4
+	else
+		echo "unsupported host" ${hostname}
+		exit 1
+	fi
+	cores=$(( ${cps} * ${sockets} ))
+	startcore=$(( ${startsocket} * ${cps} ))
+}
+
+# Usage: affinity (global cps, sockets, startsocket, hashyper, cores, startcore, wrap)
+#   returns taskset argument
+#
+#   This routine assumes hyperthreading has only 2 hyperthreads per core.
+#
+#   If hyperthread scanning is used: processor units are assigned across the low-number hyperthreads
+#   of the socket's cores. When the low-number hyperthreads are filled, the high-number hyperhtreads
+#   are assigned across the socket's cores. Then the next socket is assigned.
+#
+#   If hyperthread wrapping is used: processor units are assigned in low/high-number pairs of
+#   hyperthreads across the socket's cores. Then the next socket is assigned.
+
+wrap=${false}							# set to control hyperthread assignment across socket cores
+
+affinity() {
+	if [ ${wrap} -eq ${true} -a ${hashyper} -eq ${false} ] ; then
+		echo "architecture does not support hyperthreading for wrapping"
+		exit 1
+	fi
+	taskset=""							# return value
+	set -- $(( ${1} - 1 ))				# decrement $1
+	if [ ${1} -eq 0 ] ; then taskset="${startcore}-${startcore}"; return; fi
+	if [ ${1} -ge $(( ${cps} * ( ${sockets} - ${startsocket} ) * ( ${hashyper} + 1 ) )) ] ; then # error
+		echo "not enough cores $(( ${cores} * ${sockets} )) for $(( ${1} + 1 )) starting at ${startcore}"
+		exit 1
+	fi
+	if [ ${hashyper} -eq ${false} ] ; then taskset="${startcore}-$(( ${1} + ${startcore} ))"; return; fi # no hyperthreads
+	start2=$(( ${startcore} + ${cores} ))
+	if [ ${wrap} -eq ${true} ] ; then 	# hyperthread wrapping
+		end1=$(( ${1} / 2 + ${startcore} ))
+		end2=$(( ${end1} + ${cores} ))
+		if [ $(( ${1} % 2 )) -eq 0 ] ; then
+			end2=$(( ${end2} - 1 ))
+		fi
+		taskset="${startcore}-${end1},${start2}-${end2}"
+	else								# hyperthread scanning
+		if [ ${1} -lt ${cps} ] ; then taskset="${startcore}-$(( ${1} + ${startcore} ))"; return; fi
+		filled=$(( ${1} / ( ${cps} * 2 ) * ${cps} ))
+		modulus=$(( ${1} % ( ${cps} * 2 ) ))	# leftover cores added to saturated sockets
+		if [ ${modulus} -gt ${cps} ] ; then
+			taskset="${startcore}-$(( ${startcore} + ${filled} + ${cps} - 1 )),${start2}-$(( ${start2} + ${filled} + ${modulus} % ${cps} ))"
+		else
+			taskset="${startcore}-$(( ${startcore} + ${filled} + ${modulus} )),${start2}-$(( ${start2} + ${filled} - 1 ))"
+		fi
+	fi
+}
+
+numtimes=5
+
+num_threads='2 4 8 16 24 32'
+# num_threads='2'
+
+# toggle benchmarks
+zero=${false}
+contend=${true}
+barrier=${false}
+churn=${false}
+daisy_chain=${false}
+hot_potato=${false}
+pub_sub=${false}
+
+runCFA=${true}
+runGO=${true}
+# runCFA=${false}
+# runGO=${false}
+
+cfa=~/cfa-cc/driver/cfa
+
+# Helpers to minimize code duplication
+
+# repeats a command ${numtimes}
+preprint=''
+repeat_command() {
+    t=1
+    while [ ${t} -le ${numtimes} ] ; do
+        echo -n -e ${preprint}
+        "${@}"
+        t=`expr ${t} + 1`
+    done
+}
+
+# prints the leading info for a given run of a variant
+print_header() {
+    echo ${1}':'
+    echo -e "cores\tthroughput (entries)"
+}
+
+# runs the current benchmark with provided args
+# only works for standard-run benchmarks (not Akka)
+# must split into pre and post args to be able to supply val of p
+pre_args=''
+post_args=''
+single_run() {
+    affinity ${1}
+    preprint="${1}\t"
+    repeat_command taskset -c ${taskset} ./a.${hostname} ${pre_args} ${1} ${post_args}
+}
+
+# runs the current bench for all processor vals
+# works for standard benchs that dont need to set a config file (not Akka or CAF)
+run_bench() {
+    for p in ${num_threads} ; do
+        single_run ${p}
+    done
+}
+
+arch # get hostname
+
+# set up leading info for python script
+echo $numtimes
+echo $num_threads
+
+if [ ${runCFA} -eq ${true} ]; then
+    echo -n 'CFA '
+fi
+if [ ${runGO} -eq ${true} ]; then
+    echo -n 'Go '
+fi
+echo ""
+
+# done printing header info for output
+
+# cfa flags
+cfa_flags='-quiet -O3 -nodebug -DNDEBUG'
+
+# run the benchmarks
+
+run_contend() {
+    post_args=${1}
+
+    if [ ${runCFA} -eq ${true} ] ; then
+        cd cfa # CFA RUN
+        print_header 'CFA'
+        ${cfa} ${cfa_flags} ${2}.cfa -o a.${hostname} > /dev/null 2>&1
+        run_bench
+        rm a.${hostname}
+        cd - > /dev/null
+    fi # done CFA
+
+    if [ ${runGO} -eq ${true} ] ; then
+        cd go/${2} # Go RUN
+        print_header 'Go'
+        go build -o a.${hostname} > /dev/null 2>&1
+        run_bench
+        rm a.${hostname}
+        cd - > /dev/null
+    fi # done Go
+}
+
+# /usr/bin/time -f "%Uu %Ss %Er %Mkb"
+if [ ${contend} -eq ${true} ] ; then
+    echo "contend: "
+    run_contend '128' 'contend'
+fi
+
+if [ ${zero} -eq ${true} ] ; then
+    echo "zero: "
+    run_contend '0' 'contend'
+fi
+
+if [ ${barrier} -eq ${true} ] ; then
+    echo "barrier: "
+    run_contend '' 'barrier'
+fi
+
+if [ ${churn} -eq ${true} ] ; then
+    echo "churn: "
+    run_contend '' 'churn'
+fi
+
+if [ ${daisy_chain} -eq ${true} ] ; then
+    echo "daisy_chain: "
+    run_contend '' 'daisy_chain'
+fi
+
+if [ ${hot_potato} -eq ${true} ] ; then
+    echo "hot_potato: "
+    run_contend '' 'hot_potato'
+fi
+
+if [ ${pub_sub} -eq ${true} ] ; then
+    echo "pub_sub: "
+    run_contend '' 'pub_sub'
+fi
