kviewshell
GThreads.h
Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 #ifndef _GTHREADS_H_
00058 #define _GTHREADS_H_
00059 #ifdef HAVE_CONFIG_H
00060 #include "config.h"
00061 #endif
00062 #if NEED_GNUG_PRAGMAS
00063 # pragma interface
00064 #endif
00065 
00066 
00132 
00133 
00134 #include "DjVuGlobal.h"
00135 #include "GException.h"
00136 
00137 #define NOTHREADS     0
00138 #define COTHREADS     1
00139 #define JRITHREADS    2
00140 #define POSIXTHREADS  10
00141 #define WINTHREADS    11
00142 #define MACTHREADS    12
00143 
00144 
00145 #ifndef THREADMODEL
00146 #if defined(WIN32)
00147 #define THREADMODEL WINTHREADS
00148 #endif
00149 #if defined(macintosh)
00150 #define THREADMODEL MACTHREADS
00151 #endif
00152 #endif
00153 
00154 
00155 #ifdef USE_EXCEPTION_EMULATION
00156 #undef  THREADMODEL
00157 #define THREADMODEL NOTHREADS
00158 #endif
00159 
00160 #ifndef THREADMODEL
00161 #define THREADMODEL NOTHREADS
00162 #endif
00163 
00164 
00165 
00166 
00167 #if THREADMODEL==WINTHREADS
00168 #ifndef _WINDOWS_
00169 #define WIN32_LEAN_AND_MEAN
00170 #include "windows.h"
00171 #endif
00172 #endif
00173 
00174 #if THREADMODEL==MACTHREADS
00175 #include <threads.h>
00176 #endif
00177 
00178 #if THREADMODEL==POSIXTHREADS
00179 #include <sys/types.h>
00180 #include <sys/time.h>
00181 #include <unistd.h>
00182 #undef TRY
00183 #undef CATCH
00184 #define _CMA_NOWRAPPERS_
00185 #include <pthread.h>
00186 #endif
00187 
00188 #if THREADMODEL==JRITHREADS
00189 #include "jri.h"
00190 #endif
00191 
00192 #if THREADMODEL==COTHREADS
00193 #include <sys/types.h>
00194 #include <sys/time.h>
00195 #include <unistd.h>
00196 #endif
00197 
00198 
00199 
00200 
00201 
00202 
00203 #ifdef HAVE_NAMESPACES
00204 namespace DJVU {
00205 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00206 }
00207 #endif
00208 #endif
00209 
00210 
00211 
00230 class GThread {
00231 public:
00238   GThread(int stacksize = -1);
00242   ~GThread();
00247   int  create(void (*entry)(void*), void *arg);
00253   void terminate();
00262   static int yield();
00264   static void *current();
00265 
00266 #if THREADMODEL==WINTHREADS
00267 private:
00268   HANDLE hthr;
00269   DWORD  thrid;
00270 #elif THREADMODEL==MACTHREADS
00271 private:
00272   unsigned long thid;
00273   static pascal void *start(void *arg);
00274 #elif THREADMODEL==POSIXTHREADS
00275 private:
00276   pthread_t hthr;
00277   static void *start(void *arg);
00278 #elif THREADMODEL==JRITHREADS
00279 private:
00280   JRIGlobalRef obj;
00281 #elif THREADMODEL==COTHREADS
00282   friend class GMonitor;
00283 public:
00284   class cotask;
00285   class cotask *task;
00305   static int select(int nfds, fd_set*, fd_set*, fd_set*, struct timeval*);
00315   static void get_select(int &nfds, fd_set*, fd_set*, fd_set*, unsigned long &timeout);
00323   static void set_scheduling_callback(void (*call)(int));
00324   enum { CallbackCreate, CallbackTerminate, CallbackUnblock };
00325 
00326 #endif
00327 public:
00328   
00329   void (*xentry)(void*);
00330   void  *xarg;
00331 private:
00332   
00333   GThread(const GThread&);
00334   GThread& operator=(const GThread&);
00335 };
00336 
00337 
00362 class GMonitor
00363 {
00364 public:
00365   GMonitor();
00366   ~GMonitor();
00370   void enter();
00376   void leave();
00382   void wait();
00389   void wait(unsigned long timeout);
00393   void signal();
00397   void broadcast();
00398 private:
00399 #if THREADMODEL==WINTHREADS
00400   int ok;
00401   int count;
00402   DWORD locker;
00403   CRITICAL_SECTION cs;
00404   struct thr_waiting *head;
00405   struct thr_waiting *tail;
00406 #elif THREADMODEL==MACTHREADS
00407   int ok;
00408   int count;
00409   unsigned long locker;
00410   int wlock;
00411   int wsig;
00412 #elif THREADMODEL==POSIXTHREADS
00413   int ok;
00414   int count;
00415   pthread_t locker;
00416   pthread_mutex_t mutex;
00417   pthread_cond_t cond;
00418 #elif THREADMODEL==COTHREADS
00419   int ok;
00420   int count;
00421   void *locker;
00422   int wlock;
00423   int wsig;
00424 #elif THREADMODEL==JRITHREADS
00425   JRIGlobalRef obj;
00426 #endif  
00427 private:
00428   
00429   GMonitor(const GMonitor&);
00430   GMonitor& operator=(const GMonitor&);
00431 };
00432 
00433 
00434 
00435 
00436 
00437 
00438 
00439 #if THREADMODEL==NOTHREADS
00440 inline GThread::GThread(int) {}
00441 inline GThread::~GThread(void) {}
00442 inline void GThread::terminate() {}
00443 inline int GThread::yield() { return 0; }
00444 inline void* GThread::current() { return 0; }
00445 inline GMonitor::GMonitor() {}
00446 inline GMonitor::~GMonitor() {}
00447 inline void GMonitor::enter() {}
00448 inline void GMonitor::leave() {}
00449 inline void GMonitor::wait() {}
00450 inline void GMonitor::wait(unsigned long) {}
00451 inline void GMonitor::signal() {}
00452 inline void GMonitor::broadcast() {}
00453 #endif // NOTHREADS
00454 
00455 
00456 
00457 
00458 
00459 
00478 class GMonitorLock 
00479 {
00480 private:
00481   GMonitor *gsec;
00482 public:
00484   GMonitorLock(GMonitor *gsec) : gsec(gsec) 
00485     { if (gsec) gsec->enter(); };
00487   ~GMonitorLock() 
00488     { if (gsec) gsec->leave(); };
00489 };
00490 
00491 
00492 
00493 
00494 
00495 
00496 
00505 class GSafeFlags : public GMonitor
00506 {
00507 private:
00508    volatile long flags;
00509 public:
00511    GSafeFlags(long flags=0);
00512 
00515    GSafeFlags & operator=(long flags);
00516 
00518    operator long(void) const;
00521    GSafeFlags & operator|=(long mask);
00524    GSafeFlags & operator&=(long mask);
00525 
00531    bool test_and_modify(long set_mask, long clr_mask,
00532             long set_mask1, long clr_mask1);
00533 
00538    void wait_and_modify(long set_mask, long clr_mask,
00539             long set_mask1, long clr_mask1);
00540 
00543    void wait_for_flags(long set_mask, long clr_mask=0) const;
00544 
00548    void modify(long set_mask, long clr_mask);
00549 };
00550 
00551 inline
00552 GSafeFlags::GSafeFlags(long xflags) 
00553   : flags(xflags) 
00554 {
00555 }
00556 
00557 inline void
00558 GSafeFlags::wait_for_flags(long set_mask, long clr_mask) const
00559 {
00560    ((GSafeFlags *) this)->wait_and_modify(set_mask, clr_mask, 0, 0);
00561 }
00562 
00563 inline void
00564 GSafeFlags::modify(long set_mask, long clr_mask)
00565 {
00566    test_and_modify(0, 0, set_mask, clr_mask);
00567 }
00568 
00569 inline GSafeFlags &
00570 GSafeFlags::operator|=(long mask)
00571 {
00572    test_and_modify(0, 0, mask, 0);
00573    return *this;
00574 }
00575 
00576 inline GSafeFlags &
00577 GSafeFlags::operator&=(long mask)
00578 {
00579    test_and_modify(0, 0, 0, ~mask);
00580    return *this;
00581 }
00582 
00584 
00585 
00586 
00587 
00588 
00589 
00590 
00591 
00592 
00593 
00594 class GCriticalSection : protected GMonitor 
00595 {
00596 public:
00597   void lock() 
00598     { GMonitor::enter(); };
00599   void unlock() 
00600     { GMonitor::leave(); };
00601 };
00602 
00603 class GEvent : protected GMonitor 
00604 {
00605 private:
00606   int status;
00607 public:
00608   GEvent() 
00609     : status(0) { };
00610   void set() 
00611     { if (!status) { enter(); status=1; signal(); leave(); } };
00612   void wait() 
00613     { enter(); if (!status) GMonitor::wait(); status=0; leave(); };
00614   void wait(int timeout) 
00615     { enter(); if (!status) GMonitor::wait(timeout); status=0; leave(); };
00616 };
00617 
00618 class GCriticalSectionLock
00619 {
00620 private:
00621   GCriticalSection *gsec;
00622 public:
00623   GCriticalSectionLock(GCriticalSection *gsec) : gsec(gsec) 
00624     { if (gsec) gsec->lock(); };
00625   ~GCriticalSectionLock() 
00626     { if (gsec) gsec->unlock(); };
00627 };
00628 
00629 
00630 
00631 
00632 #ifdef HAVE_NAMESPACES
00633 }
00634 # ifndef NOT_USING_DJVU_NAMESPACE
00635 using namespace DJVU;
00636 # endif
00637 #endif
00638 #endif //_GTHREADS_H_
00639