OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [libstdc++-v3/] [include/] [std/] [mutex] - Blame information for rev 424

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 424 jeremybenn
//  -*- C++ -*-
2
 
3
// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4
// Free Software Foundation, Inc.
5
//
6
// This file is part of the GNU ISO C++ Library.  This library is free
7
// software; you can redistribute it and/or modify it under the
8
// terms of the GNU General Public License as published by the
9
// Free Software Foundation; either version 3, or (at your option)
10
// any later version.
11
 
12
// This library is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
// GNU General Public License for more details.
16
 
17
// Under Section 7 of GPL version 3, you are granted additional
18
// permissions described in the GCC Runtime Library Exception, version
19
// 3.1, as published by the Free Software Foundation.
20
 
21
// You should have received a copy of the GNU General Public License and
22
// a copy of the GCC Runtime Library Exception along with this program;
23
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24
// .
25
 
26
/** @file mutex
27
 *  This is a Standard C++ Library header.
28
 */
29
 
30
#ifndef _GLIBCXX_MUTEX
31
#define _GLIBCXX_MUTEX 1
32
 
33
#pragma GCC system_header
34
 
35
#ifndef __GXX_EXPERIMENTAL_CXX0X__
36
# include 
37
#else
38
 
39
#include 
40
#include 
41
#include 
42
#include 
43
#include 
44
#include 
45
#include 
46
#include 
47
#include 
48
#include  // for std::swap
49
 
50
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
51
 
52
namespace std
53
{
54
  /**
55
   * @defgroup mutexes Mutexes
56
   * @ingroup concurrency
57
   *
58
   * Classes for mutex support.
59
   * @{
60
   */
61
 
62
  /// mutex
63
  class mutex
64
  {
65
    typedef __gthread_mutex_t                   __native_type;
66
    __native_type  _M_mutex;
67
 
68
  public:
69
    typedef __native_type*                      native_handle_type;
70
 
71
    mutex()
72
    {
73
      // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
74
#ifdef __GTHREAD_MUTEX_INIT
75
      __native_type __tmp = __GTHREAD_MUTEX_INIT;
76
      _M_mutex = __tmp;
77
#else
78
      __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
79
#endif
80
    }
81
 
82
    mutex(const mutex&) = delete;
83
    mutex& operator=(const mutex&) = delete;
84
 
85
    void
86
    lock()
87
    {
88
      int __e = __gthread_mutex_lock(&_M_mutex);
89
 
90
      // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
91
      if (__e)
92
        __throw_system_error(__e);
93
    }
94
 
95
    bool
96
    try_lock()
97
    {
98
      // XXX EINVAL, EAGAIN, EBUSY
99
      return !__gthread_mutex_trylock(&_M_mutex);
100
    }
101
 
102
    void
103
    unlock()
104
    {
105
      // XXX EINVAL, EAGAIN, EPERM
106
      __gthread_mutex_unlock(&_M_mutex);
107
    }
108
 
109
    native_handle_type
110
    native_handle()
111
    { return &_M_mutex; }
112
  };
113
 
114
  /// recursive_mutex
115
  class recursive_mutex
116
  {
117
    typedef __gthread_recursive_mutex_t         __native_type;
118
    __native_type  _M_mutex;
119
 
120
  public:
121
    typedef __native_type*                      native_handle_type;
122
 
123
    recursive_mutex()
124
    {
125
      // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
126
#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
127
      __native_type __tmp = __GTHREAD_RECURSIVE_MUTEX_INIT;
128
      _M_mutex = __tmp;
129
#else
130
      __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
131
#endif
132
    }
133
 
134
    recursive_mutex(const recursive_mutex&) = delete;
135
    recursive_mutex& operator=(const recursive_mutex&) = delete;
136
 
137
    void
138
    lock()
139
    {
140
      int __e = __gthread_recursive_mutex_lock(&_M_mutex);
141
 
142
      // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
143
      if (__e)
144
        __throw_system_error(__e);
145
    }
146
 
147
    bool
148
    try_lock()
149
    {
150
      // XXX EINVAL, EAGAIN, EBUSY
151
      return !__gthread_recursive_mutex_trylock(&_M_mutex);
152
    }
153
 
154
    void
155
    unlock()
156
    {
157
      // XXX EINVAL, EAGAIN, EBUSY
158
      __gthread_recursive_mutex_unlock(&_M_mutex);
159
    }
160
 
161
    native_handle_type
162
    native_handle()
163
    { return &_M_mutex; }
164
  };
165
 
166
  /// timed_mutex
167
  class timed_mutex
168
  {
169
    typedef __gthread_mutex_t                   __native_type;
170
 
171
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
172
    typedef chrono::monotonic_clock             __clock_t;
173
#else
174
    typedef chrono::high_resolution_clock       __clock_t;
175
#endif
176
 
177
    __native_type  _M_mutex;
178
 
179
  public:
180
    typedef __native_type*                      native_handle_type;
181
 
182
    timed_mutex()
183
    {
184
#ifdef __GTHREAD_MUTEX_INIT
185
      __native_type __tmp = __GTHREAD_MUTEX_INIT;
186
      _M_mutex = __tmp;
187
#else
188
      __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
189
#endif
190
    }
191
 
192
    timed_mutex(const timed_mutex&) = delete;
193
    timed_mutex& operator=(const timed_mutex&) = delete;
194
 
195
    void
196
    lock()
197
    {
198
      int __e = __gthread_mutex_lock(&_M_mutex);
199
 
200
      // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
201
      if (__e)
202
        __throw_system_error(__e);
203
    }
204
 
205
    bool
206
    try_lock()
207
    {
208
      // XXX EINVAL, EAGAIN, EBUSY
209
      return !__gthread_mutex_trylock(&_M_mutex);
210
    }
211
 
212
    template 
213
      bool
214
      try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
215
      { return __try_lock_for_impl(__rtime); }
216
 
217
    template 
218
      bool
219
      try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
220
      {
221
        chrono::time_point<_Clock, chrono::seconds> __s =
222
          chrono::time_point_cast(__atime);
223
 
224
        chrono::nanoseconds __ns =
225
          chrono::duration_cast(__atime - __s);
226
 
227
        __gthread_time_t __ts = {
228
          static_cast(__s.time_since_epoch().count()),
229
          static_cast(__ns.count())
230
        };
231
 
232
        return !__gthread_mutex_timedlock(&_M_mutex, &__ts);
233
      }
234
 
235
    void
236
    unlock()
237
    {
238
      // XXX EINVAL, EAGAIN, EBUSY
239
      __gthread_mutex_unlock(&_M_mutex);
240
    }
241
 
242
    native_handle_type
243
    native_handle()
244
    { return &_M_mutex; }
245
 
246
  private:
247
    template
248
      typename enable_if<
249
        ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
250
      __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
251
      {
252
        __clock_t::time_point __atime = __clock_t::now()
253
          + chrono::duration_cast<__clock_t::duration>(__rtime);
254
 
255
        return try_lock_until(__atime);
256
      }
257
 
258
    template 
259
      typename enable_if<
260
        !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
261
      __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
262
      {
263
        __clock_t::time_point __atime = __clock_t::now()
264
          + ++chrono::duration_cast<__clock_t::duration>(__rtime);
265
 
266
        return try_lock_until(__atime);
267
      }
268
  };
269
 
270
  /// recursive_timed_mutex
271
  class recursive_timed_mutex
272
  {
273
    typedef __gthread_recursive_mutex_t         __native_type;
274
 
275
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
276
    typedef chrono::monotonic_clock             __clock_t;
277
#else
278
    typedef chrono::high_resolution_clock       __clock_t;
279
#endif
280
 
281
    __native_type  _M_mutex;
282
 
283
  public:
284
    typedef __native_type*                      native_handle_type;
285
 
286
    recursive_timed_mutex()
287
    {
288
      // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
289
#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
290
      __native_type __tmp = __GTHREAD_RECURSIVE_MUTEX_INIT;
291
      _M_mutex = __tmp;
292
#else
293
      __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
294
#endif
295
    }
296
 
297
    recursive_timed_mutex(const recursive_timed_mutex&) = delete;
298
    recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
299
 
300
    void
301
    lock()
302
    {
303
      int __e = __gthread_recursive_mutex_lock(&_M_mutex);
304
 
305
      // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
306
      if (__e)
307
        __throw_system_error(__e);
308
    }
309
 
310
    bool
311
    try_lock()
312
    {
313
      // XXX EINVAL, EAGAIN, EBUSY
314
      return !__gthread_recursive_mutex_trylock(&_M_mutex);
315
    }
316
 
317
    template 
318
      bool
319
      try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
320
      { return __try_lock_for_impl(__rtime); }
321
 
322
    template 
323
      bool
324
      try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
325
      {
326
        chrono::time_point<_Clock, chrono::seconds>  __s =
327
          chrono::time_point_cast(__atime);
328
 
329
        chrono::nanoseconds __ns =
330
          chrono::duration_cast(__atime - __s);
331
 
332
        __gthread_time_t __ts = {
333
          static_cast(__s.time_since_epoch().count()),
334
          static_cast(__ns.count())
335
        };
336
 
337
        return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts);
338
      }
339
 
340
    void
341
    unlock()
342
    {
343
      // XXX EINVAL, EAGAIN, EBUSY
344
      __gthread_recursive_mutex_unlock(&_M_mutex);
345
    }
346
 
347
    native_handle_type
348
    native_handle()
349
    { return &_M_mutex; }
350
 
351
  private:
352
    template
353
      typename enable_if<
354
        ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
355
      __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
356
      {
357
        __clock_t::time_point __atime = __clock_t::now()
358
          + chrono::duration_cast<__clock_t::duration>(__rtime);
359
 
360
        return try_lock_until(__atime);
361
      }
362
 
363
    template 
364
      typename enable_if<
365
        !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
366
      __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
367
      {
368
        __clock_t::time_point __atime = __clock_t::now()
369
          + ++chrono::duration_cast<__clock_t::duration>(__rtime);
370
 
371
        return try_lock_until(__atime);
372
      }
373
  };
374
 
375
  /// Do not acquire ownership of the mutex.
376
  struct defer_lock_t { };
377
 
378
  /// Try to acquire ownership of the mutex without blocking.
379
  struct try_to_lock_t { };
380
 
381
  /// Assume the calling thread has already obtained mutex ownership
382
  /// and manage it.
383
  struct adopt_lock_t { };
384
 
385
  extern const defer_lock_t     defer_lock;
386
  extern const try_to_lock_t    try_to_lock;
387
  extern const adopt_lock_t     adopt_lock;
388
 
389
  /// @brief  Scoped lock idiom.
390
  // Acquire the mutex here with a constructor call, then release with
391
  // the destructor call in accordance with RAII style.
392
  template
393
    class lock_guard
394
    {
395
    public:
396
      typedef _Mutex mutex_type;
397
 
398
      explicit lock_guard(mutex_type& __m) : _M_device(__m)
399
      { _M_device.lock(); }
400
 
401
      lock_guard(mutex_type& __m, adopt_lock_t) : _M_device(__m)
402
      { } // calling thread owns mutex
403
 
404
      ~lock_guard()
405
      { _M_device.unlock(); }
406
 
407
      lock_guard(const lock_guard&) = delete;
408
      lock_guard& operator=(const lock_guard&) = delete;
409
 
410
    private:
411
      mutex_type&  _M_device;
412
    };
413
 
414
  /// unique_lock
415
  template
416
    class unique_lock
