Index: libcfa/src/concurrency/kernel/fwd.hfa
===================================================================
--- libcfa/src/concurrency/kernel/fwd.hfa	(revision aeb20a4d256d7e9fe5da6b3be21994f201fa9cbe)
+++ libcfa/src/concurrency/kernel/fwd.hfa	(revision c06551b988f564d4bba9f99c9aeec146690e3599)
@@ -200,5 +200,4 @@
 					struct thread$ * expected = this.ptr;
 					if(expected == 1p) return false;
-					/* paranoid */ verify( expected == 0p );
 					if(__atomic_compare_exchange_n(&this.ptr, &expected, active_thread(), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
 						park();
@@ -213,5 +212,5 @@
 			thread$ * post(oneshot & this, bool do_unpark = true) {
 				struct thread$ * got = __atomic_exchange_n( &this.ptr, 1p, __ATOMIC_SEQ_CST);
-				if( got == 0p ) return 0p;
+				if( got == 0p || got == 1p ) return 0p;
 				if(do_unpark) unpark( got );
 				return got;
@@ -263,5 +262,4 @@
 
 					// The future is not fulfilled, try to setup the wait context
-					/* paranoid */ verify( expected == 0p );
 					if(__atomic_compare_exchange_n(&this.ptr, &expected, &wait_ctx, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
 						return true;
@@ -275,20 +273,20 @@
 			// should retract the wait ctx
 			// intented to be use by wait, wait_any, waitfor, etc. rather than used directly
-			void retract( future_t & this, oneshot & wait_ctx ) {
+			bool retract( future_t & this, oneshot & wait_ctx ) {
 				// Remove the wait context
 				struct oneshot * got = __atomic_exchange_n( &this.ptr, 0p, __ATOMIC_SEQ_CST);
 
 				// got == 0p: future was never actually setup, just return
-				if( got == 0p ) return;
+				if( got == 0p ) return false;
 
 				// got == wait_ctx: since fulfil does an atomic_swap,
 				// if we got back the original then no one else saw context
 				// It is safe to delete (which could happen after the return)
-				if( got == &wait_ctx ) return;
+				if( got == &wait_ctx ) return false;
 
 				// got == 1p: the future is ready and the context was fully consumed
 				// the server won't use the pointer again
 				// It is safe to delete (which could happen after the return)
-				if( got == 1p ) return;
+				if( got == 1p ) return true;
 
 				// got == 2p: the future is ready but the context hasn't fully been consumed
@@ -296,5 +294,5 @@
 				if( got == 2p ) {
 					while( this.ptr != 1p ) Pause();
-					return;
+					return false;
 				}
 
@@ -379,4 +377,26 @@
 				return ret;
 			}
+
+			// Wait for any future to be fulfilled
+			future_t & wait_any( future_t * futures, size_t num_futures ) {
+				oneshot temp;
+
+				// setup all futures
+				// if any are already satisfied return
+				for ( i; num_futures ) {
+					if( !setup(futures[i], temp) ) return futures[i];
+				}
+				
+				// Wait context is setup, just wait on it
+				wait( temp );
+				
+				size_t ret;
+				// attempt to retract all futures
+				for ( i; num_futures ) {
+					if ( retract( futures[i], temp ) ) ret = i;
+				}
+				
+				return futures[ret];
+			}
 		}
 
Index: tests/concurrent/futures/.expect/wait_any.txt
===================================================================
--- tests/concurrent/futures/.expect/wait_any.txt	(revision c06551b988f564d4bba9f99c9aeec146690e3599)
+++ tests/concurrent/futures/.expect/wait_any.txt	(revision c06551b988f564d4bba9f99c9aeec146690e3599)
@@ -0,0 +1,2 @@
+start
+done
Index: tests/concurrent/futures/wait_any.cfa
===================================================================
--- tests/concurrent/futures/wait_any.cfa	(revision c06551b988f564d4bba9f99c9aeec146690e3599)
+++ tests/concurrent/futures/wait_any.cfa	(revision c06551b988f564d4bba9f99c9aeec146690e3599)
@@ -0,0 +1,77 @@
+#include <thread.hfa>
+#include <fstream.hfa>
+#include <stdlib.hfa>
+#include <mutex_stmt.hfa>
+#include <locks.hfa>
+
+simple_owner_lock l;
+pthread_cond_var( simple_owner_lock ) c;
+
+size_t num_futures = 10;
+
+future_t * futures;
+
+size_t * shuffle_arr;
+
+size_t numtimes = 10;
+
+volatile bool done = false;
+
+void synchronize() {
+    lock(l);
+    if (empty(c)) {
+        wait(c,l);
+    } else {
+        for ( i; num_futures ) {
+            reset(futures[i]);
+        }
+        notify_one(c);
+    }
+    unlock(l);
+}
+
+thread Waiter {};
+void main( Waiter & this ) {
+    for (numtimes) {
+        wait_any(futures, num_futures);
+        synchronize();
+    }
+    done = true;
+    while (done) notify_one(c);
+}
+
+thread Deliverer {};
+void main( Deliverer & this ) {
+    while (!done) {
+        size_t num_satisfy = random(1,num_futures);
+        for ( i; num_satisfy ) {								// random shuffle a few values
+			swap( shuffle_arr[random(num_futures)], shuffle_arr[random(num_futures)] );
+		}
+        for ( i; num_satisfy ) {
+            post(*futures[shuffle_arr[i]].ptr, true);
+        }
+        synchronize();
+    }
+    done = false;
+}
+
+int main() {
+	sout | "start";
+    futures = alloc( num_futures );
+    shuffle_arr = alloc( num_futures );
+    for ( i; num_futures ) {								// random shuffle a few values
+        futures[i]{};
+        swap( shuffle_arr[random(num_futures)], shuffle_arr[random(num_futures)] );
+    }
+    for ( i; num_futures ) {
+        shuffle_arr[i] = i;
+    }
+	processor procs[1];
+	{
+		Waiter w;
+		Deliverer d;
+	}
+    free( futures );
+    free( shuffle_arr );
+	sout | "done";
+}
