Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/thread/src/mutex.cpp @ 13

Last change on this file since 13 was 12, checked in by landauf, 18 years ago

added boost

File size: 10.2 KB
RevLine 
[12]1// Copyright (C) 2001-2003
2// William E. Kempf
3//
4// Permission to use, copy, modify, distribute and sell this software
5// and its documentation for any purpose is hereby granted without fee,
6// provided that the above copyright notice appear in all copies and
7// that both that copyright notice and this permission notice appear
8// in supporting documentation.  William E. Kempf makes no representations
9// about the suitability of this software for any purpose.
10// It is provided "as is" without express or implied warranty.
11
12#include <boost/thread/detail/config.hpp>
13
14#include <boost/thread/mutex.hpp>
15#include <boost/thread/xtime.hpp>
16#include <boost/thread/thread.hpp>
17#include <boost/thread/exceptions.hpp>
18#include <boost/limits.hpp>
19#include <string>
20#include <stdexcept>
21#include <cassert>
22#include "timeconv.inl"
23
24#if defined(BOOST_HAS_WINTHREADS)
25#   include <new>
26#   include <boost/thread/once.hpp>
27#   include <windows.h>
28#   include <time.h>
29#   include "mutex.inl"
30#elif defined(BOOST_HAS_PTHREADS)
31#   include <errno.h>
32#elif defined(BOOST_HAS_MPTASKS)
33#    include <MacErrors.h>
34#    include "mac/init.hpp"
35#    include "mac/safe.hpp"
36#endif
37
38namespace boost {
39
40#if defined(BOOST_HAS_WINTHREADS)
41
42mutex::mutex()
43    : m_mutex(0)
44    , m_critical_section(false)
45{
46    m_critical_section = true;
47    if (m_critical_section)
48        m_mutex = new_critical_section();
49    else
50        m_mutex = new_mutex(0);
51}
52
53mutex::~mutex()
54{
55    if (m_critical_section)
56        delete_critical_section(m_mutex);
57    else
58        delete_mutex(m_mutex);
59}
60
61void mutex::do_lock()
62{
63    if (m_critical_section)
64        wait_critical_section_infinite(m_mutex);
65    else
66        wait_mutex(m_mutex, INFINITE);
67}
68
69void mutex::do_unlock()
70{
71    if (m_critical_section)
72        release_critical_section(m_mutex);
73    else
74        release_mutex(m_mutex);
75}
76
77void mutex::do_lock(cv_state&)
78{
79    do_lock();
80}
81
82void mutex::do_unlock(cv_state&)
83{
84    do_unlock();
85}
86
87try_mutex::try_mutex()
88    : m_mutex(0)
89    , m_critical_section(false)
90{
91    m_critical_section = has_TryEnterCriticalSection();
92    if (m_critical_section)
93        m_mutex = new_critical_section();
94    else
95        m_mutex = new_mutex(0);
96}
97
98try_mutex::~try_mutex()
99{
100    if (m_critical_section)
101        delete_critical_section(m_mutex);
102    else
103        delete_mutex(m_mutex);
104}
105
106void try_mutex::do_lock()
107{
108    if (m_critical_section)
109        wait_critical_section_infinite(m_mutex);
110    else
111        wait_mutex(m_mutex, INFINITE);
112}
113
114bool try_mutex::do_trylock()
115{
116    if (m_critical_section)
117        return wait_critical_section_try(m_mutex);
118    else
119        return wait_mutex(m_mutex, 0) == WAIT_OBJECT_0;
120}
121
122void try_mutex::do_unlock()
123{
124    if (m_critical_section)
125        release_critical_section(m_mutex);
126    else
127        release_mutex(m_mutex);
128}
129
130void try_mutex::do_lock(cv_state&)
131{
132    do_lock();
133}
134
135void try_mutex::do_unlock(cv_state&)
136{
137    do_unlock();
138}
139
140timed_mutex::timed_mutex()
141    : m_mutex(0)
142{
143    m_mutex = new_mutex(0);
144}
145
146timed_mutex::~timed_mutex()
147{
148    delete_mutex(m_mutex);
149}
150
151void timed_mutex::do_lock()
152{
153    wait_mutex(m_mutex, INFINITE);
154}
155
156bool timed_mutex::do_trylock()
157{
158    return wait_mutex(m_mutex, 0) == WAIT_OBJECT_0;
159}
160
161bool timed_mutex::do_timedlock(const xtime& xt)
162{
163    for (;;)
164    {
165        int milliseconds;
166        to_duration(xt, milliseconds);
167
168        int res = wait_mutex(m_mutex, milliseconds);
169
170        if (res == WAIT_TIMEOUT)
171        {
172            boost::xtime cur;
173            boost::xtime_get(&cur, boost::TIME_UTC);
174            if (boost::xtime_cmp(xt, cur) > 0)
175                continue;
176        }
177
178        return res == WAIT_OBJECT_0;
179    }
180}
181
182void timed_mutex::do_unlock()
183{
184    release_mutex(m_mutex);
185}
186
187void timed_mutex::do_lock(cv_state&)
188{
189    do_lock();
190}
191
192void timed_mutex::do_unlock(cv_state&)
193{
194    do_unlock();
195}
196
197#elif defined(BOOST_HAS_PTHREADS)
198
199mutex::mutex()
200{
201    int res = 0;
202    res = pthread_mutex_init(&m_mutex, 0);
203    if (res != 0)
204        throw thread_resource_error();
205}
206
207mutex::~mutex()
208{
209    int res = 0;
210    res = pthread_mutex_destroy(&m_mutex);
211    assert(res == 0);
212}
213
214void mutex::do_lock()
215{
216    int res = 0;
217    res = pthread_mutex_lock(&m_mutex);
218    if (res == EDEADLK) throw lock_error();
219    assert(res == 0);
220}
221
222void mutex::do_unlock()
223{
224    int res = 0;
225    res = pthread_mutex_unlock(&m_mutex);
226    if (res == EPERM) throw lock_error();
227    assert(res == 0);
228}
229
230void mutex::do_lock(cv_state&)
231{
232}
233
234void mutex::do_unlock(cv_state& state)
235{
236    state.pmutex = &m_mutex;
237}
238
239try_mutex::try_mutex()
240{
241    int res = 0;
242    res = pthread_mutex_init(&m_mutex, 0);
243    if (res != 0)
244        throw thread_resource_error();
245}
246
247try_mutex::~try_mutex()
248{
249    int res = 0;
250    res = pthread_mutex_destroy(&m_mutex);
251    assert(res == 0);
252}
253
254void try_mutex::do_lock()
255{
256    int res = 0;
257    res = pthread_mutex_lock(&m_mutex);
258    if (res == EDEADLK) throw lock_error();
259    assert(res == 0);
260}
261
262bool try_mutex::do_trylock()
263{
264    int res = 0;
265    res = pthread_mutex_trylock(&m_mutex);
266    if (res == EDEADLK) throw lock_error();
267    assert(res == 0 || res == EBUSY);
268    return res == 0;
269}
270
271void try_mutex::do_unlock()
272{
273    int res = 0;
274    res = pthread_mutex_unlock(&m_mutex);
275    if (res == EPERM) throw lock_error();
276    assert(res == 0);
277}
278
279void try_mutex::do_lock(cv_state&)
280{
281}
282
283void try_mutex::do_unlock(cv_state& state)
284{
285    state.pmutex = &m_mutex;
286}
287
288timed_mutex::timed_mutex()
289    : m_locked(false)
290{
291    int res = 0;
292    res = pthread_mutex_init(&m_mutex, 0);
293    if (res != 0)
294        throw thread_resource_error();
295
296    res = pthread_cond_init(&m_condition, 0);
297    if (res != 0)
298    {
299        pthread_mutex_destroy(&m_mutex);
300        throw thread_resource_error();
301    }
302}
303
304timed_mutex::~timed_mutex()
305{
306    assert(!m_locked);
307    int res = 0;
308    res = pthread_mutex_destroy(&m_mutex);
309    assert(res == 0);
310
311    res = pthread_cond_destroy(&m_condition);
312    assert(res == 0);
313}
314
315void timed_mutex::do_lock()
316{
317    int res = 0;
318    res = pthread_mutex_lock(&m_mutex);
319    assert(res == 0);
320
321    while (m_locked)
322    {
323        res = pthread_cond_wait(&m_condition, &m_mutex);
324        assert(res == 0);
325    }
326
327    assert(!m_locked);
328    m_locked = true;
329
330    res = pthread_mutex_unlock(&m_mutex);
331    assert(res == 0);
332}
333
334bool timed_mutex::do_trylock()
335{
336    int res = 0;
337    res = pthread_mutex_lock(&m_mutex);
338    assert(res == 0);
339
340    bool ret = false;
341    if (!m_locked)
342    {
343        m_locked = true;
344        ret = true;
345    }
346
347    res = pthread_mutex_unlock(&m_mutex);
348    assert(res == 0);
349    return ret;
350}
351
352bool timed_mutex::do_timedlock(const xtime& xt)
353{
354    int res = 0;
355    res = pthread_mutex_lock(&m_mutex);
356    assert(res == 0);
357
358    timespec ts;
359    to_timespec(xt, ts);
360
361    while (m_locked)
362    {
363        res = pthread_cond_timedwait(&m_condition, &m_mutex, &ts);
364        assert(res == 0 || res == ETIMEDOUT);
365
366        if (res == ETIMEDOUT)
367            break;
368    }
369
370    bool ret = false;
371    if (!m_locked)
372    {
373        m_locked = true;
374        ret = true;
375    }
376
377    res = pthread_mutex_unlock(&m_mutex);
378    assert(res == 0);
379    return ret;
380}
381
382void timed_mutex::do_unlock()
383{
384    int res = 0;
385    res = pthread_mutex_lock(&m_mutex);
386    assert(res == 0);
387
388    assert(m_locked);
389    m_locked = false;
390
391    res = pthread_cond_signal(&m_condition);
392    assert(res == 0);
393
394    res = pthread_mutex_unlock(&m_mutex);
395    assert(res == 0);
396}
397
398void timed_mutex::do_lock(cv_state&)
399{
400    int res = 0;
401    while (m_locked)
402    {
403        res = pthread_cond_wait(&m_condition, &m_mutex);
404        assert(res == 0);
405    }
406
407    assert(!m_locked);
408    m_locked = true;
409
410    res = pthread_mutex_unlock(&m_mutex);
411    assert(res == 0);
412}
413
414void timed_mutex::do_unlock(cv_state& state)
415{
416    int res = 0;
417    res = pthread_mutex_lock(&m_mutex);
418    assert(res == 0);
419
420    assert(m_locked);
421    m_locked = false;
422
423    res = pthread_cond_signal(&m_condition);
424    assert(res == 0);
425
426    state.pmutex = &m_mutex;
427}
428
429#elif defined(BOOST_HAS_MPTASKS)
430
431using threads::mac::detail::safe_enter_critical_region;
432
433mutex::mutex()
434{
435}
436
437mutex::~mutex()
438{
439}
440
441void mutex::do_lock()
442{
443    OSStatus lStatus = noErr;
444    lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
445        m_mutex_mutex);
446    assert(lStatus == noErr);
447}
448
449void mutex::do_unlock()
450{
451    OSStatus lStatus = noErr;
452    lStatus = MPExitCriticalRegion(m_mutex);
453    assert(lStatus == noErr);
454}
455
456void mutex::do_lock(cv_state& /*state*/)
457{
458    do_lock();
459}
460
461void mutex::do_unlock(cv_state& /*state*/)
462{
463    do_unlock();
464}
465
466try_mutex::try_mutex()
467{
468}
469
470try_mutex::~try_mutex()
471{
472}
473
474void try_mutex::do_lock()
475{
476    OSStatus lStatus = noErr;
477    lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
478        m_mutex_mutex);
479    assert(lStatus == noErr);
480}
481
482bool try_mutex::do_trylock()
483{
484    OSStatus lStatus = noErr;
485    lStatus = MPEnterCriticalRegion(m_mutex, kDurationImmediate);
486    assert(lStatus == noErr || lStatus == kMPTimeoutErr);
487    return lStatus == noErr;
488}
489
490void try_mutex::do_unlock()
491{
492    OSStatus lStatus = noErr;
493    lStatus = MPExitCriticalRegion(m_mutex);
494    assert(lStatus == noErr);
495}
496
497void try_mutex::do_lock(cv_state& /*state*/)
498{
499    do_lock();
500}
501
502void try_mutex::do_unlock(cv_state& /*state*/)
503{
504    do_unlock();
505}
506
507timed_mutex::timed_mutex()
508{
509}
510
511timed_mutex::~timed_mutex()
512{
513}
514
515void timed_mutex::do_lock()
516{
517    OSStatus lStatus = noErr;
518    lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
519        m_mutex_mutex);
520    assert(lStatus == noErr);
521}
522
523bool timed_mutex::do_trylock()
524{
525    OSStatus lStatus = noErr;
526    lStatus = MPEnterCriticalRegion(m_mutex, kDurationImmediate);
527    assert(lStatus == noErr || lStatus == kMPTimeoutErr);
528    return(lStatus == noErr);
529}
530
531bool timed_mutex::do_timedlock(const xtime& xt)
532{
533    int microseconds;
534    to_microduration(xt, microseconds);
535    Duration lDuration = kDurationMicrosecond * microseconds;
536
537    OSStatus lStatus = noErr;
538    lStatus = safe_enter_critical_region(m_mutex, lDuration, m_mutex_mutex);
539    assert(lStatus == noErr || lStatus == kMPTimeoutErr);
540
541    return(lStatus == noErr);
542}
543
544void timed_mutex::do_unlock()
545{
546    OSStatus lStatus = noErr;
547    lStatus = MPExitCriticalRegion(m_mutex);
548    assert(lStatus == noErr);
549}
550
551void timed_mutex::do_lock(cv_state& /*state*/)
552{
553    do_lock();
554}
555
556void timed_mutex::do_unlock(cv_state& /*state*/)
557{
558    do_unlock();
559}
560
561#endif
562
563} // namespace boost
564
565// Change Log:
566//   8 Feb 01  WEKEMPF Initial version.
Note: See TracBrowser for help on using the repository browser.