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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libstdc++-v3/] [include/] [std/] [mutex] - Blame information for rev 742

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 742 jeremybenn
//  -*- C++ -*-
2
 
3
// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
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 include/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  // for std::swap
48
 
49
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
50
 
51
namespace std _GLIBCXX_VISIBILITY(default)
52
{
53
_GLIBCXX_BEGIN_NAMESPACE_VERSION
54
 
55
  // Common base class for std::mutex and std::timed_mutex
56
  class __mutex_base
57
  {
58
  protected:
59
    typedef __gthread_mutex_t                   __native_type;
60
 
61
#ifdef __GTHREAD_MUTEX_INIT
62
    __native_type  _M_mutex = __GTHREAD_MUTEX_INIT;
63
 
64
    constexpr __mutex_base() noexcept = default;
65
#else
66
    __native_type  _M_mutex;
67
 
68
    __mutex_base() noexcept
69
    {
70
      // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
71
      __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
72
    }
73
 
74
    ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); }
75
#endif
76
 
77
    __mutex_base(const __mutex_base&) = delete;
78
    __mutex_base& operator=(const __mutex_base&) = delete;
79
  };
80
 
81
  // Common base class for std::recursive_mutex and std::timed_recursive_mutex
82
  class __recursive_mutex_base
83
  {
84
  protected:
85
    typedef __gthread_recursive_mutex_t         __native_type;
86
 
87
    __recursive_mutex_base(const __recursive_mutex_base&) = delete;
88
    __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
89
 
90
#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
91
    __native_type  _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
92
 
93
    __recursive_mutex_base() = default;
94
#else
95
    __native_type  _M_mutex;
96
 
97
    __recursive_mutex_base()
98
    {
99
      // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
100
      __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
101
    }
102
 
103
    ~__recursive_mutex_base()
104
    { _S_destroy(&_M_mutex); }
105
 
106
  private:
107
    // FIXME: gthreads doesn't define __gthread_recursive_mutex_destroy
108
    // so we need to obtain a __gthread_mutex_t to destroy
109
 
110
    // matches when there's only one mutex type
111
    template
112
      static
113
      typename enable_if::value, void>::type
114
      _S_destroy(_Rm* __mx)
115
      { __gthread_mutex_destroy(__mx); }
116
 
117
    // matches a recursive mutex with a member 'actual'
118
    template
119
      static typename enable_if::type
120
      _S_destroy(_Rm* __mx)
121
      { __gthread_mutex_destroy(&__mx->actual); }
122
 
123
    // matches a gthr-win32.h recursive mutex
124
    template
125
      static typename enable_if::type
126
      _S_destroy(_Rm* __mx)
127
      {
128
        __gthread_mutex_t __tmp;
129
        _S_destroy_win32(&__tmp, __mx);
130
      }
131
 
132
    template
133
      static void
134
      _S_destroy_win32(_Mx* __mx, _Rm const* __rmx)
135
      {
136
        __mx->counter = __rmx->counter;
137
        __mx->sema = __rmx->sema;
138
        __gthread_mutex_destroy(__mx);
139
      }
140
#endif
141
  };
142
 
143
  /**
144
   * @defgroup mutexes Mutexes
145
   * @ingroup concurrency
146
   *
147
   * Classes for mutex support.
148
   * @{
149
   */
150
 
151
  /// mutex
152
  class mutex : private __mutex_base
153
  {
154
  public:
155
    typedef __native_type*                      native_handle_type;
156
 
157
#ifdef __GTHREAD_MUTEX_INIT
158
    constexpr
159
#endif
160
    mutex() noexcept = default;
161
    ~mutex() = default;
162
 
163
    mutex(const mutex&) = delete;
164
    mutex& operator=(const mutex&) = delete;
165
 
166
    void
167
    lock()
168
    {
169
      int __e = __gthread_mutex_lock(&_M_mutex);
170
 
171
      // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
172
      if (__e)
173
        __throw_system_error(__e);
174
    }
175
 
176
    bool
177
    try_lock() noexcept
178
    {
179
      // XXX EINVAL, EAGAIN, EBUSY
180
      return !__gthread_mutex_trylock(&_M_mutex);
181
    }
182
 
183
    void
184
    unlock()
185
    {
186
      // XXX EINVAL, EAGAIN, EPERM
187
      __gthread_mutex_unlock(&_M_mutex);
188
    }
189
 
190
    native_handle_type
191
    native_handle()
192
    { return &_M_mutex; }
193
  };