417
    {
418
    public:
419
      typedef _Mutex mutex_type;
420
 
421
      unique_lock()
422
      : _M_device(0), _M_owns(false)
423
      { }
424
 
425
      explicit unique_lock(mutex_type& __m)
426
      : _M_device(&__m), _M_owns(false)
427
      {
428
        lock();
429
        _M_owns = true;
430
      }
431
 
432
      unique_lock(mutex_type& __m, defer_lock_t)
433
      : _M_device(&__m), _M_owns(false)
434
      { }
435
 
436
      unique_lock(mutex_type& __m, try_to_lock_t)
437
      : _M_device(&__m), _M_owns(_M_device->try_lock())
438
      { }
439
 
440
      unique_lock(mutex_type& __m, adopt_lock_t)
441
      : _M_device(&__m), _M_owns(true)
442
      {
443
        // XXX calling thread owns mutex
444
      }
445
 
446
      template
447
        unique_lock(mutex_type& __m,
448
                    const chrono::time_point<_Clock, _Duration>& __atime)
449
        : _M_device(&__m), _M_owns(_M_device->try_lock_until(__atime))
450
        { }
451
 
452
      template
453
        unique_lock(mutex_type& __m,
454
                    const chrono::duration<_Rep, _Period>& __rtime)
455
        : _M_device(&__m), _M_owns(_M_device->try_lock_for(__rtime))
456
        { }
457
 
458
      ~unique_lock()
459
      {
460
        if (_M_owns)
461
          unlock();
462
      }
463
 
464
      unique_lock(const unique_lock&) = delete;
465
      unique_lock& operator=(const unique_lock&) = delete;
466
 
467
      unique_lock(unique_lock&& __u)
468
      : _M_device(__u._M_device), _M_owns(__u._M_owns)
469
      {
470
        __u._M_device = 0;
471
        __u._M_owns = false;
472
      }
473
 
474
      unique_lock& operator=(unique_lock&& __u)
475
      {
476
        if(_M_owns)
477
          unlock();
478
 
479
        unique_lock(std::move(__u)).swap(*this);
480
 
481
        __u._M_device = 0;
482
        __u._M_owns = false;
483
 
484
        return *this;
485
      }
486
 
487
      void
488
      lock()
489
      {
490
        if (!_M_device)
491
          __throw_system_error(int(errc::operation_not_permitted));
492
        else if (_M_owns)
493
          __throw_system_error(int(errc::resource_deadlock_would_occur));
494
        else
495
          {
496
            _M_device->lock();
497
            _M_owns = true;
498
          }
499
      }
500
 
501
      bool
502
      try_lock()
503
      {
504
        if (!_M_device)
505
          __throw_system_error(int(errc::operation_not_permitted));
506
        else if (_M_owns)
507
          __throw_system_error(int(errc::resource_deadlock_would_occur));
508
        else
509
          {
510
            _M_owns = _M_device->try_lock();
511
            return _M_owns;
512
          }
513
      }
514
 
515
      template
516
        bool
517
        try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
518
        {
519
          if (!_M_device)
520
            __throw_system_error(int(errc::operation_not_permitted));
521
          else if (_M_owns)
522
            __throw_system_error(int(errc::resource_deadlock_would_occur));
523
          else
524
            {
525
              _M_owns = _M_device->try_lock_until(__atime);
526
              return _M_owns;
527
            }
528
        }
529
 
530
      template
531
        bool
532
        try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
533
        {
534
          if (!_M_device)
535
            __throw_system_error(int(errc::operation_not_permitted));
536
          else if (_M_owns)
537
            __throw_system_error(int(errc::resource_deadlock_would_occur));
538
          else
539
            {
540
              _M_owns = _M_device->try_lock_for(__rtime);
541
              return _M_owns;
542
            }
543
         }
544
 
545
      void
546
      unlock()
547
      {
548
        if (!_M_owns)
549
          __throw_system_error(int(errc::operation_not_permitted));
550
        else if (_M_device)
551
          {
552
            _M_device->unlock();
553
            _M_owns = false;
554
          }
555
      }
556
 
557
      void
558
      swap(unique_lock& __u)
559
      {
560
        std::swap(_M_device, __u._M_device);
561
        std::swap(_M_owns, __u._M_owns);
562
      }
563
 
564
      mutex_type*
565
      release()
566
      {
567
        mutex_type* __ret = _M_device;
568
        _M_device = 0;
569
        _M_owns = false;
570
        return __ret;
571
      }
572
 
573
      bool
574
      owns_lock() const
575
      { return _M_owns; }
576
 
577
      explicit operator bool() const
578
      { return owns_lock(); }
579
 
580
      mutex_type*
581
      mutex() const
582
      { return _M_device; }
583
 
584
    private:
585
      mutex_type*       _M_device;
586
      bool              _M_owns; // XXX use atomic_bool
587
    };
588
 
589
  template
590
    inline void
591
    swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y)
592
    { __x.swap(__y); }
593
 
594
  template
595
    struct __unlock_impl
596
    {
597
      template
598
        static void
599
        __do_unlock(tuple<_Lock&...>& __locks)
600
        {
601
          std::get<_Idx>(__locks).unlock();
602
          __unlock_impl<_Idx - 1>::__do_unlock(__locks);
603
        }
604
    };
605
 
606
  template<>
607
    struct __unlock_impl<-1>
608
    {
609
      template
610
        static void
611
        __do_unlock(tuple<_Lock&...>&)
612
        { }
613
    };
614
 
615
  template
