1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include "sal/config.h"
21
22#include <assert.h>
23
24#include "system.h"
25#include <sal/log.hxx>
26#include <sal/types.h>
27
28#include <osl/conditn.h>
29#include <osl/time.h>
30
31
32typedef struct _oslConditionImpl
33{
34 pthread_cond_t m_Condition;
35 pthread_mutex_t m_Lock;
36 sal_Bool m_State;
37} oslConditionImpl;
38
39
40oslCondition SAL_CALL osl_createCondition()
41{
42 oslConditionImpl* pCond;
43 int nRet=0;
44
45 pCond = (oslConditionImpl*) malloc(sizeof(oslConditionImpl));
46
47 if ( pCond == 0 )
48 {
49 SAL_WARN("sal.osl", "std::bad_alloc in C");
50 return 0;
51 }
52
53 pCond->m_State = sal_False;
54
55 /* init condition variable with default attr. (PTHREAD_PROCESS_PRIVAT) */
56 nRet = pthread_cond_init(&pCond->m_Condition, PTHREAD_CONDATTR_DEFAULT);
57 if ( nRet != 0 )
58 {
59 SAL_WARN(
60 "sal.osl",
61 "pthread_cond_init failed, errno " << nRet << ", \""
62 << strerror(nRet) << '"');
63
64 free(pCond);
65 return 0;
66 }
67
68 nRet = pthread_mutex_init(&pCond->m_Lock, PTHREAD_MUTEXATTR_DEFAULT);
69 if ( nRet != 0 )
70 {
71 SAL_WARN(
72 "sal.osl",
73 "pthread_mutex_init failed, errno " << nRet << ", \""
74 << strerror(nRet) << '"');
75
76 nRet = pthread_cond_destroy(&pCond->m_Condition);
77 SAL_WARN_IF(
78 nRet != 0, "sal.osl",
79 "pthread_cond_destroy failed, errno " << nRet << ", \""
80 << strerror(nRet) << '"');
81
82 free(pCond);
83 pCond = 0;
84 }
85
86 return (oslCondition)pCond;
87}
88
89void SAL_CALL osl_destroyCondition(oslCondition Condition)
90{
91 oslConditionImpl* pCond;
92 int nRet = 0;
93
94 if ( Condition )
95 {
96 pCond = (oslConditionImpl*)Condition;
97
98 nRet = pthread_cond_destroy(&pCond->m_Condition);
99 SAL_WARN_IF(
100 nRet != 0, "sal.osl",
101 "pthread_cond_destroy failed, errno " << nRet << ", \""
102 << strerror(nRet) << '"');
103 nRet = pthread_mutex_destroy(&pCond->m_Lock);
104 SAL_WARN_IF(
105 nRet != 0, "sal.osl",
106 "pthread_mutex_destroy failed, errno " << nRet << ", \""
107 << strerror(nRet) << '"');
108
109 free(Condition);
110 }
111
112 return;
113}
114
115sal_Bool SAL_CALL osl_setCondition(oslCondition Condition)
116{
117 oslConditionImpl* pCond;
118 int nRet=0;
119
120 assert(Condition);
121 pCond = (oslConditionImpl*)Condition;
122
123 if ( pCond == 0 )
124 {
125 return sal_False;
126 }
127
128 nRet = pthread_mutex_lock(&pCond->m_Lock);
129 if ( nRet != 0 )
130 {
131 SAL_WARN(
132 "sal.osl",
133 "pthread_mutex_lock failed, errno " << nRet << ", \""
134 << strerror(nRet) << '"');
135 return sal_False;
136 }
137
138 pCond->m_State = sal_True;
139 nRet = pthread_cond_broadcast(&pCond->m_Condition);
140 if ( nRet != 0 )
141 {
142 SAL_WARN(
143 "sal.osl",
144 "pthread_cond_broadcast failed, errno " << nRet << ", \""
145 << strerror(nRet) << '"');
146 // try to unlock the mutex
147 pthread_mutex_unlock(&pCond->m_Lock);
148 return sal_False;
149 }
150
151 nRet = pthread_mutex_unlock(&pCond->m_Lock);
152 if ( nRet != 0 )
153 {
154 SAL_WARN(
155 "sal.osl",
156 "pthread_mutex_unlock failed, errno " << nRet << ", \""
157 << strerror(nRet) << '"');
158 return sal_False;
159 }
160
161 return sal_True;
162
163}
164
165sal_Bool SAL_CALL osl_resetCondition(oslCondition Condition)
166{
167 oslConditionImpl* pCond;
168 int nRet=0;
169
170 assert(Condition);
171
172 pCond = (oslConditionImpl*)Condition;
173
174 if ( pCond == 0 )
175 {
176 return sal_False;
177 }
178
179 nRet = pthread_mutex_lock(&pCond->m_Lock);
180 if ( nRet != 0 )
181 {
182 SAL_WARN(
183 "sal.osl",
184 "pthread_mutex_lock failed, errno " << nRet << ", \""
185 << strerror(nRet) << '"');
186 return sal_False;
187 }
188
189 pCond->m_State = sal_False;
190
191 nRet = pthread_mutex_unlock(&pCond->m_Lock);
192 if ( nRet != 0 )
193 {
194 SAL_WARN(
195 "sal.osl", "pthread_mutex_unlock failed, errno " << nRet <<", \""
196 << strerror(nRet) << '"');
197 return sal_False;
198 }
199
200 return sal_True;
201}
202
203oslConditionResult SAL_CALL osl_waitCondition(oslCondition Condition, const TimeValue* pTimeout)
204{
205 oslConditionImpl* pCond;
206 int nRet=0;
207 oslConditionResult Result = osl_cond_result_ok;
208
209 assert(Condition);
210 pCond = (oslConditionImpl*)Condition;
211
212 if ( pCond == 0 )
213 {
214 return osl_cond_result_error;
215 }
216
217 nRet = pthread_mutex_lock(&pCond->m_Lock);
218 if ( nRet != 0 )
219 {
220 SAL_WARN(
221 "sal.osl", "pthread_mutex_lock failed, errno " << nRet <<", \""
222 << strerror(nRet) << '"');
223 return osl_cond_result_error;
224 }
225
226 if ( pTimeout )
227 {
228 if ( ! pCond->m_State )
229 {
230 int ret;
231 struct timeval tp;
232 struct timespec to;
233
234 gettimeofday(&tp, NULL);
235
236 SET_TIMESPEC( to, tp.tv_sec + pTimeout->Seconds,
237 tp.tv_usec * 1000 + pTimeout->Nanosec );
238
239 /* spurious wake up prevention */
240 do
241 {
242 ret = pthread_cond_timedwait(&pCond->m_Condition, &pCond->m_Lock, &to);
243 if ( ret != 0 )
244 {
245 if ( ret == ETIME || ret == ETIMEDOUT )
246 {
247 Result = osl_cond_result_timeout;
248 nRet = pthread_mutex_unlock(&pCond->m_Lock);
249 SAL_WARN_IF(
250 nRet != 0, "sal.osl",
251 "pthread_mutex_unlock failed, errno " << nRet
252 << ", \"" << strerror(nRet) << '"');
253
254 return Result;
255 }
256 else if ( ret != EINTR )
257 {
258 Result = osl_cond_result_error;
259 nRet = pthread_mutex_unlock(&pCond->m_Lock);
260 SAL_WARN_IF(
261 nRet != 0, "sal.osl",
262 "pthread_mutex_unlock failed, errno " << nRet
263 << ", \"" << strerror(nRet) << '"');
264 return Result;
265 }
266 }
267 }
268 while ( !pCond->m_State );
269 }
270 }
271 else
272 {
273 while ( !pCond->m_State )
274 {
275 nRet = pthread_cond_wait(&pCond->m_Condition, &pCond->m_Lock);
276 if ( nRet != 0 )
277 {
278 SAL_WARN(
279 "sal.osl",
280 "pthread_cond_wait failed, errno " << nRet << ", \""
281 << strerror(nRet) << '"');
282 Result = osl_cond_result_error;
283 nRet = pthread_mutex_unlock(&pCond->m_Lock);
284 SAL_WARN_IF(
285 nRet != 0, "sal.osl",
286 "pthread_mutex_unlock failed, errno " << nRet << ", \""
287 << strerror(nRet) << '"');
288
289 return Result;
290 }
291 }
292 }
293
294 nRet = pthread_mutex_unlock(&pCond->m_Lock);
295 SAL_WARN_IF(
296 nRet != 0, "sal.osl",
297 "pthread_mutex_unlock failed, errno " << nRet << ", \""
298 << strerror(nRet) << '"');
299
300 return Result;
301}
302
303sal_Bool SAL_CALL osl_checkCondition(oslCondition Condition)
304{
305 sal_Bool State;
306 oslConditionImpl* pCond;
307 int nRet=0;
308
309 assert(Condition);
310 pCond = (oslConditionImpl*)Condition;
311
312 if ( pCond == 0 )
313 {
314 return sal_False;
315 }
316
317 nRet = pthread_mutex_lock(&pCond->m_Lock);
318 SAL_WARN_IF(
319 nRet != 0, "sal.osl",
320 "pthread_mutex_lock failed, errno " << nRet << ", \"" << strerror(nRet)
321 << '"');
322
323 State = pCond->m_State;
324
325 nRet = pthread_mutex_unlock(&pCond->m_Lock);
326 SAL_WARN_IF(
327 nRet != 0, "sal.osl",
328 "pthread_mutex_unlock failed, errno " << nRet << ", \""
329 << strerror(nRet) << '"');
330
331 return State;
332}
333
334
335/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
336