diff --git a/libs/pbd/pbd/pthread_utils.h b/libs/pbd/pbd/pthread_utils.h index 47f8357b9e..f17c5d59f6 100644 --- a/libs/pbd/pbd/pthread_utils.h +++ b/libs/pbd/pbd/pthread_utils.h @@ -93,6 +93,26 @@ LIBPBD_API bool pbd_mach_set_realtime_policy (pthread_t thread_id, double period namespace PBD { LIBPBD_API extern void notify_event_loops_about_thread_creation (pthread_t, const std::string&, int requests = 256); LIBPBD_API extern PBD::Signal3 ThreadCreatedWithRequestSize; + + class LIBPBD_API Thread { + public: + static Thread* create (boost::function const&, std::string const& name = ""); + static Thread* self (); + void join (); + bool caller_is_self () const; + + private: + Thread (); + Thread (boost::function const&, std::string const& name = ""); + Thread (Thread const&); /* precent copy-construction */ + + static void* _run (void*); + + pthread_t _t; + std::string _name; + boost::function _slot; + bool _joinable; + }; } /* pthread-w32 does not support realtime scheduling diff --git a/libs/pbd/pthread_utils.cc b/libs/pbd/pthread_utils.cc index f4662c7fd8..5b1c82ae02 100644 --- a/libs/pbd/pthread_utils.cc +++ b/libs/pbd/pthread_utils.cc @@ -28,6 +28,7 @@ #include #endif +#include "pbd/failed_constructor.h" #include "pbd/pthread_utils.h" #ifdef COMPILER_MSVC @@ -436,3 +437,65 @@ pbd_mach_set_realtime_policy (pthread_t thread_id, double period_ns, bool main) #endif return false; // OK } + +PBD::Thread* +PBD::Thread::create (boost::function const& slot, std::string const& name) +{ + try { + return new PBD::Thread (slot, name); + } catch (...) { + return 0; + } +} + +PBD::Thread* +PBD::Thread::self () +{ + return new PBD::Thread (); +} + +PBD::Thread::Thread () + : _name ("Main") + , _joinable (false) +{ + _t = pthread_self (); +} + +PBD::Thread::Thread (boost::function const& slot, std::string const& name) + : _name (name) + , _slot (slot) + , _joinable (true) +{ + pthread_attr_t thread_attributes; + pthread_attr_init (&thread_attributes); + + if (pthread_create (&_t, &thread_attributes, _run, this)) { + throw failed_constructor (); + } +} + +void* +PBD::Thread::_run (void* arg) { + PBD::Thread* self = static_cast(arg); + if (!self->_name.empty ()) { + pthread_set_name (self->_name.c_str ()); + } + self->_slot (); + + pthread_exit (0); + return 0; +} + +void +PBD::Thread::join () +{ + if (_joinable) { + pthread_join (_t, NULL); + } +} + +bool +PBD::Thread::caller_is_self () const +{ + return pthread_equal (_t, pthread_self ()) != 0; +}