616
    struct __try_lock_impl
617
    {
618
      template
619
        static int
620
        __do_try_lock(tuple<_Lock&...>& __locks)
621
        {
622
          if(std::get<_Idx>(__locks).try_lock())
623
            {
624
              return __try_lock_impl<_Idx + 1,
625
                _Idx + 2 < sizeof...(_Lock)>::__do_try_lock(__locks);
626
            }
627
          else
628
            {
629
              __unlock_impl<_Idx>::__do_unlock(__locks);
630
              return _Idx;
631
            }
632
        }
633
    };
634
 
635
  template
636
    struct __try_lock_impl<_Idx, false>
637
    {
638
      template
639
        static int
640
        __do_try_lock(tuple<_Lock&...>& __locks)
641
        {
642
          if(std::get<_Idx>(__locks).try_lock())
643
            return -1;
644
          else
645
            {
646
              __unlock_impl<_Idx>::__do_unlock(__locks);
647
              return _Idx;
648
            }
649
        }
650
    };
651
 
652
  /** @brief Generic try_lock.
653
   *  @param __l1 Meets Mutex requirements (try_lock() may throw).
654
   *  @param __l2 Meets Mutex requirements (try_lock() may throw).
655
   *  @param __l3 Meets Mutex requirements (try_lock() may throw).
656
   *  @return Returns -1 if all try_lock() calls return true. Otherwise returns
657
   *          a 0-based index corresponding to the argument that returned false.
658
   *  @post Either all arguments are locked, or none will be.
659
   *
660
   *  Sequentially calls try_lock() on each argument.
661
   */
662
  template
663
    int
664
    try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
665
    {
666
      tuple<_Lock1&, _Lock2&, _Lock3&...> __locks(__l1, __l2, __l3...);
667
      return __try_lock_impl<0>::__do_try_lock(__locks);
668
    }
669
 
670
  /// lock
671
  template
672
    void
673
    lock(_L1&, _L2&, _L3&...);
674
 
675
  /// once_flag
676
  struct once_flag
677
  {
678
  private:
679
    typedef __gthread_once_t __native_type;
680
    __native_type  _M_once;
681
 
682
  public:
683
    once_flag()
684
    {
685
      __native_type __tmp = __GTHREAD_ONCE_INIT;
686
      _M_once = __tmp;
687
    }
688
 
689
    once_flag(const once_flag&) = delete;
690
    once_flag& operator=(const once_flag&) = delete;
691
 
692
    template
693
      friend void
694
      call_once(once_flag& __once, _Callable __f, _Args&&... __args);
695
  };
696
 
697
#ifdef _GLIBCXX_HAVE_TLS
698
  extern __thread void* __once_callable;
699
  extern __thread void (*__once_call)();
700
 
701
  template
702
    inline void
703
    __once_call_impl()
704
    {
705
      (*(_Callable*)__once_callable)();
706
    }
707
#else
708
  extern function __once_functor;
709
 
710
  extern void
711
  __set_once_functor_lock_ptr(unique_lock*);
712
 
713
  extern mutex&
714
  __get_once_mutex();
715
#endif
716
 
717
  extern "C" void __once_proxy();
718
 
719
  /// call_once
720
  template
721
    void
722
    call_once(once_flag& __once, _Callable __f, _Args&&... __args)
723
    {
724
#ifdef _GLIBCXX_HAVE_TLS
725
      auto __bound_functor = std::bind(__f, __args...);
726
      __once_callable = &__bound_functor;
727
      __once_call = &__once_call_impl;
728
#else
729
      unique_lock __functor_lock(__get_once_mutex());
730
      __once_functor = std::bind(__f, __args...);
731
      __set_once_functor_lock_ptr(&__functor_lock);
732
#endif
733
 
734
      int __e = __gthread_once(&(__once._M_once), &__once_proxy);
735
 
736
#ifndef _GLIBCXX_HAVE_TLS
737
      if (__functor_lock)
738
        __set_once_functor_lock_ptr(0);
739
#endif
740
 
741
      if (__e)
742
        __throw_system_error(__e);
743
    }
744
 
745
  // @} group mutexes
746
}
747
 
748
#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
749
 
750
#endif // __GXX_EXPERIMENTAL_CXX0X__
751
 
752
#endif // _GLIBCXX_MUTEX

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.