summaryrefslogtreecommitdiff
path: root/boost/thread/lock_concepts.hpp
blob: d96c3dc1b96bf9e683fcb0c53ffccbb9ee85015b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// (C) Copyright 2012 Vicente Botet
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_THREAD_LOCK_CONCEPTS_HPP
#define BOOST_THREAD_LOCK_CONCEPTS_HPP

#include <boost/thread/lock_traits.hpp>
#include <boost/thread/lock_options.hpp>
#include <boost/thread/lockable_concepts.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/detail/move.hpp>

#include <boost/chrono/chrono.hpp>
#include <boost/concept_check.hpp>
#include <boost/static_assert.hpp>

namespace boost
{

  /**
   * BasicLock object supports the basic features
   * required to delimit a critical region
   * Supports the basic lock, unlock and try_lock functions and
   * defines the lock traits
   */

  template <typename Lk>
  struct BasicLock
  {
    typedef typename Lk::mutex_type mutex_type;
    void cvt_mutex_ptr(mutex_type*) {}
    BOOST_CONCEPT_ASSERT(( BasicLockable<mutex_type> ));

    BOOST_CONCEPT_USAGE(BasicLock)
    {
      const Lk l1(mtx);
      Lk l2(mtx, defer_lock);
      Lk l3(mtx, adopt_lock);
      Lk l4(( Lk()));
      Lk l5(( boost::move(l2)));
      cvt_mutex_ptr(l1.mutex());
      if (l1.owns_lock()) return;
      if (l1) return;
      if (!l1) return;

      l2.lock();
      l2.unlock();
      l2.release();

    }
    BasicLock() :
      mtx(*static_cast<mutex_type*>(0))
    {}
  private:
    BasicLock operator=(BasicLock const&);
    mutex_type& mtx;
  }
  ;

  template <typename Lk>
  struct Lock
  {
    BOOST_CONCEPT_ASSERT(( BasicLock<Lk> ));
    typedef typename Lk::mutex_type mutex_type;
    BOOST_CONCEPT_ASSERT(( Lockable<mutex_type> ));

    BOOST_CONCEPT_USAGE(Lock)
    {
      Lk l1(mtx, try_to_lock);
      if (l1.try_lock()) return;
    }
    Lock() :
      mtx(*static_cast<mutex_type*>(0))
    {}
  private:
    Lock operator=(Lock const&);
    mutex_type& mtx;
  };

  template <typename Lk>
  struct TimedLock
  {
    BOOST_CONCEPT_ASSERT(( Lock<Lk> ));
    typedef typename Lk::mutex_type mutex_type;
    BOOST_CONCEPT_ASSERT(( TimedLockable<mutex_type> ));

    BOOST_CONCEPT_USAGE(TimedLock)
    {
      const Lk l1(mtx, t);
      Lk l2(mtx, d);
      if (l1.try_lock_until(t)) return;
      if (l1.try_lock_for(d)) return;
    }
    TimedLock() :
      mtx(*static_cast<mutex_type*>(0))
    {}
  private:
    TimedLock operator=(TimedLock const&);
    mutex_type& mtx;
    boost::chrono::system_clock::time_point t;
    boost::chrono::system_clock::duration d;
  };

  template <typename Lk>
  struct UniqueLock
  {
    BOOST_CONCEPT_ASSERT(( TimedLock<Lk> ));
    typedef typename Lk::mutex_type mutex_type;

    BOOST_CONCEPT_USAGE(UniqueLock)
    {

    }
    UniqueLock() :
      mtx(*static_cast<mutex_type*>(0))
    {}
  private:
    UniqueLock operator=(UniqueLock const&);
    mutex_type& mtx;
  };

  template <typename Lk>
  struct SharedLock
  {
    BOOST_CONCEPT_ASSERT(( TimedLock<Lk> ));
    typedef typename Lk::mutex_type mutex_type;

    BOOST_CONCEPT_USAGE(SharedLock)
    {
    }
    SharedLock() :
      mtx(*static_cast<mutex_type*>(0))
    {}
  private:
    SharedLock operator=(SharedLock const&);
    mutex_type& mtx;

  };

  template <typename Lk>
  struct UpgradeLock
  {
    BOOST_CONCEPT_ASSERT(( SharedLock<Lk> ));
    typedef typename Lk::mutex_type mutex_type;

    BOOST_CONCEPT_USAGE(UpgradeLock)
    {
    }
    UpgradeLock() :
      mtx(*static_cast<mutex_type*>(0))
    {}
  private:
    UpgradeLock operator=(UpgradeLock const&);
    mutex_type& mtx;
  };

  /**
   * An StrictLock is a scoped lock guard ensuring the mutex is locked on the
   * scope of the lock, by locking the mutex on construction and unlocking it on
   * destruction.
   *
   * Essentially, a StrictLock's role is only to live on the stack as an
   * automatic variable. strict_lock must adhere to a non-copy and non-alias
   * policy. StrictLock disables copying by making the copy constructor and the
   * assignment operator private. While we're at it, let's disable operator new
   * and operator delete; strict locks are not intended to be allocated on the
   * heap. StrictLock avoids aliasing by using a slightly less orthodox and
   * less well-known technique: disable address taking.
   */

  template <typename Lk>
  struct StrictLock
  {
    typedef typename Lk::mutex_type mutex_type;
    BOOST_CONCEPT_ASSERT(( BasicLockable<mutex_type> ));
    BOOST_STATIC_ASSERT(( is_strict_lock<Lk>::value ));

    BOOST_CONCEPT_USAGE( StrictLock)
    {
      if (l1.owns_lock(&mtx)) return;
    }
    StrictLock() :
      l1(*static_cast<Lk*>(0)),
      mtx(*static_cast<mutex_type*>(0))
    {}
  private:
    StrictLock operator=(StrictLock const&);

    Lk const& l1;
    mutex_type const& mtx;

  };

}
#endif