//file: omnithread.h //A pseudo omnithread. Use the same name of functions in omni_thread but implement //them by SGI's sproc multi-threading scheme. The purpose of doing this is to make //omniORB compatible with OpenMP. //Created by Song Li 06-06-2003 #ifndef __omnithread_h_ #define __omnithread_h_ #ifndef NULL #define NULL (void*)0 #endif #include #include #include #include #include #include #include #include #include #include #include class omni_mutex; class omni_condition; class omni_semaphore; class omni_thread; #ifndef OMNI_THREAD_EXPOSE #define OMNI_THREAD_EXPOSE private #endif #if !defined(__WIN32__) #define _OMNITHREAD_NTDLL_ #endif #define OMNI_MUTEX_IMPLEMENTATION \ ulock_t mutex; #define OMNI_CONDITION_IMPLEMENTATION \ usema_t* cond; \ int sd; #define OMNI_SEMAPHORE_IMPLEMENTATION \ omni_mutex m; \ omni_condition c; \ int value; #define OMNI_THREAD_IMPLEMENTATION \ omni_thread* posix_thread; \ static int posix_priority(priority_t); \ friend void* omni_thread_wrapper(void* ptr); typedef void(* thread_func_t)(void *); extern "C" void* omni_thread_wrapper(void* ptr); // // This exception is thrown in the event of a fatal error. // class _OMNITHREAD_NTDLL_ omni_thread_fatal { public: int error; omni_thread_fatal(int e = 0) : error(e) {} }; // // This exception is thrown when an operation is invoked with invalid // arguments. // class _OMNITHREAD_NTDLL_ omni_thread_invalid {}; /////////////////////////////////////////////////////////////////////////// // Arena /////////////////////////////////////////////////////////////////////////// class Arena { public: Arena(void); Arena(usptr_t *); usptr_t* get_arena(); operator usptr_t *(void); private: usptr_t* arena; }; /////////////////////////////////////////////////////////////////////////// // // Mutex // /////////////////////////////////////////////////////////////////////////// class _OMNITHREAD_NTDLL_ omni_mutex { public: omni_mutex(void); ~omni_mutex(void); void lock(void); void unlock(void); void acquire(void) { lock(); } void release(void) { unlock(); } friend class omni_condition; private: // dummy copy constructor and operator= to prevent copying omni_mutex(const omni_mutex&); omni_mutex& operator=(const omni_mutex&); static Arena* arena; OMNI_THREAD_EXPOSE: OMNI_MUTEX_IMPLEMENTATION }; class _OMNITHREAD_NTDLL_ omni_mutex_lock { omni_mutex& mutex; public: omni_mutex_lock(omni_mutex& m) : mutex(m) { mutex.lock(); } ~omni_mutex_lock(void) { mutex.unlock(); } private: // dummy copy constructor and operator= to prevent copying omni_mutex_lock(const omni_mutex_lock&); omni_mutex_lock& operator=(const omni_mutex_lock&); }; /////////////////////////////////////////////////////////////////////////// // // Condition variable // /////////////////////////////////////////////////////////////////////////// class _OMNITHREAD_NTDLL_ omni_condition { omni_mutex* mutex; public: omni_condition(omni_mutex* m); ~omni_condition(void); void wait(void); int timedwait(unsigned long secs, unsigned long nanosecs = 0); void signal(void); void broadcast(void); private: // dummy copy constructor and operator= to prevent copying omni_condition(const omni_condition&); omni_condition& operator=(const omni_condition&); static Arena* arena; OMNI_THREAD_EXPOSE: OMNI_CONDITION_IMPLEMENTATION }; /////////////////////////////////////////////////////////////////////////// // // Counting semaphore // /////////////////////////////////////////////////////////////////////////// class _OMNITHREAD_NTDLL_ omni_semaphore { public: omni_semaphore(unsigned int initial = 1); ~omni_semaphore(void); void wait(void); int trywait(void); void post(void); private: // dummy copy constructor and operator= to prevent copying omni_semaphore(const omni_semaphore&); omni_semaphore& operator=(const omni_semaphore&); static Arena* arena; usema_t* sema; OMNI_THREAD_EXPOSE: OMNI_SEMAPHORE_IMPLEMENTATION }; // // A helper class for semaphores, similar to omni_mutex_lock above. // class _OMNITHREAD_NTDLL_ omni_semaphore_lock { omni_semaphore& sem; public: omni_semaphore_lock(omni_semaphore& s) : sem(s) { sem.wait(); } ~omni_semaphore_lock(void) { sem.post(); } private: // dummy copy constructor and operator= to prevent copying omni_semaphore_lock(const omni_semaphore_lock&); omni_semaphore_lock& operator=(const omni_semaphore_lock&); }; /////////////////////////////////////////////////////////////////////////// // // Thread // /////////////////////////////////////////////////////////////////////////// class _OMNITHREAD_NTDLL_ omni_thread { public: enum priority_t { PRIORITY_LOW, PRIORITY_NORMAL, PRIORITY_HIGH }; enum state_t { STATE_NEW, // thread object exists but thread hasn't // started yet. STATE_RUNNING, // thread is running. STATE_TERMINATED // thread has terminated but storage has not // been reclaimed (i.e. waiting to be joined). }; omni_thread(void (*fn)(void*), void* arg = NULL, priority_t pri = PRIORITY_NORMAL); omni_thread(void* (*fn)(void*), void* arg = NULL, priority_t pri = PRIORITY_NORMAL); void start(void); protected: omni_thread(void* arg = NULL, priority_t pri = PRIORITY_NORMAL); void start_undetached(void); virtual ~omni_thread(void); public: void join(void**); void set_priority(priority_t); static omni_thread* create(void (*fn)(void*), void* arg = NULL, priority_t pri = PRIORITY_NORMAL); static omni_thread* create(void* (*fn)(void*), void* arg = NULL, priority_t pri = PRIORITY_NORMAL); static void exit(void* return_value = NULL); static omni_thread* self(void); static void yield(void); static void sleep(unsigned long secs, unsigned long nanosecs = 0); static void get_time(unsigned long* abs_sec, unsigned long* abs_nsec, unsigned long rel_sec = 0, unsigned long rel_nsec=0); static void stacksize(unsigned long sz); static unsigned long stacksize(); private: virtual void run(void* arg) {} virtual void* run_undetached(void* arg) { return NULL; } void common_constructor(void* arg, priority_t pri, int det); omni_mutex mutex; state_t _state; priority_t _priority; static omni_mutex* next_id_mutex; static int next_id; int _id; void (*fn_void)(void*); void* (*fn_ret)(void*); void* thread_arg; int detached; pid_t mThreadPID; static void setLocalThreadPtr(omni_thread* threadPtr) { ((ThreadInfo*)PRDA->usr_prda.fill)->mThreadPtr = threadPtr; } static omni_thread* getLocalThreadPtr() { return ((ThreadInfo*)PRDA->usr_prda.fill)->mThreadPtr; } /** * Structure for storing thread specific information. */ struct ThreadInfo { omni_thread* mThreadPtr; }; public: priority_t priority(void) { // return this thread's priority. omni_mutex_lock l(mutex); return _priority; } state_t state(void) { // return thread state (invalid, new, running or terminated). omni_mutex_lock l(mutex); return _state; } int id(void) { return _id; } // return unique thread id within the current process. // This class plus the instance of it declared below allows us to execute // some initialisation code before main() is called. class _OMNITHREAD_NTDLL_ init_t { static int count; public: init_t(void); }; friend class init_t; OMNI_THREAD_EXPOSE: OMNI_THREAD_IMPLEMENTATION }; #endif