#include #include #include #include // PRIO_PROCESS #undef DEBUG //#define DEBUG // ---------------------------------------------------------------------- // // Constructor // // Starts the derived thread if you don't specify false. // MThread::MThread(bool start, int prio) : fIsRunning(false), fIsDetached(false), fThread(NULL), fReturn(NULL) { #ifdef DEBUG cout << "MThread::MThread" << endl; #endif if (!start) return; SetPriority(prio); Start(); } // ---------------------------------------------------------------------- // // Destructor // // Stops the derived thread if it is still running. // MThread::~MThread() { #ifdef DEBUG cout << "~MThread::MThread" << endl; #endif Stop(); } // ---------------------------------------------------------------------- // // Detach the derived thread. This means, that if the thread ends the // needed resources (eg. for storing the return code) are freed. // In other word you cannot get any value back from the Thread. // void MThread::Detach() { if (fIsRunning) pthread_detach(*fThread); fIsDetached = true; } // ---------------------------------------------------------------------- // // Sets the priority of the thread. // -20 highest priority // 0 standard // +20 lowest priority // This can only be done before the thread is started. // bool MThread::SetPriority(int prio) { if (fIsRunning) return false; fPriority = prio; return true; } // ---------------------------------------------------------------------- // // Now we are back in a class instance, but running in new thread. // All class members can be accessed like before. // Set the flag for a running thread. Check if the thread should get // detached. Set the priority of the thread. Now reset the stop flag and // execute the thread. After the thread stopped it's execution reset the // running flag and exit. // void *MThread::RunThread() { fIsRunning = true; if (fIsDetached) pthread_detach(pthread_self()); setpriority(PRIO_PROCESS, 0, fPriority); //lowest priority fStop = false; #ifdef DEBUG cout << "MThread::RunThread" << endl; #endif void *rc = Thread(); #ifdef DEBUG cout << "MThread::RunThread...done." << endl; #endif fIsRunning = false; return rc; } // ---------------------------------------------------------------------- // // Get the Instance back from the thread argument and call the // RunThread member function, which handles all MThread bspecific stuff. // void *MThread::MapThread(void *arg) { MThread *thread = (MThread*)arg; #ifdef DEBUG cout << "MThread::MapThread" << endl; #endif return thread->RunThread(); } // ---------------------------------------------------------------------- // // A thread is created and started (MapThread). // As an argument the actual instance is used. // void MThread::Start() { fThread = new pthread_t; pthread_create(fThread, NULL, MapThread, this); } // ---------------------------------------------------------------------- // // Check if a thread is existing and running. // If the thread is detached, cancel the thread. Otherwise set the stop // flag and wait for the thread to exit. // void MThread::Stop() { #ifdef DEBUG cout << "MThread::Stop: fThread=" << fThread << ", fIsRunning=" << (int)fIsRunning << endl; #endif if (!fThread || !fIsRunning) return; if (fIsDetached) { #ifdef DEBUG cout << "Stopping detached thread..." << flush; #endif pthread_cancel(*fThread); fIsRunning = false; } else { #ifdef DEBUG cout << "Stopping thread..." << flush; #endif fStop = true; pthread_join(*fThread, &fReturn); } #ifdef DEBUG cout << "done." << endl; #endif delete fThread; fThread = NULL; #ifdef DEBUG cout << "MThread::Stop() done." << endl; #endif }