IThread.cpp

00001 /***************************************************************************
00002  *                                                                         *
00003  *   (c) Art Tevs, MPI Informatik Saarbruecken                             *
00004  *       mailto: <tevs@mpi-sb.mpg.de>                                      *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU General Public License as published by  *
00008  *   the Free Software Foundation; either version 2 of the License, or     *
00009  *   (at your option) any later version.                                   *
00010  *                                                                         *
00011  ***************************************************************************/
00012 
00013 
00014 //----------------------------------------------------------------------------------
00015 // Includes
00016 //----------------------------------------------------------------------------------
00017 #include "IThread.h"
00018 #include "EventManager.h"
00019 #include "Log.h"
00020 #include <boost/bind.hpp>
00021 
00022 namespace nrEngine{
00023 
00024         //--------------------------------------------------------------------
00025         IThread::IThread()// : EventActor(std::string("Thread_") + boost::lexical_cast<std::string>(id))
00026         {
00027                 //mThread = NULL;
00028                 mThreadState = THREAD_STOP;
00029         }
00030 
00031         //--------------------------------------------------------------------
00032         IThread::~IThread()
00033         {
00034                 // delete the thread object if it is not empty
00035                 //if (mThread)
00036                 //{
00037                 //      delete mThread;
00038                 //}
00039         }
00040 
00041         //--------------------------------------------------------------------
00042         void IThread::threadStart()
00043         {
00044                 // Check if we have already a thread created
00045                 if (mThread)
00046                 {
00047                         NR_Log(Log::LOG_KERNEL, Log::LL_WARNING, "IThread: the appropriate thread is already running!");
00048                         return;
00049                 }
00050                 NR_Log(Log::LOG_KERNEL, "IThread: Create thread and start it");
00051 
00052                 mThread.reset(new boost::thread(boost::bind(&IThread::run, this)));
00053                 // initialise the attribute
00054                 /*pthread_attr_init(&mThreadAttr);
00055 
00056                 // create the joinable attribute for thsi thread
00057                 pthread_attr_setdetachstate(&mThreadAttr, PTHREAD_CREATE_JOINABLE);
00058 
00059                 // setup thread scheduling attribute
00060                 pthread_attr_setschedpolicy(&mThreadAttr, SCHED_RR);
00061                 
00062                 // now create a thread and let it run
00063                 int res = pthread_create(&mThread, &mThreadAttr, IThread::run, (void *)this);
00064                 if (res){
00065                         NR_Log(Log::LOG_KERNEL, Log::LL_ERROR, "IThread: creation of a thread failed with error code %d", res);
00066                         return;
00067                 }*/
00068                 mThreadState = THREAD_RUNNING;
00069    
00070                 mThreadState = THREAD_RUNNING;
00071                 mThread.reset(new boost::thread(boost::bind(IThread::run, this)));
00072                 
00073         }
00074 
00075         //--------------------------------------------------------------------
00076         void IThread::threadStop()
00077         {
00078                 // change state
00079                 changeState(THREAD_STOP);
00080 
00081                 // join the thread to the main process
00082                 /*pthread_attr_destroy(&mThreadAttr);
00083                 int res = pthread_join(mThread, NULL);
00084                 if (res){
00085                         NR_Log(Log::LOG_KERNEL, Log::LL_ERROR, "IThread: can not join running thread (error code %d)", res);
00086                         return;
00087                 }*/
00088                 mThread->join();
00089         }
00090 
00091         //--------------------------------------------------------------------
00092         void IThread::threadSuspend()
00093         {
00094                 changeState(THREAD_NEXT_SUSPEND);
00095         }
00096 
00097         //--------------------------------------------------------------------
00098         void IThread::threadResume()
00099         {
00100                 changeState(THREAD_NEXT_RESUME);
00101         }
00102 
00103         //--------------------------------------------------------------------
00104         void IThread::changeState(ThreadState newState)
00105         {
00106                 // first lock the mutex and then change the state
00107                 /*try{
00108                         boost::mutex::scoped_lock lock(mMutex);
00109                         mThreadState = newState;
00110                 }catch (boost::lock_error err) {}
00111                 */
00112 
00113                 // lock the mutex change status and unlock it again
00114                 //pthread_mutex_lock(&mMutex);
00115                 mThreadState = newState;
00116                 //pthread_mutex_unlock(&mMutex);
00117                 
00118         }
00119 
00120         //--------------------------------------------------------------------
00121         void IThread::yield(IThread* mythread)
00122         {
00123                 // use pthread to yield the timeslice
00124                 //pthread_yield();
00125                 boost::thread::yield();
00126         }
00127 
00128         //--------------------------------------------------------------------
00129         void IThread::run(void* _mythread)
00130         {
00131                 // try to cast the given parameter to IThread pointer
00132                 IThread* mythread = static_cast<IThread*>(_mythread);
00133                 if (mythread == NULL)
00134                 {
00135                         NR_Log(Log::LOG_KERNEL, Log::LL_ERROR, "IThread: not valid parameter was specified for IThread::run(void*) method");
00136                         return;
00137                 }
00138                 
00139                 // now loop the thread until some messages occurs
00140                 bool run = true;
00141                 while (run){
00142 
00143                         // kernel requested to suspend the thread
00144                         if (mythread->mThreadState == THREAD_NEXT_SUSPEND)
00145                         {
00146                                 // notice about suspending and go into sleep mode
00147                                 mythread->changeState(THREAD_SLEEPING);
00148                                 mythread->_noticeSuspend();
00149 
00150                         // kernel requested to resume the execution
00151                         }else if (mythread->mThreadState == THREAD_NEXT_RESUME)
00152                         {
00153                                 // notice about resuming the work and start it again
00154                                 mythread->changeState(THREAD_RUNNING);
00155                                 mythread->_noticeResume();
00156 
00157                         // kernel does not requested anything, so run the task
00158                         }else if (mythread->mThreadState == THREAD_RUNNING)
00159                         {
00160                                 mythread->_noticeUpdate();
00161                         }
00162 
00163                         // check for the stop message, then stop the thread
00164                         // this is a reading mutex, so do not have to lock it
00165                         run = mythread->mThreadState != THREAD_STOP;
00166 
00167                         // we now yield the used timeslice for another threads
00168                         yield(mythread);
00169                 }
00170                 
00171                 // notice to stop the underlying task
00172                 mythread->_noticeStop();
00173 
00174                 // exit the thread
00175                 //return NULL;
00176         }
00177 
00178 }; // end namespace
00179 

Generated on Wed Sep 12 23:19:42 2007 for nrEngine by  doxygen 1.5.1