?? posix.cc
字號:
// Package : omnithread// omnithread/posix.cc Created : 7/94 tjr//// Copyright (C) 1994-1999 AT&T Laboratories Cambridge//// This file is part of the omnithread library//// The omnithread library is free software; you can redistribute it and/or// modify it under the terms of the GNU Library General Public// License as published by the Free Software Foundation; either// version 2 of the License, or (at your option) any later version.//// This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU// Library General Public License for more details.//// You should have received a copy of the GNU Library General Public// License along with this library; if not, write to the Free// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // 02111-1307, USA////// Implementation of OMNI thread abstraction for posix threads//// The source below tests for the definition of the macros:// PthreadDraftVersion// PthreadSupportThreadPriority// NoNanoSleep// NeedPthreadInit//// As different draft versions of the pthread standard P1003.4a/P1003.1c// define slightly different APIs, the macro 'PthreadDraftVersion'// identifies the draft version supported by this particular platform.//// Some unix variants do not support thread priority unless a real-time// kernel option is installed. The macro 'PthreadSupportThreadPriority',// if defined, enables the use of thread priority. If it is not defined,// setting or changing thread priority will be silently ignored.//// nanosleep() is defined in Posix P1003.4 since Draft 9 (?).// Not all platforms support this standard. The macro 'NoNanoSleep'// identifies platform that don't.//#ifdef __VMS# define pthread_attr_destroy PTHREAD_ATTR_DESTROY# define pthread_attr_init PTHREAD_ATTR_INIT# define pthread_attr_setschedparam PTHREAD_ATTR_SETSCHEDPARAM# define pthread_attr_setstacksize PTHREAD_ATTR_SETSTACKSIZE# define pthread_cond_broadcast PTHREAD_COND_BROADCAST# define pthread_cond_destroy PTHREAD_COND_DESTROY# define pthread_cond_init PTHREAD_COND_INIT# define pthread_cond_signal PTHREAD_COND_SIGNAL# define pthread_cond_timedwait PTHREAD_COND_TIMEDWAIT# define pthread_cond_wait PTHREAD_COND_WAIT# define pthread_create PTHREAD_CREATE# define pthread_delay_np PTHREAD_DELAY_NP# define pthread_detach PTHREAD_DETACH# define pthread_exit PTHREAD_EXIT# define pthread_get_expiration_np PTHREAD_GET_EXPIRATION_NP# define pthread_getspecific PTHREAD_GETSPECIFIC# define pthread_join32 PTHREAD_JOIN32# define pthread_key_create PTHREAD_KEY_CREATE# define pthread_mutex_destroy PTHREAD_MUTEX_DESTROY# define pthread_mutex_init PTHREAD_MUTEX_INIT# define pthread_mutex_lock PTHREAD_MUTEX_LOCK# define pthread_mutex_unlock PTHREAD_MUTEX_UNLOCK# define pthread_self PTHREAD_SELF# define pthread_setschedparam PTHREAD_SETSCHEDPARAM# define pthread_setspecific PTHREAD_SETSPECIFIC# define pthread_yield_np PTHREAD_YIELD_NP#endif#include <stdlib.h>#include <errno.h>#include <time.h>#include <omnithread.h>#if (defined(__GLIBC__) && __GLIBC__ >= 2) || defined(__SCO_VERSION__) || defined(__aix__) || defined (__cygwin__) || defined(__darwin__) || defined(__macos__)// typedef of struct timeval and gettimeofday();#include <sys/time.h>#include <unistd.h>#endif#if defined(__linux__) && defined(_MIT_POSIX_THREADS)#include <pthread/mit/sys/timers.h>#endif#if defined(__irix__) && defined(PthreadSupportThreadPriority)#if _POSIX_THREAD_PRIORITY_SCHEDULING#include <sched.h>#endif#endif#define DB(x) // x//#include <iostream.h> or #include <iostream> if DB is on.#if (PthreadDraftVersion <= 6)#define ERRNO(x) (((x) != 0) ? (errno) : 0)#ifdef __VMS// pthread_setprio returns old priority on success (draft version 4:// OpenVms version < 7)#define THROW_ERRORS(x) { if ((x) == -1) throw omni_thread_fatal(errno); }#else#define THROW_ERRORS(x) { if ((x) != 0) throw omni_thread_fatal(errno); }#endif#else#define ERRNO(x) (x)#define THROW_ERRORS(x) { int rc = (x); \ if (rc != 0) throw omni_thread_fatal(rc); }#endif/////////////////////////////////////////////////////////////////////////////// Mutex/////////////////////////////////////////////////////////////////////////////omni_mutex::omni_mutex(void){#if (PthreadDraftVersion == 4) THROW_ERRORS(pthread_mutex_init(&posix_mutex, pthread_mutexattr_default));#else THROW_ERRORS(pthread_mutex_init(&posix_mutex, 0));#endif}omni_mutex::~omni_mutex(void){ THROW_ERRORS(pthread_mutex_destroy(&posix_mutex));}/////////////////////////////////////////////////////////////////////////////// Condition variable/////////////////////////////////////////////////////////////////////////////omni_condition::omni_condition(omni_mutex* m) : mutex(m){#if (PthreadDraftVersion == 4) THROW_ERRORS(pthread_cond_init(&posix_cond, pthread_condattr_default));#else THROW_ERRORS(pthread_cond_init(&posix_cond, 0));#endif}omni_condition::~omni_condition(void){ THROW_ERRORS(pthread_cond_destroy(&posix_cond));}voidomni_condition::wait(void){ THROW_ERRORS(pthread_cond_wait(&posix_cond, &mutex->posix_mutex));}intomni_condition::timedwait(unsigned long secs, unsigned long nanosecs){ timespec rqts = { secs, nanosecs };again: int rc = ERRNO(pthread_cond_timedwait(&posix_cond, &mutex->posix_mutex, &rqts)); if (rc == 0) return 1;#if (PthreadDraftVersion <= 6) if (rc == EAGAIN) return 0;#endif // Some versions of unix produces this errno when the wait was // interrupted by a unix signal or fork. // Some versions of the glibc 2.0.x produces this errno when the // program is debugged under gdb. Straightly speaking this is non-posix // compliant. We catch this here to make debugging possible. if (rc == EINTR) goto again; if (rc == ETIMEDOUT) return 0; throw omni_thread_fatal(rc);#ifdef _MSC_VER return 0;#endif}voidomni_condition::signal(void){ THROW_ERRORS(pthread_cond_signal(&posix_cond));}voidomni_condition::broadcast(void){ THROW_ERRORS(pthread_cond_broadcast(&posix_cond));}/////////////////////////////////////////////////////////////////////////////// Counting semaphore/////////////////////////////////////////////////////////////////////////////omni_semaphore::omni_semaphore(unsigned int initial) : c(&m){ value = initial;}omni_semaphore::~omni_semaphore(void){}voidomni_semaphore::wait(void){ omni_mutex_lock l(m); while (value == 0) c.wait(); value--;}intomni_semaphore::trywait(void){ omni_mutex_lock l(m); if (value == 0) return 0; value--; return 1;}voidomni_semaphore::post(void){ omni_mutex_lock l(m); value++; c.signal();}/////////////////////////////////////////////////////////////////////////////// Thread///////////////////////////////////////////////////////////////////////////////// static variables//omni_mutex* omni_thread::next_id_mutex;int omni_thread::next_id = 0;static pthread_key_t self_key;#ifdef PthreadSupportThreadPrioritystatic int lowest_priority;static int normal_priority;static int highest_priority;#endif#if defined(__osf1__) && defined(__alpha__) || defined(__VMS)// omniORB requires a larger stack size than the default (21120) on OSF/1static size_t stack_size = 32768;#elif defined(__rtems__)static size_t stack_size = ThreadStackSize;#elif defined(__aix__)static size_t stack_size = 262144;#elsestatic size_t stack_size = 0;#endif//// Initialisation function (gets called before any user code).//static int& count() { static int the_count = 0; return the_count;}omni_thread::init_t::init_t(void){ if (count()++ != 0) // only do it once however many objects get created. return; DB(cerr << "omni_thread::init: posix 1003.4a/1003.1c (draft " << PthreadDraftVersion << ") implementation initialising\n");#ifdef NeedPthreadInit pthread_init();#endif#if (PthreadDraftVersion == 4) THROW_ERRORS(pthread_keycreate(&self_key, NULL));#else THROW_ERRORS(pthread_key_create(&self_key, NULL));#endif#ifdef PthreadSupportThreadPriority#if defined(__osf1__) && defined(__alpha__) || defined(__VMS) lowest_priority = PRI_OTHER_MIN; highest_priority = PRI_OTHER_MAX;#elif defined(__hpux__) lowest_priority = PRI_OTHER_MIN; highest_priority = PRI_OTHER_MAX;#elif defined(__sunos__) && (__OSVERSION__ == 5) // a bug in pthread_attr_setschedparam means lowest priority is 1 not 0 lowest_priority = 1; highest_priority = 3;#else lowest_priority = sched_get_priority_min(SCHED_FIFO); highest_priority = sched_get_priority_max(SCHED_FIFO);#endif switch (highest_priority - lowest_priority) { case 0: case 1: normal_priority = lowest_priority; break; default: normal_priority = lowest_priority + 1; break;#endif /* PthreadSupportThreadPriority */ next_id_mutex = new omni_mutex; // // Create object for this (i.e. initial) thread. // omni_thread* t = new omni_thread; t->_state = STATE_RUNNING; t->posix_thread = pthread_self (); DB(cerr << "initial thread " << t->id() << endl); THROW_ERRORS(pthread_setspecific(self_key, (void*)t));#ifdef PthreadSupportThreadPriority#if (PthreadDraftVersion == 4) THROW_ERRORS(pthread_setprio(t->posix_thread, posix_priority(PRIORITY_NORMAL)));#elif (PthreadDraftVersion == 6) pthread_attr_t attr; pthread_attr_init(&attr); THROW_ERRORS(pthread_attr_setprio(&attr, posix_priority(PRIORITY_NORMAL))); THROW_ERRORS(pthread_setschedattr(t->posix_thread, attr));#else struct sched_param sparam; sparam.sched_priority = posix_priority(PRIORITY_NORMAL); THROW_ERRORS(pthread_setschedparam(t->posix_thread, SCHED_OTHER, &sparam));#endif /* PthreadDraftVersion */#endif /* PthreadSupportThreadPriority */}omni_thread::init_t::~init_t(void){ if (--count() != 0) return; omni_thread* self = omni_thread::self(); if (!self) return; pthread_setspecific(self_key, 0); delete self; delete next_id_mutex;}//// Wrapper for thread creation.//extern "C" void* omni_thread_wrapper(void* ptr){ omni_thread* me = (omni_thread*)ptr; DB(cerr << "omni_thread_wrapper: thread " << me->id() << " started\n"); THROW_ERRORS(pthread_setspecific(self_key, me)); // // Now invoke the thread function with the given argument. // if (me->fn_void != NULL) { (*me->fn_void)(me->thread_arg); omni_thread::exit(); } if (me->fn_ret != NULL) { void* return_value = (*me->fn_ret)(me->thread_arg); omni_thread::exit(return_value); } if (me->detached) { me->run(me->thread_arg); omni_thread::exit(); } else { void* return_value = me->run_undetached(me->thread_arg); omni_thread::exit(return_value); } // should never get here. return NULL;}//// Constructors for omni_thread - set up the thread object but don't// start it running.//// construct a detached thread running a given function.omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri){ common_constructor(arg, pri, 1); fn_void = fn; fn_ret = NULL;}// construct an undetached thread running a given function.omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri){ common_constructor(arg, pri, 0); fn_void = NULL; fn_ret = fn;}// construct a thread which will run either run() or run_undetached().omni_thread::omni_thread(void* arg, priority_t pri){ common_constructor(arg, pri, 1); fn_void = NULL; fn_ret = NULL;}// common part of all constructors.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -