00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
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
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 = ⌖
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;
00268 }
00269
00270
00271 }