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
|
#include "stdafx.h"
#include "ThreadGroup.h"
#include "Thread.h"
namespace os {
ThreadGroup::ThreadGroup() : data(new ThreadGroupData()) {}
ThreadGroup::ThreadGroup(Callback start, Callback end) : data(new ThreadGroupData(start, end)) {}
ThreadGroup::ThreadGroup(const ThreadGroup &o) : data(o.data) {
data->addRef();
}
ThreadGroup::~ThreadGroup() {
data->release();
}
ThreadGroup &ThreadGroup::operator =(const ThreadGroup &o) {
data->release();
data = o.data;
data->addRef();
return *this;
}
vector<Thread> ThreadGroup::threads() const {
return data->threads();
}
void ThreadGroup::join() {
data->join();
}
ThreadGroupData::ThreadGroupData() : references(1), attached(0), sema(0) {}
ThreadGroupData::ThreadGroupData(ThreadGroup::Callback start, ThreadGroup::Callback stop)
: references(1), attached(0), sema(0), start(start), stop(stop) {}
ThreadGroupData::~ThreadGroupData() {}
void ThreadGroupData::threadStarted(ThreadData *data) {
atomicIncrement(attached);
start();
util::Lock::L z(runningLock);
running.insert(data);
}
bool ThreadGroupData::threadUnreachable(ThreadData *data) {
util::Lock::L z(runningLock);
// We handed out another reference. Abort!
if (atomicRead(data->references) > 0)
return false;
running.erase(data);
return true;
}
void ThreadGroupData::threadTerminated() {
stop();
sema.up();
// TODO: Perhaps we shall decrease 'attached' at some time to avoid overflow?
}
vector<Thread> ThreadGroupData::threads() {
vector<Thread> result;
util::Lock::L z(runningLock);
for (InlineSet<ThreadData>::iterator i = running.begin(); i != running.end(); ++i) {
result.push_back(Thread(i));
}
return result;
}
void ThreadGroupData::join() {
// Wait for all threads in turn.
while (atomicRead(attached) > 0) {
atomicDecrement(attached);
sema.down();
}
}
}
|