/* thread.h */ /* * Copyright information and license terms for this software can be * found in the file LICENSE that is included with the distribution */ /** * @author mrk */ #ifndef THREAD_H #define THREAD_H #include #include #include #if __cplusplus>=201103L #include #endif #include #include #include #include namespace epics { namespace pvData { enum ThreadPriority { lowestPriority =epicsThreadPriorityLow, lowerPriority =epicsThreadPriorityLow + 15, lowPriority =epicsThreadPriorityMedium - 15, middlePriority =epicsThreadPriorityMedium, highPriority =epicsThreadPriorityMedium + 15, higherPriority =epicsThreadPriorityHigh - 15, highestPriority =epicsThreadPriorityHigh }; class Thread; typedef std::tr1::shared_ptr ThreadPtr; typedef std::tr1::shared_ptr EpicsThreadPtr; typedef epicsThreadRunable Runnable; namespace detail { template struct MethRunner : public epicsThreadRunable { typedef void(C::*fn_t)(); fn_t fn; C* inst; MethRunner(C* i, fn_t f) :fn(f), inst(i) {} virtual ~MethRunner() {} virtual void run() { (inst->*fn)(); } }; } // namespace detail /** * @brief C++ wrapper for epicsThread from EPICS base. * */ class epicsShareClass Thread : public epicsThread { EPICS_NOT_COPYABLE(Thread) public: /** @brief Holds all the configuration necessary to launch a @class Thread * * The defaults may be used except for the runnable, which must be given * either in the constructor, or the @method run() method. * * @note Instances of @class Config may not be reused. * * Defaults: * name: "" * priority: epicsThreadPriorityLow (aka epics::pvData::lowestPriority) * stack size: epicsThreadStackSmall * auto start: true * runner: nil (must be set explictly) * @code stuct bar { void meth(); ... } X; // with a static thread name Thread foo(Thread::Config(&X, &bar::meth) .name("example") .prio(epicsThreadPriorityHigh)); // with a constructed thread name Thread foo(Thread::Config(&X, &bar::meth) .prio(epicsThreadPriorityHigh) <<"example"<<1); @endcode */ class epicsShareClass Config { unsigned int p_prio, p_stack; std::ostringstream p_strm; bool p_autostart; Runnable *p_runner; typedef epics::auto_ptr p_owned_runner_t; p_owned_runner_t p_owned_runner; friend class Thread; Runnable& x_getrunner(); void x_setdefault(); public: Config(); Config(Runnable *r); Config(void(*fn)(void*), void *ptr); template Config(C* inst, void(C::*meth)()) {this->x_setdefault();this->run(inst, meth);} #if __cplusplus>=201103L Config(std::function&& fn); #endif Config& name(const std::string& n); Config& prio(unsigned int p); Config& stack(epicsThreadStackSizeClass s); Config& autostart(bool a); //! Thread will execute Runnable::run() Config& run(Runnable* r); //! Thread will execute (*fn)(ptr) Config& run(void(*fn)(void*), void *ptr); //! Thread will execute (inst->*meth)() template Config& run(C* inst, void(C::*meth)()) { this->p_owned_runner.reset(new detail::MethRunner(inst, meth)); this->p_runner = this->p_owned_runner.get(); return *this; } #if __cplusplus>=201103L Config& run(std::function&& fn); #endif //! Append to thread name string. Argument must be understood by std::ostream::operator<< template Config& operator<<(T x) { this->p_strm<