194
 
195
  /// recursive_mutex
196
  class recursive_mutex : private __recursive_mutex_base
197
  {
198
  public:
199
    typedef __native_type*                      native_handle_type;
200
 
201
    recursive_mutex() = default;
202
    ~recursive_mutex() = default;
203
 
204
    recursive_mutex(const recursive_mutex&) = delete;
205
    recursive_mutex& operator=(const recursive_mutex&) = delete;
206
 
207
    void
208
    lock()
209
    {
210
      int __e = __gthread_recursive_mutex_lock(&_M_mutex);
211
 
212
      // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
213
      if (__e)
214
        __throw_system_error(__e);
215
    }
216
 
217
    bool
218
    try_lock() noexcept
219
    {
220
      // XXX EINVAL, EAGAIN, EBUSY
221
      return !__gthread_recursive_mutex_trylock(&_M_mutex);
222
    }
223
 
224
    void
225
    unlock()
226
    {
227
      // XXX EINVAL, EAGAIN, EBUSY
228
      __gthread_recursive_mutex_unlock(&_M_mutex);
229
    }
230
 
231
    native_handle_type
232
    native_handle()
233
    { return &_M_mutex; }
234
  };
235
 
236
#if _GTHREAD_USE_MUTEX_TIMEDLOCK
237
  /// timed_mutex
238
  class timed_mutex : private __mutex_base
239
  {
240
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
241
    typedef chrono::steady_clock                __clock_t;
242
#else
243
    typedef chrono::high_resolution_clock       __clock_t;
244
#endif
245
 
246
  public:
247
    typedef __native_type*                      native_handle_type;
248
 
249
    timed_mutex() = default;
250
    ~timed_mutex() = default;
251
 
252
    timed_mutex(const timed_mutex&) = delete;
253
    timed_mutex& operator=(const timed_mutex&) = delete;
254
 
255
    void
256
    lock()
257
    {
258
      int __e = __gthread_mutex_lock(&_M_mutex);
259
 
260
      // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
261
      if (__e)
262
        __throw_system_error(__e);
263
    }
264
 
265
    bool
266
    try_lock() noexcept
267
    {
268
      // XXX EINVAL, EAGAIN, EBUSY
269
      return !__gthread_mutex_trylock(&_M_mutex);
270
    }
271
 
272
    template 
273
      bool
274
      try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
275
      { return __try_lock_for_impl(__rtime); }
276
 
277
    template 
278
      bool
279
      try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
280
      {
281
        chrono::time_point<_Clock, chrono::seconds> __s =
282
          chrono::time_point_cast(__atime);
283
 
284
        chrono::nanoseconds __ns =
285
          chrono::duration_cast(__atime - __s);
286
 
287
        __gthread_time_t __ts = {
288
          static_cast(__s.time_since_epoch().count()),
289
          static_cast(__ns.count())
290
        };
291
 
292
        return !__gthread_mutex_timedlock(&_M_mutex, &__ts);
293
      }
294
 
295
    void
296
    unlock()
297
    {
298
      // XXX EINVAL, EAGAIN, EBUSY
299
      __gthread_mutex_unlock(&_M_mutex);
300
    }
301
 
302
    native_handle_type
303
    native_handle()
304
    { return &_M_mutex; }
305
 
306
  private:
307
    template
308
      typename enable_if<
309
        ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
310
      __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
311
      {
312
        __clock_t::time_point __atime = __clock_t::now()
313
          + chrono::duration_cast<__clock_t::duration>(__rtime);
314
 
315
        return try_lock_until(__atime);
316
      }
317
 
318
    template 
319
      typename enable_if<
320
        !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
321
      __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
322
      {
323
        __clock_t::time_point __atime = __clock_t::now()
324
          + ++chrono::duration_cast<__clock_t::duration>(__rtime);
325
 
326
        return try_lock_until(__atime);
327
      }
328
  };
