📄 pthreads.h
字号:
// -*- c++ -*-/* * MICO --- an Open Source CORBA implementation * Copyright (c) 1997-2008 by The Mico Team * * OSThread: An abstract Thread class for MICO * Copyright (C) 1999 Andy Kersting & Andreas Schultz * * This 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., 675 Mass Ave, Cambridge, MA 02139, USA. * * For more information, visit the MICO Home Page at * http://www.mico.org/ * * support for POSIX Draft 10ish Pthreads for Linux as developed by * Xavier LeRoy@inria.fr * */#ifndef __OS_THREAD_PTHREADS_H__#define __OS_THREAD_PTHREADS_H__void _init ();//// Mutex//class CondVar;//!// \ingroup micomt//// The Mutex class is a simple synchronization object used to protect// critical sections.//class Mutex#ifdef DEBUG_NAMES : public NamedObject#endif // DEBUG_NAMES{public: friend class CondVar; /*! * \enum Attribute * * The Attribute enum defines a specific attribute for the Mutex * class. An attribute may be either Normal or Recursive. A normal * mutex may only be locked once by a thread. Attempts to lock it * more than once will result in a deadlock. A recursive mutex may * be locked multiple times by the same thread. */ enum Attribute { Normal, Recursive }; /*! * \enum ErrorType * * Error types associated with a mutex. */ enum ErrorType { NoError, //!< No error on the mutex AlreadyLocked, //!< The mutex is already locked. TryAgain, //!< Try locking again. Invalid, //!< Invalid mutex. Fault, //!< A fault occurred. DeadLock, //!< The operation would result in deadlock UnknownError //!< An unknown error occurred }; //! \name Constructor/Destructor //@{ Mutex(MICO_Boolean locked = FALSE, Attribute attr = Normal); ~Mutex(); //@} //! \name Mutex Operations //@{ /*! * The trylock method is used to sample the mutex to see if it * is locked. If the mutex is not locked the thread will obtain * the lock, returning true. Otherwise, an error condition will * be returned, and the thread will not own the lock. * * \return True if the thread obtains the lock. */ MICO_ULong trylock() { ErrorType ret = NoError;#ifdef MTDEBUG if (MICO::Logger::IsLogged (MICO::Logger::Thread)) { __mtdebug_lock(); MICO::Logger::Stream (MICO::Logger::Thread) __NAME (<< name ()) << ": Mutex::trylock ()" << endl; __mtdebug_unlock(); }#endif // MTDEBUG switch (pthread_mutex_trylock(&_mutex)) { case 0: ret = MICOMT::Mutex::NoError; break; case EBUSY: ret = MICOMT::Mutex::AlreadyLocked; break; case EAGAIN: ret = MICOMT::Mutex::TryAgain; break; case EINVAL: ret = MICOMT::Mutex::Invalid; break; case EFAULT: ret = MICOMT::Mutex::Fault; break; case EDEADLK: ret = MICOMT::Mutex::DeadLock; break; default: ret = MICOMT::Mutex::UnknownError; } return ret; } /*! * The lock method is used to lock the mutex. A thread locking * the mutex will have ownership of the lock until it is unlocked. * Any thread trying to subsequently lock the mutex will block * until the owning thread has unlocked it. */ void lock() {#ifdef MTDEBUG if (MICO::Logger::IsLogged (MICO::Logger::Thread)) { __mtdebug_lock(); MICO::Logger::Stream (MICO::Logger::Thread) __NAME(<< name ()) << ": Mutex::lock ()" << endl; __mtdebug_unlock(); }#endif // MTDEBUG#ifdef SOLARIS_MUTEX if (_rec) { if (_id == pthread_self()) { // we already have the look _cnt++; return; } pthread_mutex_lock(&_mutex); assert(_cnt == 0); // paranoia _id = pthread_self(); _cnt = 1; } else { pthread_mutex_lock(&_mutex); }#else // SOLARIS_MUTEX pthread_mutex_lock(&_mutex);#endif // SOLARIS_MUTEX } /*! * The unlock method is used to release the ownership of a mutex. * Threads waiting on the locked mutex are re-woken and may attempt * to lock the mutex themselves. */ void unlock() {#ifdef MTDEBUG if (MICO::Logger::IsLogged (MICO::Logger::Thread)) { __mtdebug_lock(); MICO::Logger::Stream (MICO::Logger::Thread) __NAME(<< name ()) << ": Mutex::unlock ()" << endl; __mtdebug_unlock(); }#endif // MTDEBUG#ifdef SOLARIS_MUTEX if (_rec) { _cnt--; if (!_cnt) { _id = 0; // hopefully 0 is not a valid thread id pthread_mutex_unlock(&_mutex); } } else { pthread_mutex_unlock(&_mutex); }#else // SOLARIS_MUTEX pthread_mutex_unlock(&_mutex);#endif // SOLARIS_MUTEX } //@}protected: pthread_mutex_t _mutex; //!< Pthread mutex object#ifdef SOLARIS_MUTEX pthread_t _id; //!< Id of thread which hold ownership unsigned int _cnt; //!< Counter of recursive mutex unsigned int _rec; //!< Is mutex recursive?#endif // SOLARIS_MUTEX};//// Conditional Variable///*! * \ingroup micomt * * A condition variable is a synchronization object that associates * a condition with a mutex. */class CondVar#ifdef DEBUG_NAMES : public NamedObject#endif // DEBUG_NAMES{public: //! \name Constructor/Destructor //@{ CondVar(MICOMT::Mutex* mut); ~CondVar(); //@} //! \name Condition Variable Operations //@{ /*! * The wait method blocks the calling thread until it is woken * up by another thread signalling or broadcasting to the condition * variable. * * \return True on success, false on failure */ MICO_Boolean wait() {#ifdef MTDEBUG if (MICO::Logger::IsLogged (MICO::Logger::Thread)) { __mtdebug_lock(); MICO::Logger::Stream (MICO::Logger::Thread) __NAME(<< name ()) << ": CondVar::wait ()" << endl; __mtdebug_unlock(); }#endif // MTDEBUG return (pthread_cond_wait(&_cond,&_mutex->_mutex) == 0); }; /*! * The timedwait method blocks the calling thread until it * is woken up by another thread signalling or broadcasting to * the condition variable. It can also be woken up after the * elapsed time specified by tmout. * * \param tmout Milliseconds to wait for a signal. * \return True on success, false on failure. */ MICO_Boolean timedwait(MICO_ULong tmout); /*! * The broadcast method wakes up all threads waiting on the * condition variable. */ void broadcast() {#ifdef MTDEBUG if (MICO::Logger::IsLogged (MICO::Logger::Thread)) { __mtdebug_lock(); MICO::Logger::Stream (MICO::Logger::Thread) __NAME(<< name ()) << ": CondVar::broadcast ()" << endl; __mtdebug_unlock(); }#endif // MTDEBUG pthread_cond_broadcast(&_cond); }; /*! * The signal method wakes up exactly one thread waiting * on the condition variable. */ void signal() {#ifdef MTDEBUG if (MICO::Logger::IsLogged (MICO::Logger::Thread)) { __mtdebug_lock(); MICO::Logger::Stream (MICO::Logger::Thread) __NAME(<< name ()) << ": CondVar::signal ()" << endl; __mtdebug_unlock(); }#endif // MTDEBUG pthread_cond_signal(&_cond); }; //@}protected: pthread_cond_t _cond; //!< The pthread condition variable MICOMT::Mutex* _mutex; //!< The mutex which will condition use};//// reader/writer lock///*! * \ingroup micomt * * The RWLock class implements a mutex-like object that can be locked * for either reading or writing. */class RWLock#ifdef DEBUG_NAMES : public NamedObject#endif // DEBUG_NAMES{public: //! \name Constructor/Destructor //@{ RWLock(); ~RWLock(); //@} /*! * The rdlock method locks the reading side of the lock. */ void rdlock() {#ifdef MTDEBUG if (MICO::Logger::IsLogged (MICO::Logger::Thread)) { __mtdebug_lock(); MICO::Logger::Stream (MICO::Logger::Thread) __NAME(<< name ()) << ": RWLock::rdlock ()" << endl; __mtdebug_unlock(); }#endif // MTDEBUG pthread_rwlock_rdlock(&_rwlock); } /*! * The wrlock method locks the writing side of the lock. */ void wrlock() {#ifdef MTDEBUG if (MICO::Logger::IsLogged (MICO::Logger::Thread)) { __mtdebug_lock(); MICO::Logger::Stream (MICO::Logger::Thread) __NAME(<< name ()) << ": RWLock::wrlock ()" << endl; __mtdebug_unlock(); }#endif // MTDEBUG pthread_rwlock_wrlock(&_rwlock); } /*! * The unlock method releases the lock. */ void unlock() {#ifdef MTDEBUG if (MICO::Logger::IsLogged (MICO::Logger::Thread)) { __mtdebug_lock(); MICO::Logger::Stream (MICO::Logger::Thread) __NAME(<< name ()) << ": RWLock::unlock ()" << endl; __mtdebug_unlock(); }#endif // MTDEBUG pthread_rwlock_unlock(&_rwlock); }private: pthread_rwlock_t _rwlock; //!< The pthread read/write lock};//// Semaphore///*! * \ingroup micomt * * The semaphore class is a synchronization object. A semaphore is a * counter for resources shared between threads. */#if defined(HAVE_SEMAPHORE_H) && !(defined(__APPLE__) && defined(__MACH__))// the OS provides POSIX semaphore implementation// in semaphore.h header file// kcg: in the case of MacOS X 10.2 (Darwin 6.8) we have an issue with// POSIX semaphore initialization, so we use MICO's own semaphore// implementation on this platformclass Semaphore#ifdef DEBUG_NAMES : public NamedObject#endif // DEBUG_NAMES{private: sem_t _s; //!< The system semaphorepublic: /*! * \enum ErrorType * * Error types associated with a semaphore. */ enum ErrorType { NoError, //!< No error on semaphore NoPermission, //!< Permission denied TryAgain, //!< Try again SemInvalid, //!< Invalide semaphore Interrupted, //!< Interrupted by signal UnknownError //!< Unknow error }; //! \name Constructor/Destructor //@{ Semaphore(unsigned int val = 0); ~Semaphore(); //@} //! \name Semaphore Operations //@{ /*! * The wait method waits until the semaphore count is non-zero, * then decrement the count. */ void wait() {#ifdef MTDEBUG if (MICO::Logger::IsLogged (MICO::Logger::Thread)) { __mtdebug_lock(); MICO::Logger::Stream (MICO::Logger::Thread) __NAME(<< name ()) << ": Semaphore::wait ()" << endl; __mtdebug_unlock(); }#endif // MTDEBUG while (sem_wait(&_s) == EINTR) { } } /*! * If the semaphore count is zero, this method will not block. * Instead it returns ErrorType::TryAgain. */ Semaphore::ErrorType trylock() { Semaphore::ErrorType ret = MICOMT::Semaphore::NoError;#ifdef MTDEBUG if (MICO::Logger::IsLogged (MICO::Logger::Thread)) { __mtdebug_lock(); MICO::Logger::Stream (MICO::Logger::Thread) __NAME (<< name ()) << ": Semaphore::trylock ()" << endl; __mtdebug_unlock(); }#endif // MTDEBUG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -