Changeset 3982384 for libcfa/src/concurrency/future.hfa
- Timestamp:
- May 17, 2023, 1:35:09 AM (2 years ago)
- Branches:
- ADT, master
- Children:
- f11010e
- Parents:
- 6e4c44d (diff), 8db4708 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/future.hfa
r6e4c44d r3982384 19 19 #include "monitor.hfa" 20 20 #include "select.hfa" 21 #include "locks.hfa" 21 22 22 23 //---------------------------------------------------------------------------- … … 26 27 // future_t is lockfree and uses atomics which aren't needed given we use locks here 27 28 forall( T ) { 28 // enum (int){ FUTURE_EMPTY = 0, FUTURE_FULFILLED = 1 }; // Enums seem to be broken so feel free to add this back afterwards29 // enum { FUTURE_EMPTY = 0, FUTURE_FULFILLED = 1 }; // Enums seem to be broken so feel free to add this back afterwards 29 30 30 31 // temporary enum replacement … … 44 45 }; 45 46 46 // C_TODO: perhaps allow exceptions to be inserted like uC++?47 48 47 static inline { 49 48 … … 53 52 } 54 53 55 void ?{}( future(T) & this) {54 void ?{}( future(T) & this ) { 56 55 this.waiters{}; 57 56 this.state = FUTURE_EMPTY; … … 60 59 61 60 // Reset future back to original state 62 void reset( future(T) & this) with(this)61 void reset( future(T) & this ) with(this) 63 62 { 64 63 lock( lock ); … … 82 81 void _internal_flush( future(T) & this ) with(this) { 83 82 while( ! waiters`isEmpty ) { 83 if ( !__handle_waituntil_OR( waiters ) ) // handle special waituntil OR case 84 break; // if handle_OR returns false then waiters is empty so break 84 85 select_node &s = try_pop_front( waiters ); 85 86 86 if ( s.race_flag == 0p ) 87 // poke in result so that woken threads do not need to reacquire any locks 88 // *(((future_node(T) &)s).my_result) = result; 87 if ( s.clause_status == 0p ) // poke in result so that woken threads do not need to reacquire any locks 89 88 copy_T( result, *(((future_node(T) &)s).my_result) ); 90 else if ( !install_select_winner( s, &this ) ) continue;91 89 92 // only unpark if future is not selected 93 // or if it is selected we only unpark if we win the race 94 unpark( s.blocked_thread ); 90 wake_one( waiters, s ); 95 91 } 96 92 } 97 93 98 94 // Fulfil the future, returns whether or not someone was unblocked 99 bool fulfil( future(T) & this, T &val ) with(this) {95 bool fulfil( future(T) & this, T val ) with(this) { 100 96 lock( lock ); 101 97 if( state != FUTURE_EMPTY ) … … 153 149 } 154 150 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 151 bool register_select( future(T) & this, select_node & s ) with(this) { 152 lock( lock ); 153 154 // check if we can complete operation. If so race to establish winner in special OR case 155 if ( !s.park_counter && state != FUTURE_EMPTY ) { 156 if ( !__make_select_node_available( s ) ) { // we didn't win the race so give up on registering 157 unlock( lock ); 158 return false; 159 } 160 } 161 162 // future not ready -> insert select node and return 159 163 if( state == FUTURE_EMPTY ) { 160 164 insert_last( waiters, s ); 161 165 unlock( lock ); 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) { 166 return false; 167 } 168 169 __make_select_node_available( s ); 170 unlock( lock ); 171 return true; 172 } 173 174 bool unregister_select( future(T) & this, select_node & s ) with(this) { 175 if ( ! s`isListed ) return false; 177 176 lock( lock ); 178 177 if ( s`isListed ) remove( s ); 179 178 unlock( lock ); 179 return false; 180 180 } 181 181 182 bool on_selected( future(T) & this, select_node & node ) { return true; } 182 183 } 183 184 } … … 186 187 // These futures below do not support select statements so they may not be as useful as 'future' 187 188 // however the 'single_future' is cheap and cheerful and is most likely more performant than 'future' 188 // since it uses raw atomics and no locks afaik189 // since it uses raw atomics and no locks 189 190 // 190 191 // 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.