329
 
330
  /// recursive_timed_mutex
331
  class recursive_timed_mutex : private __recursive_mutex_base
332
  {
333
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
334
    typedef chrono::steady_clock                __clock_t;
335
#else
336
    typedef chrono::high_resolution_clock       __clock_t;
337
#endif
338
 
339
  public:
340
    typedef __native_type*                      native_handle_type;
341
 
342
    recursive_timed_mutex() = default;
343
    ~recursive_timed_mutex() = default;
344
 
345
    recursive_timed_mutex(const recursive_timed_mutex&) = delete;
346
    recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
347
 
348
    void
349
    lock()
350
    {
351
      int __e = __gthread_recursive_mutex_lock(&_M_mutex);
352
 
353
      // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
354
      if (__e)
355
        __throw_system_error(__e);
356
    }
357
 
358
    bool
359
    try_lock() noexcept
360
    {
361
      // XXX EINVAL, EAGAIN, EBUSY
362
      return !__gthread_recursive_mutex_trylock(&_M_mutex);
363
    }
364
 
365
    template 
366
      bool
367
      try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
368
      { return __try_lock_for_impl(__rtime); }
369
 
370
    template 
371
      bool
372
      try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
373
      {
374
        chrono::time_point<_Clock, chrono::seconds>  __s =
375
          chrono::time_point_cast(__atime);
376
 
377
        chrono::nanoseconds __ns =
378
          chrono::duration_cast(__atime - __s);
379
 
380
        __gthread_time_t __ts = {
381
          static_cast(__s.time_since_epoch().count()),
382
          static_cast(__ns.count())
383
        };
384
 
385
        return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts);
386
      }
387
 
388
    void
389
    unlock()
390
    {
391
      // XXX EINVAL, EAGAIN, EBUSY
392
      __gthread_recursive_mutex_unlock(&_M_mutex);
393
    }
394
 
395
    native_handle_type
396
    native_handle()
397
    { return &_M_mutex; }
398
 
399
  private:
400
    template
401
      typename enable_if<
402
        ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
403
      __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
404
      {
405
        __clock_t::time_point __atime = __clock_t::now()
406
          + chrono::duration_cast<__clock_t::duration>(__rtime);
407
 
408
        return try_lock_until(__atime);
409
      }
410
 
411
    template 
412
      typename enable_if<
413
        !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
414
      __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
415
      {
416
        __clock_t::time_point __atime = __clock_t::now()
417
          + ++chrono::duration_cast<__clock_t::duration>(__rtime);
418
 
419
        return try_lock_until(__atime);
420
      }
421
  };
422
#endif
423
 
424
  /// Do not acquire ownership of the mutex.
425
  struct defer_lock_t { };
426
 
427
  /// Try to acquire ownership of the mutex without blocking.
428
  struct try_to_lock_t { };
429
 
430
  /// Assume the calling thread has already obtained mutex ownership
431
  /// and manage it.
432
  struct adopt_lock_t { };
433
 
434
  constexpr defer_lock_t        defer_lock { };
435
  constexpr try_to_lock_t       try_to_lock { };
436
  constexpr adopt_lock_t        adopt_lock { };
437
 
438
  /// @brief  Scoped lock idiom.
439
  // Acquire the mutex here with a constructor call, then release with
440
  // the destructor call in accordance with RAII style.
441
  template
442
    class lock_guard
