// $Id: PThread.cxx,v 1.12 1999/09/16 16:41:34 yoonforh Exp $ ///////////////////////////////////////////////////////////////////////////// /* * Copyright (c) 1998-2002 Yoon Kyung Koo(yoonforh@yahoo.com). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL YOON KYUNG KOO OR THE OTHER * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // a Thread class implementation // // NOTE // This posix thread class implementation is based upon // POSIX.1c standards(draft 10). // Using this class in prior draft environments // without serious revision could lead to malfunction. // This implementation lacks of thread attribute support. // Several enhancements are added in UI thread version. // Should apply those enhancements in this pthread class impl. // TODO // -. DG/UX (draft 6) sets error number in errno variable // but standard PTHREAD DOES NOT SET errno BUT pass // as a RETURN VALUE!!! // so, this Thread class DOES NOT SUPPORT DG/UX // /// ///////////////////////////////////////////////////////////////////////////// // // // AUTHOR : Yoon Kyung Koo (yoonforh@yahoo.com) // // // ///////////////////////////////////////////////////////////////////////////// #include #include "Thread.hxx" /** * Semaphore class * semaphore wrapper class * implementation */ #define THREAD_SCOPE 0 Semaphore::Semaphore(int value) { if (::sem_init(&sem, THREAD_SCOPE, value)<0) cerr << "sem_init:cannot initialize semaphore. " << ::strerror(errno) << endl; } Semaphore::~Semaphore() { if (::sem_destroy(&sem)<0) cerr << "sem_destroy:cannot destroy semaphore. " << ::strerror(errno) << endl; } /** * Mutex class * mutex wrapper class * implementation */ Mutex::Mutex() { int val; if ((val=::pthread_mutex_init(&mutex, NULL))!=0) cerr << "pthread_mutex_init:cannot initialize mutex. " << ::strerror(val) << endl; } Mutex::~Mutex() { int val; if ((val=::pthread_mutex_destroy(&mutex))!=0) cerr << "pthread_mutex_destroy:cannot destroy mutex. " << ::strerror(val) << endl; } /** * CondVar class * condition variable wrapper class * implementation */ CondVar::CondVar(Mutex& mutex) : mutex(mutex) { int val; if ((val=::pthread_cond_init(&cv, NULL))!=0) cerr << "pthread_cond_init:cannot initialize cv. " << ::strerror(val) << endl; } CondVar::~CondVar() { int val; if ((val=::pthread_cond_destroy(&cv))!=0) cerr << "pthread_cond_destroy:Cannot destroy cv. " << ::strerror(val) << endl; } /** * Thread class * thread wrapper class * implementation * TO DO * -. support for TSD(thread specific data) * -. support for ThreadAttr * (currently only stack size supported) */ Thread::Thread(const string& name, int stackSize=0) : name(name),status(THREAD_STATUS_NORMAL),running(false) { int val; if ((val=::pthread_attr_init(&attr))!=0) { cerr << "pthread_attr_init:cannot initialize thread attribute. " << ::strerror(val) << endl; status = THREAD_STATUS_FATAL; return; } if (stackSize > 0) if ((val=::pthread_attr_setstacksize(&attr, stackSize))!=0) { cerr << "pthread_attr_setstacksize failed. " << ::strerror(val) << endl; status = THREAD_STATUS_FATAL; return; } init(); } // destructor Thread::~Thread() { cancel(); cleanup(); } // do nothing... void Thread::run() { #ifdef DEBUG cerr << "virtual Thread::run() called..." << endl; #endif } // member functions /** * init() : write codes what you want to do * before thread start */ void Thread::init() { #ifdef DEBUG cerr << "[virtual] init" << endl; #endif } /** * cleanup() : write codes what you want to do * after thread quit */ void Thread::cleanup() { #ifdef DEBUG cerr << "[virtual] cleanup" << endl; #endif // by default detach thread // this function assumes that this thread was running in non-detached mode detach(); } /** * Thread::_run() : * private/static method invoking this thread object's run() method */ void * Thread::_run(void * arg) { // NOTE: do not use global scope symbol '::' in front of macros // pthread_cleanup_push or pthread_cleanup_pop // they does some freakish hacks pthread_cleanup_push(_cleanup, arg); // should be provided in pair with cleanup_pop ((Thread *)arg)->run(); ((Thread *)arg)->setFatalStatus(); // after run, thread exits pthread_cleanup_pop(1); // should be provided in pair with cleanup_push return NULL; }