/*! \file pithread.h * \brief Thread * * This file declare thread class and some wait functions */ /* PIP - Platform Independent Primitives Thread Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef PITHREAD_H #define PITHREAD_H #include #include "pimutex.h" #include "piobject.h" typedef void (*ThreadFunc)(void * ); class PIP_EXPORT PIThread: public PIObject { PIOBJECT(PIThread) public: //! Contructs thread with custom data "data", external function "func" and main cycle delay "timer_delay". PIThread(void * data, ThreadFunc func, bool startNow = false, int timer_delay = -1); //! Contructs thread with main cycle delay "timer_delay". PIThread(bool startNow = false, int timer_delay = -1); virtual ~PIThread(); #ifdef DOXYGEN //! Priority of thread enum Priority {piHighest /** Highest */, piHigh /** High */, piNormal /** Normal, default */, piLow /** Low */, piLowerst /** Lowest */ }; #else # ifdef QNX enum Priority {piHighest = 12, piHigh = 11, piNormal = 10, piLow = 9, piLowerst = 8 }; # else enum Priority {piHighest = -2, piHigh = -1, piNormal = 0, piLow = 1, piLowerst = 2 }; # endif #endif EVENT_HANDLER0(bool, start) {return start(-1);} EVENT_HANDLER1(bool, start, int, timer_delay); EVENT_HANDLER1(bool, start, ThreadFunc, func) {ret_func = func; return start(-1);} EVENT_HANDLER2(bool, start, ThreadFunc, func, int, timer_delay) {ret_func = func; return start(timer_delay);} EVENT_HANDLER0(bool, startOnce); EVENT_HANDLER1(bool, startOnce, ThreadFunc, func) {ret_func = func; return startOnce();} EVENT_HANDLER0(void, stop) {stop(false);} EVENT_HANDLER1(void, stop, bool, wait) {terminating = true; if (wait) waitForFinish();} EVENT_HANDLER0(void, terminate); //! \brief Set common data passed to external function void setData(void * d) {data_ = d;} //! \brief Set external function that will be executed after every \a run() void setSlot(ThreadFunc func) {ret_func = func;} //! \brief Set priority of thread void setPriority(PIThread::Priority prior); //! \brief Return priority of thread PIThread::Priority priority() const {return priority_;} //! \brief Return \c true if thread is running bool isRunning() const {return running;} bool isStopping() const {return running && terminating;} EVENT_HANDLER0(bool, waitForStart) {return waitForStart(-1);} EVENT_HANDLER1(bool, waitForStart, int, timeout_msecs); EVENT_HANDLER0(bool, waitForFinish) {return waitForFinish(-1);} EVENT_HANDLER1(bool, waitForFinish, int, timeout_msecs); //! \brief Set necessity of lock every \a run with internal mutex void needLockRun(bool need) {lockRun = need;} EVENT_HANDLER0(void, lock) {mutex_.lock();} EVENT_HANDLER0(void, unlock) {mutex_.unlock();} //! \brief Return internal mutex PIMutex & mutex() {return mutex_;} EVENT(started) EVENT(stopped) //! \handlers //! \{ /** \fn bool start(int timer_delay = -1) * \brief Start thread * \details Start execution of \a run() in internal loop with * "timer_delay" delay in milliseconds. If "timer_delay" <= 0 * there is no delay in loop. Thread also exec external function * set by \a setSlot() if it`s not null * * \return \c false if thread already started or can`t start thread */ /** \fn bool start(ThreadFunc func, int timer_delay = -1) * \brief Start thread * \details Overloaded function. Set external function "func" before start * * \return \c false if thread already started or can`t start thread */ /** \fn bool startOnce() * \brief Start thread without internal loop * \details Start execution of \a run() once. Thread also exec * external function set by \a setSlot() if it`s not null * * \return \c false if thread already started or can`t start thread */ /** \fn bool startOnce(ThreadFunc func) * \brief Start thread without internal loop * \details Overloaded function. Set external function "func" before start * * \return \c false if thread already started or can`t start thread */ /** \fn void stop(bool wait = false) * \brief Stop thread * \details Stop execution of thread and wait for it finish * if "wait" is \c true. This function can block for infinite * time if "wait" is \c true and any of thread function is * busy forever */ /** \fn void terminate() * \brief Strongly stop thread * \details Stop execution of thread immediately */ /** \fn bool waitForStart(int timeout_msecs = -1) * \brief Wait for thread start * \details This function block until thread finish for "timeout_msecs" * or forever if "timeout_msecs" < 0 * * \return \c false if timeout is exceeded */ /** \fn bool waitForFinish(int timeout_msecs = -1) * \brief Wait for thread finish * \details This function block until thread start for "timeout_msecs" * or forever if "timeout_msecs" < 0 * * \return \c false if timeout is exceeded */ //! \fn void lock() //! \brief Lock internal mutex //! \fn void unlock() //! \brief Unlock internal mutex //! \} //! \events //! \{ //! \fn void started() //! \brief Raise on thread start //! \fn void stopped() //! \brief Raise on thread stop //! \} protected: static void * thread_function(void * t); static void * thread_function_once(void * t); //! Function executed once at the start of thread. virtual void begin() {;} //! Function executed at every "timer_delay" msecs until thread was stopped. virtual void run() {;} //! Function executed once at the end of thread. virtual void end() {;} volatile bool terminating, running, lockRun; int timer, policy; void * data_; PIMutex mutex_; PIThread::Priority priority_; ThreadFunc ret_func; #ifndef WINDOWS pthread_t thread; sched_param sparam; #else void * thread; #endif }; #endif // PITHREAD_H