443
    {
444
    public:
445
      typedef _Mutex mutex_type;
446
 
447
      explicit lock_guard(mutex_type& __m) : _M_device(__m)
448
      { _M_device.lock(); }
449
 
450
      lock_guard(mutex_type& __m, adopt_lock_t) : _M_device(__m)
451
      { } // calling thread owns mutex
452
 
453
      ~lock_guard()
454
      { _M_device.unlock(); }
455
 
456
      lock_guard(const lock_guard&) = delete;
457
      lock_guard& operator=(const lock_guard&) = delete;
458
 
459
    private:
460
      mutex_type&  _M_device;
461
    };
462
 
463
  /// unique_lock
464
  template
465
    class unique_lock
466
    {
467
    public:
468
      typedef _Mutex mutex_type;
469
 
470
      unique_lock() noexcept
471
      : _M_device(0), _M_owns(false)
472
      { }
473
 
474
      explicit unique_lock(mutex_type& __m)
475
      : _M_device(&__m), _M_owns(false)
476
      {
477
        lock();
478
        _M_owns = true;
479
      }
480
 
481
      unique_lock(mutex_type& __m, defer_lock_t) noexcept
482
      : _M_device(&__m), _M_owns(false)
483
      { }
484
 
485
      unique_lock(mutex_type& __m, try_to_lock_t)
486
      : _M_device(&__m), _M_owns(_M_device->try_lock())
487
      { }
488
 
489
      unique_lock(mutex_type& __m, adopt_lock_t)
490
      : _M_device(&__m), _M_owns(true)
491
      {
492
        // XXX calling thread owns mutex
493
      }
494
 
495
      template
496
        unique_lock(mutex_type& __m,
497
                    const chrono::time_point<_Clock, _Duration>& __atime)
498
        : _M_device(&__m), _M_owns(_M_device->try_lock_until(__atime))
499
        { }
500
 
501
      template
502
        unique_lock(mutex_type& __m,
503
                    const chrono::duration<_Rep, _Period>& __rtime)
504
        : _M_device(&__m), _M_owns(_M_device->try_lock_for(__rtime))
505
        { }
506
 
507
      ~unique_lock()
508
      {
509
        if (_M_owns)
510
          unlock();
511
      }
512
 
513
      unique_lock(const unique_lock&) = delete;
514
      unique_lock& operator=(const unique_lock&) = delete;
515
 
516
      unique_lock(unique_lock&& __u) noexcept
517
      : _M_device(__u._M_device), _M_owns(__u._M_owns)
518
      {
519
        __u._M_device = 0;
520
        __u._M_owns = false;
521
      }
522
 
523
      unique_lock& operator=(unique_lock&& __u) noexcept
524
      {
525
        if(_M_owns)
526
          unlock();
527
 
528
        unique_lock(std::move(__u)).swap(*this);
529
 
530
        __u._M_device = 0;
531
        __u._M_owns = false;
532
 
533
        return *this;
534
      }
535
 
536
      void
537
      lock()
538
      {
539
        if (!_M_device)
540
          __throw_system_error(int(errc::operation_not_permitted));
541
        else if (_M_owns)
542
          __throw_system_error(int(errc::resource_deadlock_would_occur));
543
        else
544
          {
545
            _M_device->lock();
546
            _M_owns = true;
547
          }
548
      }
549
 
550
      bool
551
      try_lock()
552
      {
553
        if (!_M_device)
554
          __throw_system_error(int(errc::operation_not_permitted));
555
        else if (_M_owns)
556
          __throw_system_error(int(errc::resource_deadlock_would_occur));
557
        else
558
          {
559
            _M_owns = _M_device->try_lock();
560
            return _M_owns;
561
          }
562
      }
563
 
564
      template
565
        bool
566
        try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
567
        {
568
          if (!_M_device)
569
            __throw_system_error(int(errc::operation_not_permitted));
570
          else if (_M_owns)
571
            __throw_system_error(int(errc::resource_deadlock_would_occur));
572
          else
573
            {
574
              _M_owns = _M_device->try_lock_until(__atime);
575
              return _M_owns;
576
            }
577
        }
578
 
579
      template
580
        bool
581
        try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
582
        {
583
          if (!_M_device)
584
            __throw_system_error(int(errc::operation_not_permitted));
585
          else if (_M_owns)
586
            __throw_system_error(int(errc::resource_deadlock_would_occur));
587
          else
588
            {
589
              _M_owns = _M_device->try_lock_for(__rtime);
590
              return _M_owns;
591
            }
592
         }
593
 
594
      void
595
      unlock()
596
      {
597
        if (!_M_owns)
598
          __throw_system_error(int(errc::operation_not_permitted));
599
        else if (_M_device)
600
          {
601
            _M_device->unlock();
602
            _M_owns = false;
603
          }
604
      }
605
 
606
      void
607
      swap(unique_lock& __u) noexcept
608
      {
609
        std::swap(_M_device, __u._M_device);
610
        std::swap(_M_owns, __u._M_owns);
611
      }
612
 
613
      mutex_type*
614
      release() noexcept
615
      {
616
        mutex_type* __ret = _M_device;
617
        _M_device = 0;
618
        _M_owns = false;
619
        return __ret;
620
      }
621
 
622
      bool
623
      owns_lock() const noexcept
624
      { return _M_owns; }
625
 
626
      explicit operator bool() const noexcept
627
      { return owns_lock(); }
628
 
629
      mutex_type*
630
      mutex() const noexcept
631
      { return _M_device; }
632
 
633
    private:
634
      mutex_type*       _M_device;
635
      bool              _M_owns; // XXX use atomic_bool
636
    };
