- File:
-
- 1 edited
-
libcfa/src/concurrency/future.hfa (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/future.hfa
rbeeff61e r5e4a830 19 19 #include "monitor.hfa" 20 20 #include "select.hfa" 21 #include "locks.hfa"22 21 23 22 //---------------------------------------------------------------------------- … … 27 26 // future_t is lockfree and uses atomics which aren't needed given we use locks here 28 27 forall( T ) { 29 // enum { FUTURE_EMPTY = 0, FUTURE_FULFILLED = 1 }; // Enums seem to be broken so feel free to add this back afterwards28 // enum(int) { FUTURE_EMPTY = 0, FUTURE_FULFILLED = 1 }; // Enums seem to be broken so feel free to add this back afterwards 30 29 31 30 // temporary enum replacement … … 45 44 }; 46 45 46 // C_TODO: perhaps allow exceptions to be inserted like uC++? 47 47 48 static inline { 48 49 … … 81 82 void _internal_flush( future(T) & this ) with(this) { 82 83 while( ! waiters`isEmpty ) { 83 if ( !__handle_waituntil_OR( waiters ) ) // handle special waituntil OR case84 break; // if handle_OR returns false then waiters is empty so break85 84 select_node &s = try_pop_front( waiters ); 86 85 87 if ( s. clause_status== 0p )86 if ( s.race_flag == 0p ) 88 87 // poke in result so that woken threads do not need to reacquire any locks 88 // *(((future_node(T) &)s).my_result) = result; 89 89 copy_T( result, *(((future_node(T) &)s).my_result) ); 90 else if ( ! __make_select_node_available(s ) ) continue;90 else if ( !install_select_winner( s, &this ) ) continue; 91 91 92 92 // only unpark if future is not selected … … 97 97 98 98 // Fulfil the future, returns whether or not someone was unblocked 99 bool fulfil( future(T) & this, T val ) with(this) {99 bool fulfil( future(T) & this, T & val ) with(this) { 100 100 lock( lock ); 101 101 if( state != FUTURE_EMPTY ) … … 153 153 } 154 154 155 bool register_select( future(T) & this, select_node & s ) with(this) { 156 lock( lock ); 157 158 // check if we can complete operation. If so race to establish winner in special OR case 159 if ( !s.park_counter && state != FUTURE_EMPTY ) { 160 if ( !__make_select_node_available( s ) ) { // we didn't win the race so give up on registering 161 unlock( lock ); 162 return false; 163 } 164 } 165 166 // future not ready -> insert select node and return 155 void * register_select( future(T) & this, select_node & s ) with(this) { 156 lock( lock ); 157 158 // future not ready -> insert select node and return 0p 167 159 if( state == FUTURE_EMPTY ) { 168 160 insert_last( waiters, s ); 169 161 unlock( lock ); 170 return false; 171 } 172 173 __make_select_node_available( s ); 174 unlock( lock ); 175 return true; 176 } 177 178 bool unregister_select( future(T) & this, select_node & s ) with(this) { 179 if ( ! s`isListed ) return false; 162 return 0p; 163 } 164 165 // future ready and we won race to install it as the select winner return 1p 166 if ( install_select_winner( s, &this ) ) { 167 unlock( lock ); 168 return 1p; 169 } 170 171 unlock( lock ); 172 // future ready and we lost race to install it as the select winner 173 return 2p; 174 } 175 176 void unregister_select( future(T) & this, select_node & s ) with(this) { 180 177 lock( lock ); 181 178 if ( s`isListed ) remove( s ); 182 179 unlock( lock ); 183 return false;184 180 } 185 181 186 bool on_selected( future(T) & this, select_node & node ) { return true; }187 182 } 188 183 } … … 191 186 // These futures below do not support select statements so they may not be as useful as 'future' 192 187 // however the 'single_future' is cheap and cheerful and is most likely more performant than 'future' 193 // since it uses raw atomics and no locks 188 // since it uses raw atomics and no locks afaik 194 189 // 195 190 // As far as 'multi_future' goes I can't see many use cases as it will be less performant than 'future'
Note:
See TracChangeset
for help on using the changeset viewer.