summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--includes/Threads.h49
-rw-r--r--src/Threads.cc45
3 files changed, 95 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 9eb4d53..935a54f 100644
--- a/Makefile
+++ b/Makefile
@@ -148,6 +148,7 @@ TEST_SOURCES = \
test-Sanity.cc \
test-String.cc \
test-Tasks.cc \
+test-Threads.cc \
test-Handles.cc \
LIB = libBalau.a
diff --git a/includes/Threads.h b/includes/Threads.h
index 5a4ef61..2347a84 100644
--- a/includes/Threads.h
+++ b/includes/Threads.h
@@ -1,9 +1,13 @@
#pragma once
+#include <queue>
#include <pthread.h>
namespace Balau {
+template<class T>
+class Queue;
+
class Lock {
public:
Lock();
@@ -12,6 +16,51 @@ class Lock {
void leave() { pthread_mutex_unlock(&m_lock); }
private:
pthread_mutex_t m_lock;
+ template<class T>
+ friend class Queue;
+};
+
+class ThreadHelper;
+
+class Thread {
+ public:
+ virtual ~Thread();
+ void threadStart();
+ void * join();
+ protected:
+ Thread() : m_joined(false) { }
+ virtual void * proc() = 0;
+ private:
+ pthread_t m_thread;
+ bool m_joined;
+
+ friend class ThreadHelper;
+};
+
+template<class T>
+class Queue {
+ public:
+ Queue() { pthread_cond_init(&m_cond, NULL); }
+ ~Queue() { pthread_cond_destroy(&m_cond); }
+ void push(T & t) {
+ m_lock.enter();
+ m_queue.push(t);
+ pthread_cond_signal(&m_cond);
+ m_lock.leave();
+ }
+ T pop() {
+ m_lock.enter();
+ if (m_queue.size() == 0)
+ pthread_cond_wait(&m_cond, &m_lock.m_lock);
+ T t = m_queue.front();
+ m_queue.pop();
+ m_lock.leave();
+ return t;
+ }
+ private:
+ std::queue<T> m_queue;
+ Lock m_lock;
+ pthread_cond_t m_cond;
};
};
diff --git a/src/Threads.cc b/src/Threads.cc
index fa3f0f3..5f07040 100644
--- a/src/Threads.cc
+++ b/src/Threads.cc
@@ -1,9 +1,20 @@
#include "Exceptions.h"
#include "Threads.h"
+#include "Local.h"
+
+namespace Balau {
+
+class ThreadHelper {
+ public:
+ static void * threadProc(void * arg);
+};
+
+}
Balau::Lock::Lock() {
int r;
pthread_mutexattr_t attr;
+
r = pthread_mutexattr_init(&attr);
Assert(r == 0);
r = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
@@ -11,3 +22,37 @@ Balau::Lock::Lock() {
r = pthread_mutex_init(&m_lock, &attr);
Assert(r == 0);
}
+
+void * Balau::ThreadHelper::threadProc(void * arg) {
+ void * tls = g_tlsManager->createTLS();
+ g_tlsManager->setTLS(tls);
+ Balau::Thread * thread = reinterpret_cast<Balau::Thread *>(arg);
+ void * r = thread->proc();
+ free(tls);
+ return r;
+}
+
+Balau::Thread::~Thread() {
+ join();
+}
+
+void * Balau::Thread::join() {
+ void * r = NULL;
+ if (!m_joined) {
+ m_joined = true;
+ pthread_join(m_thread, &r);
+ }
+ return r;
+}
+
+void Balau::Thread::threadStart() {
+ pthread_attr_t attr;
+ int r;
+
+ r = pthread_attr_init(&attr);
+ Assert(r == 0);
+ r = pthread_create(&m_thread, &attr, Balau::ThreadHelper::threadProc, this);
+ Assert(r == 0);
+ r = pthread_attr_destroy(&attr);
+ Assert(r == 0);
+}