Changes in / [0aef549:8421d3f]
- Files:
-
- 10 edited
-
doc/theses/colby_parsons_MMAth/text/channels.tex (modified) (2 diffs)
-
libcfa/src/bits/weakso_locks.cfa (modified) (1 diff)
-
libcfa/src/bits/weakso_locks.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/channel.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/future.hfa (modified) (2 diffs)
-
libcfa/src/concurrency/locks.cfa (modified) (1 diff)
-
libcfa/src/concurrency/locks.hfa (modified) (3 diffs)
-
libcfa/src/concurrency/select.cfa (modified) (1 diff)
-
libcfa/src/concurrency/select.hfa (modified) (2 diffs)
-
src/Concurrency/Waituntil.cpp (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/colby_parsons_MMAth/text/channels.tex
r0aef549 r8421d3f 19 19 It was the popularity of Go channels that lead to their implementation in \CFA. 20 20 Neither Go nor \CFA channels have the restrictions of the early channel-based concurrent systems. 21 22 Other popular languages and libraries that provide channels include C++ Boost~\cite{boost:channel}, Rust~\cite{rust:channel}, Haskell~\cite{haskell:channel}, and OCaml~\cite{ocaml:channel}.23 Boost channels only support asynchronous (non-blocking) operations, and Rust channels are limited to only having one consumer per channel.24 Haskell channels are unbounded in size, and OCaml channels are zero-size.25 These restrictions in Haskell and OCaml are likely due to their functional approach, which results in them both using a list as the underlying data structure for their channel.26 These languages and libraries are not discussed further, as their channel implementation is not comparable to the bounded-buffer style channels present in Go and \CFA.27 21 28 22 \section{Producer-Consumer Problem} … … 237 231 \begin{lrbox}{\myboxB} 238 232 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 239 <<<<<<< HEAD240 var cons_done, prod_done bool = false, false;241 var prodJoin chan int = make(chan int)242 var consJoin chan int = make(chan int)243 244 func consumer( channel chan uint64 ) {245 for {246 if cons_done { break }247 <-channel248 }249 consJoin <- 0 // synch with main thd250 }251 =======252 233 channel( size_t ) chan{ 128 }; 253 234 thread Consumer {}; 254 235 thread Producer {}; 255 >>>>>>> 8421d3fad6379460563c3a8922889a72c4d868fe256 236 257 237 void main( Producer & this ) { -
libcfa/src/bits/weakso_locks.cfa
r0aef549 r8421d3f 30 30 bool register_select( blocking_lock & this, select_node & node ) { return false; } 31 31 bool unregister_select( blocking_lock & this, select_node & node ) { return false; } 32 void on_selected( blocking_lock & this, select_node & node ) {}32 bool on_selected( blocking_lock & this, select_node & node ) { return true; } 33 33 -
libcfa/src/bits/weakso_locks.hfa
r0aef549 r8421d3f 62 62 bool register_select( blocking_lock & this, select_node & node ) OPTIONAL_THREAD; 63 63 bool unregister_select( blocking_lock & this, select_node & node ) OPTIONAL_THREAD; 64 voidon_selected( blocking_lock & this, select_node & node ) OPTIONAL_THREAD;64 bool on_selected( blocking_lock & this, select_node & node ) OPTIONAL_THREAD; 65 65 66 66 //---------- … … 80 80 static inline bool register_select( multiple_acquisition_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); } 81 81 static inline bool unregister_select( multiple_acquisition_lock & this, select_node & node ) { return unregister_select( (blocking_lock &)this, node ); } 82 static inline void on_selected( multiple_acquisition_lock & this, select_node & node ) {on_selected( (blocking_lock &)this, node ); }82 static inline bool on_selected( multiple_acquisition_lock & this, select_node & node ) { return on_selected( (blocking_lock &)this, node ); } -
libcfa/src/concurrency/channel.hfa
r0aef549 r8421d3f 441 441 } 442 442 static inline bool unregister_select( chan_read(T) & this, select_node & node ) { return unregister_chan( this.chan, node ); } 443 static inline voidon_selected( chan_read(T) & this, select_node & node ) with(this) {443 static inline bool on_selected( chan_read(T) & this, select_node & node ) with(this) { 444 444 if ( node.extra == 0p ) // check if woken up due to closed channel 445 445 __closed_remove( chan, ret ); 446 446 // This is only reachable if not closed or closed exception was handled 447 return true; 447 448 } 448 449 … … 533 534 static inline bool unregister_select( chan_write(T) & this, select_node & node ) { return unregister_chan( this.chan, node ); } 534 535 535 static inline voidon_selected( chan_write(T) & this, select_node & node ) with(this) {536 static inline bool on_selected( chan_write(T) & this, select_node & node ) with(this) { 536 537 if ( node.extra == 0p ) // check if woken up due to closed channel 537 538 __closed_insert( chan, elem ); 538 539 539 540 // This is only reachable if not closed or closed exception was handled 541 return true; 540 542 } 541 543 -
libcfa/src/concurrency/future.hfa
r0aef549 r8421d3f 70 70 // check if the future is available 71 71 // currently no mutual exclusion because I can't see when you need this call to be synchronous or protected 72 bool available( future(T) & this ) { return __atomic_load_n( &this.state, __ATOMIC_RELAXED ); }72 bool available( future(T) & this ) { return this.state; } 73 73 74 74 … … 180 180 } 181 181 182 void on_selected( future(T) & this, select_node & node ) {}182 bool on_selected( future(T) & this, select_node & node ) { return true; } 183 183 } 184 184 } 185 185 186 186 //-------------------------------------------------------------------------------------------------------- 187 // These futures below do not support select statements so they may not have as many featuresas 'future'187 // These futures below do not support select statements so they may not be as useful as 'future' 188 188 // however the 'single_future' is cheap and cheerful and is most likely more performant than 'future' 189 189 // since it uses raw atomics and no locks -
libcfa/src/concurrency/locks.cfa
r0aef549 r8421d3f 239 239 } 240 240 241 void on_selected( blocking_lock & this, select_node & node ) {}241 bool on_selected( blocking_lock & this, select_node & node ) { return true; } 242 242 243 243 //----------------------------------------------------------------------------- -
libcfa/src/concurrency/locks.hfa
r0aef549 r8421d3f 114 114 static inline bool register_select( single_acquisition_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); } 115 115 static inline bool unregister_select( single_acquisition_lock & this, select_node & node ) { return unregister_select( (blocking_lock &)this, node ); } 116 static inline void on_selected( single_acquisition_lock & this, select_node & node ) {on_selected( (blocking_lock &)this, node ); }116 static inline bool on_selected( single_acquisition_lock & this, select_node & node ) { return on_selected( (blocking_lock &)this, node ); } 117 117 118 118 //---------- … … 131 131 static inline bool register_select( owner_lock & this, select_node & node ) { return register_select( (blocking_lock &)this, node ); } 132 132 static inline bool unregister_select( owner_lock & this, select_node & node ) { return unregister_select( (blocking_lock &)this, node ); } 133 static inline void on_selected( owner_lock & this, select_node & node ) {on_selected( (blocking_lock &)this, node ); }133 static inline bool on_selected( owner_lock & this, select_node & node ) { return on_selected( (blocking_lock &)this, node ); } 134 134 135 135 //----------------------------------------------------------------------------- … … 621 621 } 622 622 623 static inline void on_selected( simple_owner_lock & this, select_node & node ) {}623 static inline bool on_selected( simple_owner_lock & this, select_node & node ) { return true; } 624 624 625 625 -
libcfa/src/concurrency/select.cfa
r0aef549 r8421d3f 49 49 return false; 50 50 } 51 void on_selected( select_timeout_node & this, select_node & node ) {}51 bool on_selected( select_timeout_node & this, select_node & node ) { return true; } 52 52 53 53 // Gateway routine to wait on duration -
libcfa/src/concurrency/select.hfa
r0aef549 r8421d3f 91 91 // For unregistering a select stmt on a selectable concurrency primitive 92 92 // If true is returned then the corresponding code block is run (only in non-special OR case and only if node status is not RUN) 93 bool unregister_select( T &, select_node & );93 bool unregister_select( T &, select_node & ); 94 94 95 95 // This routine is run on the selecting thread prior to executing the statement corresponding to the select_node 96 96 // passed as an arg to this routine 97 97 // If on_selected returns false, the statement is not run, if it returns true it is run. 98 voidon_selected( T &, select_node & );98 bool on_selected( T &, select_node & ); 99 99 }; 100 100 … … 208 208 bool register_select( select_timeout_node & this, select_node & node ); 209 209 bool unregister_select( select_timeout_node & this, select_node & node ); 210 voidon_selected( select_timeout_node & this, select_node & node );210 bool on_selected( select_timeout_node & this, select_node & node ); 211 211 212 212 // Gateway routines to waituntil on duration -
src/Concurrency/Waituntil.cpp
r0aef549 r8421d3f 95 95 case 0: 96 96 try { 97 on_selected( A, clause1 );97 if (on_selected( A, clause1 )) 98 98 doA(); 99 99 } … … 122 122 // the unregister and on_selected calls are needed to support primitives where the acquire has side effects 123 123 // so the corresponding block MUST be run for those primitives to not lose state (example is channels) 124 if ( !has_run(clause_statuses[0]) && whenA && unregister_select(A, clause1) ) 125 on_selected( A, clause1 ) 124 if ( ! has_run(clause_statuses[0]) && whenA && unregister_select(A, clause1) && on_selected( A, clause1 ) ) 126 125 doA(); 127 126 ... repeat if above for B and C ... … … 620 619 621 620 // Generates: 622 /* on_selected( target_1, node_1 );... corresponding body of target_1 ...621 /* if ( on_selected( target_1, node_1 )) ... corresponding body of target_1 ... 623 622 */ 624 623 CompoundStmt * GenerateWaitUntilCore::genStmtBlock( const WhenClause * clause, const ClauseData * data ) { … … 626 625 return new CompoundStmt( cLoc, 627 626 { 628 new ExprStmt( cLoc, 629 genSelectTraitCall( clause, data, "on_selected" ) 630 ), 631 ast::deepCopy( clause->stmt ) 627 new IfStmt( cLoc, 628 genSelectTraitCall( clause, data, "on_selected" ), 629 new CompoundStmt( cLoc, 630 { 631 ast::deepCopy( clause->stmt ) 632 } 633 ) 634 ) 632 635 } 633 636 ); … … 641 644 case 0: 642 645 try { 643 on_selected( target1, clause1 );644 dotarget1stmt();646 if (on_selected( target1, clause1 )) 647 dotarget1stmt(); 645 648 } 646 649 finally { clause_statuses[i] = __SELECT_RUN; unregister_select(target1, clause1); } … … 661 664 case 0: 662 665 try { 663 on_selected( target1, clause1 );664 dotarget1stmt();666 if (on_selected( target1, clause1 )) 667 dotarget1stmt(); 665 668 } 666 669 finally { clause_statuses[i] = __SELECT_RUN; unregister_select(target1, clause1); } … … 1017 1020 ifCond, 1018 1021 genStmtBlock( stmt->clauses.at(idx), data.at(idx) ), 1022 // ast::deepCopy( stmt->clauses.at(idx)->stmt ), 1019 1023 recursiveOrIfGen( stmt, data, idx + 1, elseWhenName ) 1020 1024 )
Note:
See TracChangeset
for help on using the changeset viewer.