From 4014067a1668d94000b059d72832482a06cf8369 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 6 Jan 2007 19:39:56 +0000 Subject: Added ability to get Raul Thread for current calling context. Strong threading assertions. Flowcanvas port removal fixes. Patch port destruction. Code cleanups, bug fixes. git-svn-id: http://svn.drobilla.net/lad/raul@234 a436a847-0d15-0410-975c-d299462d15a1 --- raul/Thread.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 5 deletions(-) (limited to 'raul/Thread.h') diff --git a/raul/Thread.h b/raul/Thread.h index b7fd9c4..2a7a321 100644 --- a/raul/Thread.h +++ b/raul/Thread.h @@ -28,17 +28,34 @@ * Extend this and override the _run method to easily create a thread * to perform some task. * + * The current Thread can be accessed using the get() method. + * * \ingroup raul */ class Thread : boost::noncopyable { public: - Thread() : _pthread_exists(false) {} - virtual ~Thread() { stop(); } + + static Thread* create(const std::string& name="") + { return new Thread(name); } - void set_name(const std::string& name) { _name = name; } + /** Must be called from thread */ + static Thread* create_for_this_thread(const std::string& name="") + { return new Thread(pthread_self(), name); } + /** Return the calling thread. + * The return value of this should NOT be cached unless the thread is + * explicitly user created with create(). + */ + static Thread& get() { + Thread* this_thread = reinterpret_cast(pthread_getspecific(_thread_key)); + if (!this_thread) + this_thread = new Thread(); // sets thread-specific data + + return *this_thread; + } + /** Launch and start the thread. */ virtual void start() { std::cout << "[" << _name << " Thread] Starting." << std::endl; @@ -78,23 +95,56 @@ public: << strerror(result) << ")" << std::endl; } } - + + const std::string& name() { return _name; } + void set_name(const std::string& name) { _name = name; } + + const unsigned context() { return _context; } + void set_context(unsigned context) { _context = context; } protected: + Thread(const std::string& name="") : _context(0), _name(name), _pthread_exists(false) + { + pthread_once(&_thread_key_once, thread_key_alloc); + } + + /** Must be called from thread */ + Thread(pthread_t thread, const std::string& name="") + : _context(0), _name(name), _pthread_exists(true), _pthread(thread) + { + pthread_once(&_thread_key_once, thread_key_alloc); + pthread_setspecific(_thread_key, this); + } + /** Thread function to execute. * * This is called once on start, and terminated on stop. * Implementations likely want to put some infinite loop here. */ - virtual void _run() = 0; + virtual void _run() {} private: + inline static void* _static_run(void* me) { + pthread_setspecific(_thread_key, me); Thread* myself = (Thread*)me; myself->_run(); return NULL; // and I } + /** Allocate thread-specific data key */ + static void thread_key_alloc() + { + pthread_key_create(&_thread_key, NULL); + } + + /* Key for the thread-specific buffer */ + static pthread_key_t _thread_key; + + /* Once-only initialisation of the key */ + static pthread_once_t _thread_key_once; + + unsigned _context; std::string _name; bool _pthread_exists; pthread_t _pthread; -- cgit v1.2.1