637
 
638
  /// Partial specialization for unique_lock objects.
639
  template
640
    inline void
641
    swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept
642
    { __x.swap(__y); }
643
 
644
  template
645
    struct __unlock_impl
646
    {
647
      template
648
        static void
649
        __do_unlock(tuple<_Lock&...>& __locks)
650
        {
651
          std::get<_Idx>(__locks).unlock();
652
          __unlock_impl<_Idx - 1>::__do_unlock(__locks);
653
        }
654
    };
655
 
656
  template<>
657
    struct __unlock_impl<-1>
658
    {
659
      template
660
        static void
661
        __do_unlock(tuple<_Lock&...>&)
662
        { }
663
    };
664
 
665
  template
666
    unique_lock<_Lock>
667
    __try_to_lock(_Lock& __l)
668
    { return unique_lock<_Lock>(__l, try_to_lock); }
669
 
670
  template
671
    struct __try_lock_impl
672
    {
673
      template
674
        static void
675
        __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
676
        {
677
          __idx = _Idx;
678
          auto __lock = __try_to_lock(std::get<_Idx>(__locks));
679
          if (__lock.owns_lock())
680
            {
681
              __try_lock_impl<_Idx + 1, _Idx + 2 < sizeof...(_Lock)>::
682
                __do_try_lock(__locks, __idx);
683
              if (__idx == -1)
684
                __lock.release();
685
            }
686
        }
687
    };
688
 
689
  template
690
    struct __try_lock_impl<_Idx, false>
691
    {
692
      template
693
        static void
694
        __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
695
        {
696
          __idx = _Idx;
697
          auto __lock = __try_to_lock(std::get<_Idx>(__locks));
698
          if (__lock.owns_lock())
699
            {
700
              __idx = -1;
701
              __lock.release();
702
            }
703
        }
704
    };
705
 
706
  /** @brief Generic try_lock.
707
   *  @param __l1 Meets Mutex requirements (try_lock() may throw).
708
   *  @param __l2 Meets Mutex requirements (try_lock() may throw).
709
   *  @param __l3 Meets Mutex requirements (try_lock() may throw).
710
   *  @return Returns -1 if all try_lock() calls return true. Otherwise returns
711
   *          a 0-based index corresponding to the argument that returned false.
712
   *  @post Either all arguments are locked, or none will be.
713
   *
714
   *  Sequentially calls try_lock() on each argument.
715
   */
716
  template
717
    int
718
    try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
