00001 // Copyright (C) 2009, Vaclav Haisman. All rights reserved. 00002 // 00003 // Redistribution and use in source and binary forms, with or without modifica- 00004 // tion, are permitted provided that the following conditions are met: 00005 // 00006 // 1. Redistributions of source code must retain the above copyright notice, 00007 // this list of conditions and the following disclaimer. 00008 // 00009 // 2. Redistributions in binary form must reproduce the above copyright notice, 00010 // this list of conditions and the following disclaimer in the documentation 00011 // and/or other materials provided with the distribution. 00012 // 00013 // THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, 00014 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 00015 // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00016 // APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 00017 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- 00018 // DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00019 // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 00020 // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00021 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00022 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00023 00029 00030 namespace log4cplus { namespace thread { 00031 00032 00033 #define LOG4CPLUS_THROW_RTE(msg) \ 00034 do { detail::syncprims_throw_exception (msg, __FILE__, __LINE__); } while (0) 00035 00036 // 00037 // 00038 // 00039 00040 inline 00041 Mutex::Mutex () 00042 { 00043 int ret = pthread_mutex_init (&mtx, 0); 00044 if (ret != 0) 00045 LOG4CPLUS_THROW_RTE ("Mutex::Mutex"); 00046 } 00047 00048 00049 inline 00050 Mutex::~Mutex () 00051 { 00052 int ret = pthread_mutex_destroy (&mtx); 00053 if (ret != 0) 00054 LOG4CPLUS_THROW_RTE ("Mutex::~Mutex"); 00055 } 00056 00057 00058 inline 00059 void 00060 Mutex::lock () const 00061 { 00062 int ret = pthread_mutex_lock (&mtx); 00063 if (ret != 0) 00064 LOG4CPLUS_THROW_RTE ("Mutex::lock"); 00065 } 00066 00067 00068 inline 00069 void 00070 Mutex::unlock () const 00071 { 00072 int ret = pthread_mutex_unlock (&mtx); 00073 if (ret != 0) 00074 LOG4CPLUS_THROW_RTE ("Mutex::unlock"); 00075 } 00076 00077 00078 // 00079 // 00080 // 00081 00082 inline 00083 Semaphore::Semaphore (unsigned max, unsigned initial) 00084 { 00085 int ret = sem_init (&sem, max, initial); 00086 if (ret != 0) 00087 LOG4CPLUS_THROW_RTE ("Semaphore::Semaphore"); 00088 } 00089 00090 00091 inline 00092 Semaphore::~Semaphore () 00093 try 00094 { 00095 int ret = sem_destroy (&sem); 00096 if (ret != 0) 00097 LOG4CPLUS_THROW_RTE ("Semaphore::~Semaphore"); 00098 } 00099 catch (...) 00100 { } 00101 00102 00103 inline 00104 void 00105 Semaphore::unlock () const 00106 { 00107 int ret = sem_post (&sem); 00108 if (ret != 0) 00109 LOG4CPLUS_THROW_RTE ("Semaphore::unlock"); 00110 } 00111 00112 00113 inline 00114 void 00115 Semaphore::lock () const 00116 { 00117 int ret = sem_wait (&sem); 00118 if (ret != 0) 00119 LOG4CPLUS_THROW_RTE ("Semaphore::lock"); 00120 } 00121 00122 00123 // 00124 // 00125 // 00126 00127 inline 00128 ManualResetEvent::ManualResetEvent (bool sig) 00129 : sigcount (0) 00130 , signaled (sig) 00131 { 00132 int ret = pthread_cond_init (&cv, 0); 00133 if (ret != 0) 00134 LOG4CPLUS_THROW_RTE ("ManualResetEvent::ManualResetEvent"); 00135 } 00136 00137 00138 inline 00139 ManualResetEvent::~ManualResetEvent () 00140 try 00141 { 00142 int ret = pthread_cond_destroy (&cv); 00143 if (ret != 0) 00144 LOG4CPLUS_THROW_RTE ("ManualResetEvent::~ManualResetEvent"); 00145 } 00146 catch (...) 00147 { } 00148 00149 00150 inline 00151 void 00152 ManualResetEvent::signal () const 00153 { 00154 MutexGuard mguard (mtx); 00155 00156 signaled = true; 00157 sigcount += 1; 00158 int ret = pthread_cond_broadcast (&cv); 00159 if (ret != 0) 00160 LOG4CPLUS_THROW_RTE ("ManualResetEVent::signal"); 00161 00162 } 00163 00164 00165 inline 00166 void 00167 ManualResetEvent::wait () const 00168 { 00169 MutexGuard mguard (mtx); 00170 00171 if (! signaled) 00172 { 00173 unsigned prev_count = sigcount; 00174 do 00175 { 00176 int ret = pthread_cond_wait (&cv, &mtx.mtx); 00177 if (ret != 0) 00178 { 00179 mguard.unlock (); 00180 mguard.detach (); 00181 LOG4CPLUS_THROW_RTE ("ManualResetEvent::wait"); 00182 } 00183 } 00184 while (prev_count == sigcount); 00185 } 00186 } 00187 00188 00189 inline 00190 bool 00191 ManualResetEvent::timed_wait (unsigned long msec) const 00192 { 00193 MutexGuard mguard (mtx); 00194 00195 if (! signaled) 00196 { 00197 helpers::Time const wakeup_time (helpers::Time::gettimeofday () 00198 + helpers::Time (msec / 1000, (msec % 1000) * 1000)); 00199 struct timespec const ts = {wakeup_time.sec (), 00200 wakeup_time.usec () * 1000}; 00201 unsigned prev_count = sigcount; 00202 do 00203 { 00204 int ret = pthread_cond_timedwait (&cv, &mtx.mtx, &ts); 00205 switch (ret) 00206 { 00207 case 0: 00208 break; 00209 00210 case ETIMEDOUT: 00211 return false; 00212 00213 default: 00214 mguard.unlock (); 00215 mguard.detach (); 00216 LOG4CPLUS_THROW_RTE ("ManualResetEvent::timed_wait"); 00217 } 00218 } 00219 while (prev_count == sigcount); 00220 } 00221 00222 return true; 00223 } 00224 00225 00226 inline 00227 void 00228 ManualResetEvent::reset () const 00229 { 00230 MutexGuard mguard (mtx); 00231 00232 signaled = false; 00233 } 00234 00235 00236 #undef LOG4CPLUS_THROW_RTE 00237 00238 00239 } } // namespace log4cplus { namespace thread {