-
Notifications
You must be signed in to change notification settings - Fork 4
/
thread-split.cpp
96 lines (75 loc) · 1.71 KB
/
thread-split.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include "os.h"
namespace {
//force some year-old C code to compile properly as C++ - I decided to switch long ago but still haven't finished.
#define this This
//TODO: there is no procedure for destroying threads
struct threadpool {
mutex lock;
multievent* wake;
multievent* started;
uint32_t numthreads;
uint32_t numidle;
//these vary between each piece of work
function<void(unsigned int id)> work;
uint32_t id;
multievent* done;
};
static struct threadpool * pool;
void threadproc(struct threadpool * this)
{
while (true)
{
this->wake->wait();
lock_decr(&this->numidle);
function<void(unsigned int id)> work = this->work;
unsigned int id = lock_incr(&this->id);
multievent* done = this->done;
this->started->signal();
work(id);
done->signal();
lock_incr(&this->numidle);
}
}
struct threadpool* pool_create()
{
struct threadpool * pool = new threadpool;
pool->wake=new multievent();
pool->started=new multievent();
pool->numthreads=0;
pool->numidle=0;
return pool;
}
void pool_delete(struct threadpool* pool)
{
delete pool->wake;
delete pool->started;
delete pool;
}
}
void thread_split(unsigned int count, function<void(unsigned int id)> work)
{
if (!count) return;
if (count==1)
{
work(0);
return;
}
struct threadpool * this = thread_once_undo(&pool, bind(pool_create), bind(pool_delete));
this->lock.lock();
multievent* done=new multievent();
this->work=work;
this->id=1;
this->done=done;
while (lock_read(&this->numidle) < count-1)
{
this->numthreads++;
lock_incr(&this->numidle);
thread_create(bind_this(threadproc));
}
this->wake->signal(count-1);
this->started->wait(count-1);
this->lock.unlock();
work(0);
done->wait(count-1);
delete done;
}