weaver.h
00001 /* -*- C++ -*- 00002 00003 This file declares the Weaver, Job and Thread classes. 00004 00005 $ Author: Mirko Boehm $ 00006 $ Copyright: (C) 2004, Mirko Boehm $ 00007 $ Contact: mirko@kde.org 00008 http://www.kde.org 00009 http://www.hackerbuero.org $ 00010 $ License: LGPL with the following explicit clarification: 00011 This code may be linked against any version of the TQt toolkit 00012 from Troll Tech, Norway. $ 00013 00014 */ 00015 00016 #ifndef WEAVER_H 00017 #define WEAVER_H 00018 00019 extern "C" 00020 { 00021 #include <stdarg.h> 00022 #include <unistd.h> 00023 #include <stdio.h> 00024 } 00025 00026 #include <tqobject.h> 00027 #include <tqptrlist.h> 00028 #include <tqthread.h> 00029 #include <tqwaitcondition.h> 00030 #include <tqmutex.h> 00031 #include <tqevent.h> 00032 00033 #include <tdepimmacros.h> 00034 00035 namespace KPIM { 00036 namespace ThreadWeaver { 00037 00054 KDE_EXPORT extern bool Debug; 00055 KDE_EXPORT extern int DebugLevel; 00056 00057 KDE_EXPORT inline void setDebugLevel (bool debug, int level) 00058 { 00059 Debug = debug; 00060 DebugLevel = level; 00061 } 00062 00063 KDE_EXPORT inline void debug(int severity, const char * cformat, ...) 00064 #ifdef __GNUC__ 00065 __attribute__ ( (format (printf, 2, 3 ) ) ) 00066 #endif 00067 ; 00068 00069 KDE_EXPORT inline void debug(int severity, const char * cformat, ...) 00070 { 00071 if ( Debug == true && ( severity<=DebugLevel || severity == 0) ) 00072 { 00073 static TQMutex mutex; 00074 TQString text; 00075 00076 mutex.lock(); 00077 va_list ap; 00078 va_start( ap, cformat ); 00079 vprintf (cformat, ap); 00080 va_end (ap); 00081 mutex.unlock(); 00082 } 00083 } 00084 00085 00086 class Thread; 00087 class Job; 00088 00100 class KDE_EXPORT Event : public TQCustomEvent 00101 { 00102 public: 00103 enum Action { 00104 NoAction = 0, 00105 Finished, 00106 Suspended, 00107 ThreadStarted, 00108 ThreadExiting, 00109 ThreadBusy, 00110 ThreadSuspended, 00111 JobStarted, 00112 JobFinished, 00113 JobSPR, 00114 JobAPR 00115 }; 00116 Event ( Action = NoAction, Thread * = 0, Job *job = 0); 00118 static int type (); 00120 Thread* thread () const; 00122 Job* job () const; 00124 Action action () const; 00125 private: 00126 Action m_action; 00127 Thread *m_thread; 00128 Job *m_job; 00129 static const int Type; 00130 }; 00131 00164 class KDE_EXPORT Job : public TQObject 00165 { 00166 Q_OBJECT 00167 00168 public: 00170 Job(TQObject* parent=0, const char* name=0); 00171 00173 virtual ~Job(); 00174 00179 virtual void execute(Thread*); 00180 00182 virtual bool isFinished() const; 00183 00185 void wakeAPR (); 00186 00189 virtual void processEvent ( Event* ); 00190 00191 signals: 00193 void started (); 00195 void done (); 00208 void SPR (); 00211 void APR (); 00212 protected: 00214 void lock(); 00216 void unlock(); 00220 virtual void run () = 0; 00223 Thread *thread(); 00225 virtual void setFinished(bool status); 00229 void triggerSPR (); 00235 void triggerAPR (); 00236 00237 bool m_finished; 00238 00239 TQMutex *m_mutex; 00240 00241 Thread * m_thread; 00242 00243 TQWaitCondition *m_wc; 00244 }; 00245 00246 class Weaver; 00247 00250 class KDE_EXPORT Thread : public TQThread 00251 { 00252 public: 00256 Thread(Weaver *parent); 00257 00259 ~Thread(); 00260 00270 void run(); 00271 00272 /* Provide the msleep() method (protected in TQThread) to be 00273 available for executed jobs. */ 00274 void msleep(unsigned long msec); 00275 00280 unsigned int id() const; 00281 00283 void post (Event::Action, Job* = 0); 00284 00285 private: 00286 Weaver *m_parent; 00287 00288 const unsigned int m_id; 00289 00290 static unsigned int sm_Id; 00291 00292 static unsigned int makeId(); 00293 }; 00294 00297 class KDE_EXPORT Weaver : public TQObject 00298 { 00299 Q_OBJECT 00300 00301 public: 00302 Weaver (TQObject* parent=0, const char* name=0, 00303 int inventoryMin = 4, // minimal number of provided threads 00304 int inventoryMax = 32); // maximum number of provided threads 00305 virtual ~Weaver (); 00307 virtual void enqueue (Job*); 00316 void enqueue (TQPtrList<Job> jobs); 00326 virtual bool dequeue (Job*); 00330 virtual void dequeue (); 00333 // virtual void jobFinished(Thread *); 00341 virtual void finish(); 00352 virtual void suspend (bool state); 00354 bool isEmpty () const; 00358 bool isIdle () const; 00360 int queueLength (); 00371 virtual Job* applyForWork (Thread *thread, Job *previous); 00375 void lock (); 00377 void unlock (); 00382 void post (Event::Action, Thread* = 0, Job* = 0); 00384 int threads () const; 00385 signals: 00392 void finished (); 00397 void suspended (); 00401 void jobDone (Job*); 00402 // The following signals are used mainly for debugging purposes. 00403 void threadCreated (Thread *); 00404 void threadDestroyed (Thread *); 00405 void threadBusy (Thread *); 00406 void threadSuspended (Thread *); 00407 00408 protected: 00412 void assignJobs(); 00415 bool event ( TQEvent* ); 00417 TQPtrList<Thread> m_inventory; 00419 TQPtrList<Job> m_assignments; 00422 int m_active; 00424 int m_inventoryMin; 00426 int m_inventoryMax; 00428 TQWaitCondition m_jobAvailable; 00430 TQWaitCondition m_jobFinished; 00433 bool m_shuttingDown; 00438 bool m_running; 00443 bool m_suspend; 00444 private: 00446 TQMutex *m_mutex; 00447 }; 00448 } // namespace ThreadWeaver 00449 } // namespace KPIM 00450 00451 #endif // defined WEAVER_H