⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 posix.cc

📁 编译工具
💻 CC
📖 第 1 页 / 共 2 页
字号:
//				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 + -