Line data Source code
1 :
2 : /* Copyright (c) 2010-2012, Stefan Eilemann <eile@eyescale.ch>
3 : *
4 : * This library is free software; you can redistribute it and/or modify it under
5 : * the terms of the GNU Lesser General Public License version 2.1 as published
6 : * by the Free Software Foundation.
7 : *
8 : * This library is distributed in the hope that it will be useful, but WITHOUT
9 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11 : * details.
12 : *
13 : * You should have received a copy of the GNU Lesser General Public License
14 : * along with this library; if not, write to the Free Software Foundation, Inc.,
15 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 : */
17 :
18 : #include "condition.h"
19 : #include "debug.h"
20 : #include "time.h"
21 :
22 : #include <cstring>
23 : #include <errno.h>
24 :
25 : #ifdef _WIN32
26 : # include "condition_w32.ipp"
27 : #else
28 : # include <pthread.h>
29 : # include <sys/time.h>
30 : #endif
31 :
32 : namespace lunchbox
33 : {
34 : namespace detail
35 : {
36 : class Condition
37 : {
38 : public:
39 : pthread_mutex_t mutex;
40 : pthread_cond_t cond;
41 : };
42 : }
43 :
44 4190 : Condition::Condition()
45 4190 : : _impl( new detail::Condition )
46 : {
47 : // mutex init
48 4190 : int error = pthread_mutex_init( &_impl->mutex, 0 );
49 4190 : if( error )
50 : {
51 0 : LBERROR << "Error creating pthread mutex: " << strerror( error )
52 0 : << std::endl;
53 0 : return;
54 : }
55 :
56 : // condvar init
57 4190 : error = pthread_cond_init( &_impl->cond, 0 );
58 4190 : if( error )
59 : {
60 0 : LBERROR << "Error creating pthread condition: " << strerror( error )
61 0 : << std::endl;
62 0 : return;
63 : }
64 : }
65 :
66 4190 : Condition::~Condition()
67 : {
68 4190 : int error = pthread_mutex_destroy( &_impl->mutex );
69 4190 : if( error )
70 0 : LBERROR << "Error destroying pthread mutex: " << strerror( error )
71 0 : << std::endl;
72 :
73 4190 : error = pthread_cond_destroy( &_impl->cond );
74 4190 : if( error )
75 0 : LBERROR << "Error destroying pthread condition: " << strerror( error )
76 0 : << std::endl;
77 :
78 4190 : delete _impl;
79 4190 : }
80 :
81 47238884 : void Condition::lock()
82 : {
83 47238884 : pthread_mutex_lock( &_impl->mutex );
84 47239490 : }
85 :
86 23108800 : void Condition::signal()
87 : {
88 23108800 : pthread_cond_signal( &_impl->cond );
89 23108800 : }
90 :
91 817875 : void Condition::broadcast()
92 : {
93 817875 : pthread_cond_broadcast( &_impl->cond );
94 817881 : }
95 :
96 47239480 : void Condition::unlock()
97 : {
98 47239480 : pthread_mutex_unlock( &_impl->mutex );
99 47238738 : }
100 :
101 458183 : void Condition::wait()
102 : {
103 458183 : pthread_cond_wait( &_impl->cond, &_impl->mutex );
104 458183 : }
105 :
106 4166 : bool Condition::timedWait( const uint32_t timeout )
107 : {
108 4166 : if( timeout == LB_TIMEOUT_INDEFINITE )
109 : {
110 4133 : wait();
111 4133 : return true;
112 : }
113 :
114 : const uint32_t time = timeout == LB_TIMEOUT_DEFAULT ?
115 33 : 300000 /* 5 min */ : timeout;
116 :
117 : #ifdef _WIN32
118 : int error = pthread_cond_timedwait_w32_np( &_impl->cond, &_impl->mutex,
119 : time );
120 : #else
121 33 : const timespec delta = convertToTimespec( time );
122 : timeval now;
123 33 : gettimeofday( &now, 0 );
124 :
125 : timespec then;
126 33 : then.tv_sec = delta.tv_sec + now.tv_sec;
127 33 : then.tv_nsec = delta.tv_nsec + now.tv_usec * 1000;
128 69 : while( then.tv_nsec > 1000000000 )
129 : {
130 3 : ++then.tv_sec;
131 3 : then.tv_nsec -= 1000000000;
132 : }
133 :
134 33 : int error = pthread_cond_timedwait( &_impl->cond, &_impl->mutex, &then );
135 : #endif
136 33 : if( error == ETIMEDOUT )
137 33 : return false;
138 :
139 0 : if( error )
140 0 : LBERROR << "pthread_cond_timedwait failed: " << strerror( error )
141 0 : << std::endl;
142 0 : return true;
143 : }
144 :
145 87 : }
|