source: libcfa/src/concurrency/cofor.hfa@ f1149ac

Last change on this file since f1149ac was 0da9475, checked in by caparson <caparson@…>, 22 months ago

fixed bug where cofor runner could derefence a null pointer

  • Property mode set to 100644
File size: 2.4 KB
Line 
1#include <thread.hfa>
2#include <locks.hfa>
3#include <list.hfa>
4
5//////////////////////////////////////////////////////////////////////////////////////////
6// cofor ( uC++ COFOR )
7typedef void (*__cofor_body_t)( ssize_t );
8
9void __Cofor__( ssize_t low, ssize_t high, __cofor_body_t loop_body );
10
11#define COFOR( lidname, low, high, loopbody ) \
12 { \
13 void __CFA_loopLambda__( ssize_t lidname ) { \
14 loopbody \
15 } \
16 __Cofor__( low, high, __CFA_loopLambda__ ); \
17 }
18
19struct runner_node {
20 void * value;
21 inline dlink(runner_node);
22};
23P9_EMBEDDED( runner_node, dlink(runner_node) )
24
25thread cofor_runner {
26 go_mutex mutex_lock; // MX lock
27 dlist( runner_node ) items;
28 void (*func)(void *);
29 volatile bool done;
30};
31
32void ?{}( cofor_runner & this ) { this.done = false; }
33
34void main( cofor_runner & this ) with(this) {
35 while ( !done || !items`isEmpty ) {
36 lock( mutex_lock );
37 runner_node * node = &try_pop_front( items );
38 unlock( mutex_lock );
39 if ( !node )
40 continue;
41 func( node->value );
42 free( node->value );
43 free( node );
44 }
45}
46
47void start_runners( cofor_runner * thds, unsigned nprocs, void (*func)(void *) ) {
48 for ( i; nprocs ) {
49 thds[i].func = func;
50 }
51}
52
53void end_runners( cofor_runner * thds, unsigned nprocs ) {
54 for ( i; nprocs ) {
55 thds[i].done = true;
56 }
57}
58
59void send_work( cofor_runner * thds, unsigned nprocs, unsigned & curr_proc, void * value ) {
60 runner_node * node = malloc();
61 (*node){};
62 node->value = value;
63 lock( thds[curr_proc].mutex_lock );
64 insert_last( thds[curr_proc].items, *node );
65 unlock( thds[curr_proc].mutex_lock );
66 curr_proc = ( curr_proc + 1 ) % nprocs;
67}
68
69//////////////////////////////////////////////////////////////////////////////////////////
70// corun
71
72//
73typedef void (*__CFA_corun_lambda_t)( void );
74
75// used to run a corun statement in parallel
76thread co_runner {
77 __CFA_corun_lambda_t body;
78};
79
80// wraps a co_runner to provide RAII deallocation
81struct runner_block {
82 co_runner * runner;
83};
84static inline void ?{}( co_runner & this, __CFA_corun_lambda_t body ) { this.body = body; }
85
86void main( co_runner & this ) with( this ) { body(); }
87
88static inline void ?{}( runner_block & this ) {}
89static inline void ?{}( runner_block & this, __CFA_corun_lambda_t body ) {
90 (*(this.runner = malloc())){ body };
91}
92
93static inline void ^?{}( runner_block & this ) {
94 delete( this.runner );
95}
Note: See TracBrowser for help on using the repository browser.