Vault
4.1
|
00001 /* 00002 Copyright c1997-2014 Trygve Isaacson. All rights reserved. 00003 This file is part of the Code Vault version 4.1 00004 http://www.bombaydigital.com/ 00005 License: MIT. See LICENSE.md in the Vault top level directory. 00006 */ 00007 00010 #include "vthread.h" 00011 #include "vtypes_internal_platform.h" 00012 00013 #include "vmutex.h" 00014 #include "vsemaphore.h" 00015 #include "vlogger.h" 00016 #include "vinstant.h" 00017 #include "vexception.h" 00018 00019 #include <sys/time.h> 00020 #include <sys/resource.h> 00021 00022 // VThread platform-specific functions --------------------------------------- 00023 00024 // static 00025 void VThread::threadCreate(VThreadID_Type* threadID, bool createDetached, threadMainFunction threadMainProcPtr, void* threadArgument) { 00026 int result; 00027 pthread_attr_t threadAttributes; 00028 00029 result = ::pthread_attr_init(&threadAttributes); 00030 00031 if (result != 0) { 00032 throw VStackTraceException(VSystemError(result), "VThread::threadCreate: pthread_attr_init() failed."); 00033 } 00034 00035 result = ::pthread_attr_setdetachstate(&threadAttributes, createDetached ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE); 00036 00037 if (result != 0) { 00038 throw VStackTraceException(VSystemError(result), "VThread::threadCreate: pthread_attr_setdetachstate() failed."); 00039 } 00040 00041 result = ::pthread_create(threadID, &threadAttributes, threadMainProcPtr, threadArgument); 00042 00043 if (result != 0) { 00044 // Usually this means we have hit the limit of threads allowed per process. 00045 // Log our statistics. Maybe we have a thread handle leak. 00046 throw VStackTraceException(VSystemError(result), "VThread::threadCreate: pthread_create failed. Likely due to lack of resources."); 00047 } 00048 00049 (void) ::pthread_attr_destroy(&threadAttributes); 00050 } 00051 00052 // static 00053 #ifdef VTHREAD_PTHREAD_SETNAME_SUPPORTED 00054 void VThread::_threadStarting(const VThread* thread) { 00055 // This API lets us associate our thread name with the native thread resource, so that debugger/crashdump/instruments etc. can see our thread name. 00056 (void)/*int result =*/ ::pthread_setname_np(thread->getName()); // "np" indicates API is non-POSIX 00057 } 00058 #else 00059 void VThread::_threadStarting(const VThread* /*thread*/) { 00060 // Nothing to do if pthread_setname_np() is not available. 00061 } 00062 #endif 00063 00064 // static 00065 void VThread::_threadEnded(const VThread* /*thread*/) { 00066 // Nothing to do for unix version. 00067 } 00068 00069 // static 00070 void VThread::threadExit() { 00071 ::pthread_exit(NULL); 00072 } 00073 00074 // static 00075 bool VThread::threadJoin(VThreadID_Type threadID, void** value) { 00076 return (::pthread_join(threadID, value) == 0); 00077 } 00078 00079 // static 00080 void VThread::threadDetach(VThreadID_Type threadID) { 00081 ::pthread_detach(threadID); 00082 } 00083 00084 // static 00085 VThreadID_Type VThread::threadSelf() { 00086 return ::pthread_self(); 00087 } 00088 00089 // static 00090 bool VThread::setPriority(int nice) { 00091 return (::setpriority(PRIO_PROCESS, 0, nice) == 0); 00092 } 00093 00094 // static 00095 void VThread::sleep(const VDuration& interval) { 00096 int milliseconds = static_cast<int>(interval.getDurationMilliseconds()); 00097 struct timeval timeout; 00098 timeout.tv_sec = interval.getDurationSeconds(); 00099 timeout.tv_usec = (milliseconds % 1000) * 1000; 00100 00101 (void) ::select(1, NULL, NULL, NULL, &timeout); // 1 means file descriptor [0], will just timeout 00102 } 00103 00104 // static 00105 void VThread::yield() { 00106 #ifdef sun 00107 // On Solaris there is no yield function. 00108 // Simulate by sleeping for 1ms. How to improve? 00109 VThread::sleep(VDuration::MILLISECOND()); 00110 #else 00111 (void) ::sched_yield(); 00112 #endif 00113 } 00114 00115 // VMutex platform-specific functions ---------------------------------------- 00116 00117 // static 00118 bool VMutex::mutexInit(VMutex_Type* mutex) { 00119 return (::pthread_mutex_init(mutex, NULL) == 0); 00120 } 00121 00122 // static 00123 void VMutex::mutexDestroy(VMutex_Type* mutex) { 00124 (void) ::pthread_mutex_destroy(mutex); 00125 } 00126 00127 // static 00128 bool VMutex::mutexLock(VMutex_Type* mutex) { 00129 return (::pthread_mutex_lock(mutex) == 0); 00130 } 00131 00132 // static 00133 bool VMutex::mutexUnlock(VMutex_Type* mutex) { 00134 return (::pthread_mutex_unlock(mutex) == 0); 00135 } 00136 00137 // VSemaphore platform-specific functions ------------------------------------ 00138 00139 // static 00140 bool VSemaphore::semaphoreInit(VSemaphore_Type* semaphore) { 00141 return (pthread_cond_init(semaphore, NULL) == 0); 00142 } 00143 00144 // static 00145 bool VSemaphore::semaphoreDestroy(VSemaphore_Type* semaphore) { 00146 return (pthread_cond_destroy(semaphore) == 0); 00147 } 00148 00149 // static 00150 bool VSemaphore::semaphoreWait(VSemaphore_Type* semaphore, VMutex_Type* mutex, const VDuration& timeoutInterval) { 00151 if (timeoutInterval == VDuration::ZERO()) { 00152 return (pthread_cond_wait(semaphore, mutex) == 0); 00153 } 00154 00155 // The timespec is an absolute time (base is 1970 UTC), not an 00156 // offset from the current time. 00157 VInstant now; 00158 VInstant timeoutWhen = now + timeoutInterval; 00159 Vs64 timeoutValue = timeoutWhen.getValue(); 00160 00161 struct timespec timeoutSpec; 00162 00163 // Convert milliseconds to seconds.nanoseconds. e.g., 1234ms = 1sec + 234,000,000ns 00164 timeoutSpec.tv_sec = static_cast<time_t>(timeoutValue / CONST_S64(1000)); 00165 timeoutSpec.tv_nsec = static_cast<time_t>(CONST_S64(1000000) * (timeoutValue % CONST_S64(1000))); 00166 00167 int result = pthread_cond_timedwait(semaphore, mutex, &timeoutSpec); 00168 00169 return (result == 0) || (result == ETIMEDOUT); 00170 } 00171 00172 // static 00173 bool VSemaphore::semaphoreSignal(VSemaphore_Type* semaphore) { 00174 return (pthread_cond_signal(semaphore) == 0); 00175 } 00176 00177 // static 00178 bool VSemaphore::semaphoreBroadcast(VSemaphore_Type* semaphore) { 00179 return (pthread_cond_broadcast(semaphore) == 0); 00180 } 00181