source: libcfa/src/concurrency/cofor.hfa

Last change on this file was 0da9475, checked in by caparson <caparson@…>, 5 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.