719
    {
720
      int __idx;
721
      auto __locks = std::tie(__l1, __l2, __l3...);
722
      __try
723
      { __try_lock_impl<0>::__do_try_lock(__locks, __idx); }
724
      __catch(...)
725
      { }
726
      return __idx;
727
    }
728
 
729
  /** @brief Generic lock.
730
   *  @param __l1 Meets Mutex requirements (try_lock() may throw).
731
   *  @param __l2 Meets Mutex requirements (try_lock() may throw).
732
   *  @param __l3 Meets Mutex requirements (try_lock() may throw).
733
   *  @throw An exception thrown by an argument's lock() or try_lock() member.
734
   *  @post All arguments are locked.
735
   *
736
   *  All arguments are locked via a sequence of calls to lock(), try_lock()
737
   *  and unlock().  If the call exits via an exception any locks that were
738
   *  obtained will be released.
739
   */
740
  template
741
    void
742
    lock(_L1& __l1, _L2& __l2, _L3&... __l3)
743
    {
744
      while (true)
745
        {
746
          unique_lock<_L1> __first(__l1);
747
          int __idx;
748
          auto __locks = std::tie(__l2, __l3...);
749
          __try_lock_impl<0, sizeof...(_L3)>::__do_try_lock(__locks, __idx);
750
          if (__idx == -1)
751
            {
752
              __first.release();
753
              return;
754
            }
755
        }
756
    }
757
 
758
  /// once_flag
759
  struct once_flag
760
  {
761
  private:
762
    typedef __gthread_once_t __native_type;
763
    __native_type  _M_once = __GTHREAD_ONCE_INIT;
764
 
765
  public:
766
    /// Constructor
767
    constexpr once_flag() noexcept = default;
768
 
769
    /// Deleted copy constructor
770
    once_flag(const once_flag&) = delete;
771
    /// Deleted assignment operator
772
    once_flag& operator=(const once_flag&) = delete;
773
 
774
    template
775
      friend void
776
      call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
777
  };
778
 
779
#ifdef _GLIBCXX_HAVE_TLS
780
  extern __thread void* __once_callable;
781
  extern __thread void (*__once_call)();
782
 
783
  template
784
    inline void
785
    __once_call_impl()
786
    {
787
      (*(_Callable*)__once_callable)();
788
    }
789
#else
790
  extern function __once_functor;
791
 
792
  extern void
793
  __set_once_functor_lock_ptr(unique_lock*);
794
 
795
  extern mutex&
796
  __get_once_mutex();
797
#endif
798
 
799
  extern "C" void __once_proxy(void);
800
 
801
  /// call_once
802
  template
803
    void
804
    call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
805
    {
806
#ifdef _GLIBCXX_HAVE_TLS
807
      auto __bound_functor = std::__bind_simple(std::forward<_Callable>(__f),
808
          std::forward<_Args>(__args)...);
809
      __once_callable = &__bound_functor;
810
      __once_call = &__once_call_impl;
811
#else
812
      unique_lock __functor_lock(__get_once_mutex());
813
      auto __callable = std::__bind_simple(std::forward<_Callable>(__f),
814
          std::forward<_Args>(__args)...);
815
      __once_functor = [&]() { __callable(); };
816
      __set_once_functor_lock_ptr(&__functor_lock);
817
#endif
818
 
819
      int __e = __gthread_once(&(__once._M_once), &__once_proxy);
820
 
821
#ifndef _GLIBCXX_HAVE_TLS
822
      if (__functor_lock)
823
        __set_once_functor_lock_ptr(0);
824
#endif
825
 
826
      if (__e)
827
        __throw_system_error(__e);
828
    }
829
 
830
  // @} group mutexes
831
_GLIBCXX_END_NAMESPACE_VERSION
832
} // namespace
833
 
834
#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
835
 
836
#endif // __GXX_EXPERIMENTAL_CXX0X__
837
 
838
#endif // _GLIBCXX_MUTEX

powered by: WebSVN 2.1.0

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