Vault  4.1
vthread_platform.cpp
Go to the documentation of this file.
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 

Copyright ©1997-2014 Trygve Isaacson. All rights reserved. This documentation was generated with Doxygen.