Thread_POSIX.cpp

Go to the documentation of this file.
00001 /* ES40 emulator.
00002  * Copyright (C) 2007-2008 by the ES40 Emulator Project
00003  *
00004  * WWW    : http://sourceforge.net/projects/es40
00005  * E-mail : camiel@camicom.com
00006  * 
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00020  * 
00021  * Although this is not required, the author would appreciate being notified of, 
00022  * and receiving any modifications you may make to the source code that might serve
00023  * the general public.
00024  */
00025 
00037 //
00038 // Thread_POSIX.cpp
00039 //
00040 // $Id: Thread_POSIX.cpp,v 1.1 2008/03/31 19:13:34 iamcamiel Exp $
00041 //
00042 // Library: Foundation
00043 // Package: Threading
00044 // Module:  Thread
00045 //
00046 // Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
00047 // and Contributors.
00048 //
00049 // Permission is hereby granted, free of charge, to any person or organization
00050 // obtaining a copy of the software and accompanying documentation covered by
00051 // this license (the "Software") to use, reproduce, display, distribute,
00052 // execute, and transmit the Software, and to prepare derivative works of the
00053 // Software, and to permit third-parties to whom the Software is furnished to
00054 // do so, all subject to the following:
00055 // 
00056 // The copyright notices in the Software and this entire statement, including
00057 // the above license grant, this restriction and the following disclaimer,
00058 // must be included in all copies of the Software, in whole or in part, and
00059 // all derivative works of the Software, unless such copies or derivative
00060 // works are solely in the form of machine-executable object code generated by
00061 // a source language processor.
00062 // 
00063 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00064 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00065 // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
00066 // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
00067 // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
00068 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00069 // DEALINGS IN THE SOFTWARE.
00070 //
00071 
00072 
00073 #include "VMS/Thread_POSIX.h"
00074 #include "VMS/Exception.h"
00075 #include "VMS/ErrorHandler.h"
00076 #include <signal.h>
00077 
00078 
00079 //
00080 // Block SIGPIPE in main thread.
00081 //
00082 #if defined(POCO_OS_FAMILY_UNIX)
00083 namespace
00084 {
00085         class SignalBlocker
00086         {
00087         public:
00088                 SignalBlocker()
00089                 {
00090                         sigset_t sset;
00091                         sigemptyset(&sset);
00092                         sigaddset(&sset, SIGPIPE); 
00093                         pthread_sigmask(SIG_BLOCK, &sset, 0);
00094                 }
00095                 ~SignalBlocker()
00096                 {
00097                 }
00098         };
00099         
00100         static SignalBlocker signalBlocker;
00101 }
00102 #endif
00103 
00104 
00105 namespace Poco {
00106 
00107 
00108 pthread_key_t ThreadImpl::_currentKey;
00109 bool ThreadImpl::_haveCurrentKey = false;
00110 
00111 
00112 ThreadImpl::ThreadImpl():
00113         _pData(new ThreadData)
00114 {
00115         if (!_haveCurrentKey)
00116         {
00117                 if (pthread_key_create(&_currentKey, NULL))
00118                         throw SystemException("cannot allocate thread context key");
00119                 _haveCurrentKey = true;
00120         }
00121 }
00122 
00123                         
00124 ThreadImpl::~ThreadImpl()
00125 {
00126         if (_pData->pTarget)
00127                 pthread_detach(_pData->thread);
00128 }
00129 
00130 
00131 void ThreadImpl::setPriorityImpl(int prio)
00132 {
00133         if (prio != _pData->prio)
00134         {
00135                 _pData->prio = prio;
00136                 if (_pData->pTarget)
00137                 {
00138                         struct sched_param par;
00139                         par.sched_priority = mapPrio(_pData->prio);
00140                         if (pthread_setschedparam(_pData->thread, SCHED_OTHER, &par))
00141                                 throw SystemException("cannot set thread priority");
00142                 }
00143         }
00144 }
00145 
00146 
00147 void ThreadImpl::startImpl(Runnable& target)
00148 {
00149         if (_pData->pTarget) throw SystemException("thread already running");
00150 
00151         _pData->pTarget = &target;
00152         if (pthread_create(&_pData->thread, NULL, entry, this))
00153         {
00154                 _pData->pTarget = 0;
00155                 throw SystemException("cannot start thread");
00156         }
00157 
00158         if (_pData->prio != PRIO_NORMAL_IMPL)
00159         {
00160                 struct sched_param par;
00161                 par.sched_priority = mapPrio(_pData->prio);
00162                 if (pthread_setschedparam(_pData->thread, SCHED_OTHER, &par))
00163                         throw SystemException("cannot set thread priority");
00164         }
00165 }
00166 
00167 
00168 void ThreadImpl::joinImpl()
00169 {
00170         _pData->done.wait();
00171         void* result;
00172         if (pthread_join(_pData->thread, &result))
00173                 throw SystemException("cannot join thread"); 
00174 }
00175 
00176 
00177 bool ThreadImpl::joinImpl(long milliseconds)
00178 {
00179         if (_pData->done.tryWait(milliseconds))
00180         {
00181                 void* result;
00182                 if (pthread_join(_pData->thread, &result))
00183                         throw SystemException("cannot join thread");
00184                 return true;
00185         }
00186         else return false;
00187 }
00188 
00189 
00190 bool ThreadImpl::isRunningImpl() const
00191 {
00192         return _pData->pTarget != 0;
00193 }
00194 
00195 
00196 ThreadImpl* ThreadImpl::currentImpl()
00197 {
00198         if (_haveCurrentKey)
00199                 return reinterpret_cast<ThreadImpl*>(pthread_getspecific(_currentKey));
00200         else
00201                 return 0;
00202 }
00203 
00204 
00205 void* ThreadImpl::entry(void* pThread)
00206 {
00207         pthread_setspecific(_currentKey, pThread);
00208 
00209 #if defined(POCO_OS_FAMILY_UNIX)
00210         sigset_t sset;
00211         sigemptyset(&sset);
00212         sigaddset(&sset, SIGQUIT);
00213         sigaddset(&sset, SIGTERM);
00214         sigaddset(&sset, SIGPIPE); 
00215         pthread_sigmask(SIG_BLOCK, &sset, 0);
00216 #endif
00217 
00218         ThreadImpl* pThreadImpl = reinterpret_cast<ThreadImpl*>(pThread);
00219         AutoPtr<ThreadData> pData = pThreadImpl->_pData;
00220         try
00221         {
00222                 pData->pTarget->run();
00223         }
00224         catch (Exception& exc)
00225         {
00226                 ErrorHandler::handle(exc);
00227         }
00228         catch (std::exception& exc)
00229         {
00230                 ErrorHandler::handle(exc);
00231         }
00232         catch (...)
00233         {
00234                 ErrorHandler::handle();
00235         }
00236         pData->pTarget = 0;
00237         pData->done.set();
00238         return 0;
00239 }
00240 
00241 
00242 int ThreadImpl::mapPrio(int prio)
00243 {
00244 #if defined(__VMS) || defined(__digital__)
00245         static const int pmin = PRI_OTHER_MIN;
00246         static const int pmax = PRI_OTHER_MAX;
00247 #else
00248         static const int pmin = sched_get_priority_min(SCHED_OTHER);
00249         static const int pmax = sched_get_priority_max(SCHED_OTHER);
00250 #endif
00251 
00252         switch (prio)
00253         {
00254         case PRIO_LOWEST_IMPL:
00255                 return pmin;
00256         case PRIO_LOW_IMPL:
00257                 return pmin + (pmax - pmin)/4;
00258         case PRIO_NORMAL_IMPL:
00259                 return pmin + (pmax - pmin)/2;
00260         case PRIO_HIGH_IMPL:
00261                 return pmin + 3*(pmax - pmin)/4;
00262         case PRIO_HIGHEST_IMPL:
00263                 return pmax;
00264         default:
00265                 poco_bugcheck_msg("invalid thread priority");
00266         }
00267         return -1; // just to satisfy compiler - we'll never get here anyway
00268 }
00269 
00270 
00271 } // namespace Poco

SourceForge.net Logo
Project space on SourceForge.net