IThread.h

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 #ifndef _NR_I_THREAD_H_
00015 #define _NR_I_THREAD_H_
00016 
00017 //----------------------------------------------------------------------------------
00018 // Includes
00019 //----------------------------------------------------------------------------------
00020 #include "Prerequisities.h"
00021 
00022 #include <boost/thread/thread.hpp>
00023 
00024 namespace nrEngine{
00025 
00026         //! Abstract class to run a ITask in a thread controlled by Kernel
00027         /**
00028          * IThread is a base class for each kin dof tasks, allows also parallel
00029          * running of a task as a thread. Kernel tasks are derived from thi class
00030          * so a task has also a possibility to run in a own thread. Kernel
00031          * controls the creation and managing of threads. Threads communicate
00032          * through the engine's default communication protocol.
00033          *
00034          * Writing a task as a thread for your application is not a big issue.
00035          * You have to listen on kernel messages coming on the engine's default
00036          * channel to be able to react on stop/suspend/resume messages. Kernel
00037          * can not simply hold on a task. Because this can corrupt data if a task was
00038          * performing any important calculations. Also this is not a good style.
00039          * Kernel will provide a function to force a killing of a thread-task, but
00040          * prevent using of this function.
00041          *
00042          * Instead of killing the running threads, kernel will send a message about
00043          * stopping the thread. A thread-task should react on this event to
00044          * gracefully stop the execution.
00045          *
00046          * The thread interface does provide neccessary functions to your tasks, so
00047          * you do not have to think about managing the kernel messages by yourself.
00048          * Instead of this the thread will call taskStop() method to indicate the task,
00049          * that kernel want to stop the thread. Suspending the task will cause the kernel
00050          * to let the according thread sleeping until the task is resumed. There is
00051          * no other way how you can let the task sleep.
00052          *
00053          * So how the thread interface cooperate with the kernel and the task interface.
00054          * You write your task in the way, like if it were a simple task running
00055          * sequentially in the kernel. Each ITask itnerface is a derived class from
00056          * IThread but a thread portion of the code will only be active if you use the task
00057          * as a thread for the kernel. By marking the task as a thread i.e. by adding
00058          * the task to the kernel as a thread, you will activate the thread interface automatic.
00059          * Kernel will start the thread and will call the taskInit() and taskStart() functions
00060          * at the right moment. If the task is a thread, so it will call threadStart() instead
00061          * which will call thread_taskStart() method of derived ITask interface. The method
00062          * will call your taskStart() method, so you will not notice if there is a difference
00063          * between starting a task as a task or as a thread.
00064          *
00065          * In each cycle the kernel does call taskUpdate() method for sequential tasks. For
00066          * parallel tasks (threads) it does not call anything, because thread interface already
00067          * running and it will automaticaly call the appropritate taskUpdate() method, so
00068          * the task is getting updated. Also the thread base class does check if there is
00069          * any messages from the kernel (i.e. sleep or stop). If so it will call appropriate
00070          * methods in ITask interface.
00071          *
00072          * Our threads does yield their time slice to another threads after each execution cycle.
00073          * In this manner we get a friendly and intuitive behaviour of threads running in parallel.
00074          *
00075          * NOTE: The IThread interaface and Kernel does do all the job for you to manage
00076          * themself as a threads and to let them run in parallel. The only one thing it
00077          * can not manage for you is synchronisation. You have to worry about this by yourself
00078          * by using of mutex locking mechanism.
00079          *
00080          * \ingroup kernel
00081         **/
00082         class _NRExport IThread{
00083                 public:
00084                         /**
00085                          * Virtual destructor so we are able to derive classes
00086                          * with overloaded methods.
00087                          **/
00088                         virtual ~IThread();
00089 
00090                 protected:
00091 
00092                         /**
00093                          * Protected constructor, so only the ITask-Interface
00094                          * and friends are able to create an instance of this class.
00095                          * In this way we protect wrong usage of this interface.
00096                          **/
00097                         IThread();
00098 
00099                         /**
00100                          * Call this method if a thread goes into sleep mode. The derived
00101                          * task should reimplement this method to call the appropriate suspend
00102                          * method
00103                          **/
00104                         virtual void _noticeSuspend() = 0;
00105 
00106                         /**
00107                          * Call this method by waking up a thread. The derived task interface
00108                          * should call the appropritate resume method
00109                          **/
00110                         virtual void _noticeResume() = 0;
00111 
00112                         /**
00113                          * Thread does call this method in a main loop. The method
00114                          * should call the appropritate update method in ITask interface
00115                          **/
00116                         virtual void _noticeUpdate() = 0;
00117 
00118                         /**
00119                          * Call this method by stopping the execution of a thread. The underlying
00120                          * task has to remove all used data, because after calling of this method
00121                          * it will be destroyed
00122                          **/
00123                         virtual void _noticeStop() = 0;
00124 
00125                 private:
00126 
00127                         /**
00128                          * This is a entry point for a thread. The method is
00129                          * static because it do not have to access any data
00130                          * of the object itself. The given thread instance as a parameter
00131                          * will be updated and managed as a thread.
00132                          **/
00133                         static void run(void* mythread);
00134 
00135                         //! Kernel is a friend class
00136                         friend class Kernel;
00137 
00138                         /**
00139                          * Call the appropriate yield method of the threading library.
00140                          * The thread calling this method will yield its remaining timeslice
00141                          * to other threads.
00142                          *
00143                          * @param mythread Pointer to the thread which yields.
00144                          *              If NULL specified, so the called thread will be yield.
00145                          **/
00146                         static void yield(IThread* mythread = NULL);
00147                         
00148                         /**
00149                          * Kernel does call this method if the appropriate task is running
00150                          * as a thread in the kernel. This method manage the derived class by calling appropriate
00151                          * virtual methods, which has to be reimplemented in the ITask interface.
00152                          **/
00153                         void threadStart();
00154 
00155                         /**
00156                          * Kernel does call this method, if a thread should stop.
00157                          **/
00158                         void threadStop();
00159 
00160                         /**
00161                          * Kernel call this method if a thread is going into sleep mode
00162                          **/
00163                         void threadSuspend();
00164 
00165                         /**
00166                          * Kernel call this method if a thread is goind to resume
00167                          **/
00168                         void threadResume();
00169 
00170                         //! Define thread states
00171                         enum ThreadState{
00172                                 //! Thread is not running it is stopped
00173                                 THREAD_STOP,
00174 
00175                                 //! Thread does running
00176                                 THREAD_RUNNING,
00177 
00178                                 //! Thread is in sleep state (no action, but ready to wakeup)
00179                                 THREAD_SLEEPING,
00180 
00181                                 //! Wakeup the thread as soon as possible
00182                                 THREAD_NEXT_RESUME,
00183 
00184                                 //! Suspend the thread as soon as possible
00185                                 THREAD_NEXT_SUSPEND
00186                         };
00187 
00188                         //! This is a variable which will manage the thread state
00189                         ThreadState     mThreadState;
00190 
00191                         // Mutex to lock the data before use
00192                         //pthread_mutex_t mMutex;
00193 
00194                         //! Store here the thread instance
00195                         SharedPtr<boost::thread> mThread;
00196 
00197                         //! Thread attributes
00198                         //pthread_attr_t mThreadAttr;
00199                         
00200                         
00201                         //! Change a thread to new state, use mutex to lock the state
00202                         void changeState(ThreadState newState);
00203 
00204         };
00205 
00206 }; // end namespace
00207 #endif  //_NR...

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