• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Distributed under the Boost Software License, Version 1.0. (See
2 // accompanying file LICENSE_1_0.txt or copy at
3 // http://www.boost.org/LICENSE_1_0.txt)
4 // (C) Copyright 2008-2009,2012 Vicente J. Botet Escriba
5 
6 #ifndef BOOST_THREAD_STRICT_LOCK_HPP
7 #define BOOST_THREAD_STRICT_LOCK_HPP
8 
9 #include <boost/thread/detail/config.hpp>
10 #include <boost/thread/detail/delete.hpp>
11 #include <boost/thread/detail/lockable_wrapper.hpp>
12 #include <boost/thread/lock_options.hpp>
13 #include <boost/thread/lock_traits.hpp>
14 #include <boost/thread/lockable_traits.hpp>
15 #include <boost/thread/lockable_concepts.hpp>
16 #include <boost/thread/lock_concepts.hpp>
17 #include <boost/thread/exceptions.hpp>
18 #include <boost/throw_exception.hpp>
19 
20 #include <boost/config/abi_prefix.hpp>
21 
22 namespace boost
23 {
24 
25 
26   //[strict_lock
27   template <typename Lockable>
28   class strict_lock
29   {
30 
31     BOOST_CONCEPT_ASSERT(( BasicLockable<Lockable> ));
32   public:
33     typedef Lockable mutex_type;
34 
35     // construct/copy/destroy:
36 
37     BOOST_THREAD_NO_COPYABLE( strict_lock)
38 
39     /**
40      * Constructor from a mutex reference.
41      *
42      * @param mtx the mutex to lock.
43      *
44      * __Effects: Stores a reference to the mutex to lock and locks it.
45      * __Throws: Any exception BasicMutex::lock() can throw.
46      */
strict_lock(mutex_type & mtx)47     explicit strict_lock(mutex_type& mtx) :
48       mtx_(mtx)
49     {
50       mtx.lock();
51     } /*< locks on construction >*/
52 
53 
54 #if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST
strict_lock(std::initializer_list<thread_detail::lockable_wrapper<Lockable>> l_)55     strict_lock(std::initializer_list<thread_detail::lockable_wrapper<Lockable> > l_) :
56       mtx_(*(const_cast<thread_detail::lockable_wrapper<Lockable>*>(l_.begin())->m))
57     {
58       mtx_.lock();
59     }
60 #endif
61 
62     /**
63      * Destructor
64      *
65      * __Effects: unlocks the stored mutex.
66      *
67      * __Throws
68      */
~strict_lock()69     ~strict_lock()
70     {
71       mtx_.unlock();
72     } /*< unlocks on destruction >*/
73 
74 
75     // observers
76 
77     /**
78      * @return the owned mutex.
79      */
mutex() const80     mutex_type* mutex() const BOOST_NOEXCEPT
81     {
82       return &mtx_;
83     }
84 
85     /**
86      * @return whether this lock is locking a mutex.
87      */
owns_lock() const88     bool owns_lock() const BOOST_NOEXCEPT
89     {
90       return true;
91     }
92 
93     /**
94      * @return whether this lock is locking that mutex.
95      */
owns_lock(const mutex_type * l) const96     bool owns_lock(const mutex_type* l) const BOOST_NOEXCEPT
97     {
98       return l == mutex();
99     } /*< strict locks specific function >*/
100 
101     //BOOST_ADRESS_OF_DELETE(strict_lock) /*< disable aliasing >*/
102     //BOOST_HEAP_ALLOCATION_DELETE(strict_lock) /*< disable heap allocation >*/
103 
104     /*< no possibility to unlock >*/
105 
106   private:
107     mutex_type& mtx_;
108   };
109   //]
110   template <typename Lockable>
111   struct is_strict_lock_sur_parole<strict_lock<Lockable> > : true_type
112   {
113   };
114 
115   /**
116    * A nested strict lock is a scoped lock guard ensuring the mutex is locked on its
117    * scope, by taking ownership of an nesting lock, locking the mutex on construction if not already locked
118    * and restoring the ownership to the nesting lock on destruction.
119    */
120   //[nested_strict_lock
121   template <typename Lock>
122   class nested_strict_lock
123   {
124     BOOST_CONCEPT_ASSERT(( BasicLock<Lock> )); /*< The Lock must be a movable lock >*/
125   public:
126     typedef typename Lock::mutex_type mutex_type; /*< Name the lockable type locked by Lock >*/
127 
128     BOOST_THREAD_NO_COPYABLE( nested_strict_lock)
129 
130     /**
131      * Constructor from a nesting @c Lock.
132      *
133      * @param lk the nesting lock
134      *
135      * __Requires: <c>lk.mutex() != null_ptr</c>
136      * __Effects: Stores the reference to the lock parameter and takes ownership on it.
137      * If the lock doesn't owns the mutex @c mtx lock it.
138      * __Postconditions: @c owns_lock(lk.mutex())
139      * __StrongException
140      * __Throws:
141      *
142      * - lock_error when BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined and lk.mutex() == null_ptr
143      *
144      * - Any exception that @c lk.lock() can throw.
145      *
146      */
nested_strict_lock(Lock & lk)147     explicit nested_strict_lock(Lock& lk) :
148       lk_(lk) /*< Store reference to lk >*/
149     {
150       /*< Define BOOST_THREAD_DONT_CHECK_PRECONDITIONS if you don't want to check lk ownership >*/
151       BOOST_THREAD_ASSERT_PRECONDITION(  lk.mutex() != 0,
152           lock_error()
153       );
154       if (!lk.owns_lock()) lk.lock(); /*< ensures it is locked >*/
155       tmp_lk_ = move(lk); /*< Move ownership to temporary lk >*/
156     }
157 
158 #if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST
nested_strict_lock(std::initializer_list<thread_detail::lockable_wrapper<Lock>> l_)159     nested_strict_lock(std::initializer_list<thread_detail::lockable_wrapper<Lock> > l_) :
160       lk_(*(const_cast<thread_detail::lockable_wrapper<Lock>*>(l_.begin())->m))
161     {
162       /*< Define BOOST_THREAD_DONT_CHECK_PRECONDITIONS if you don't want to check lk ownership >*/
163       BOOST_THREAD_ASSERT_PRECONDITION(  lk_.mutex() != 0,
164           lock_error()
165       );
166       if (!lk_.owns_lock()) lk_.lock(); /*< ensures it is locked >*/
167       tmp_lk_ = move(lk_); /*< Move ownership to temporary lk >*/
168     }
169 #endif
170 
171     /**
172      * Destructor
173      *
174      * __Effects: Restores ownership to the nesting lock.
175      */
~nested_strict_lock()176     ~nested_strict_lock()BOOST_NOEXCEPT
177     {
178       lk_ = move(tmp_lk_); /*< Move ownership to nesting lock >*/
179     }
180 
181     // observers
182     /**
183      * return @c the owned mutex.
184      */
mutex() const185     mutex_type* mutex() const BOOST_NOEXCEPT
186     {
187       return tmp_lk_.mutex();
188     }
189 
190     /**
191      * @return whether this lock is locking a mutex.
192      */
owns_lock() const193     bool owns_lock() const BOOST_NOEXCEPT
194     {
195       return true;
196     }
197 
198     /**
199      * @return whether if this lock is locking that mutex.
200      */
owns_lock(mutex_type const * l) const201     bool owns_lock(mutex_type const* l) const BOOST_NOEXCEPT
202     {
203       return l == mutex();
204     }
205 
206     //BOOST_ADRESS_OF_DELETE(nested_strict_lock)
207     //BOOST_HEAP_ALLOCATEION_DELETE(nested_strict_lock)
208 
209   private:
210     Lock& lk_;
211     Lock tmp_lk_;
212   };
213   //]
214 
215   template <typename Lock>
216   struct is_strict_lock_sur_parole<nested_strict_lock<Lock> > : true_type
217   {
218   };
219 
220 #if ! defined BOOST_THREAD_NO_MAKE_STRICT_LOCK
221   template <typename Lockable>
make_strict_lock(Lockable & mtx)222   strict_lock<Lockable> make_strict_lock(Lockable& mtx)
223   {
224     return { thread_detail::lockable_wrapper<Lockable>(mtx) };
225   }
226   template <typename Lock>
make_nested_strict_lock(Lock & lk)227   nested_strict_lock<Lock> make_nested_strict_lock(Lock& lk)
228   {
229     return { thread_detail::lockable_wrapper<Lock>(lk) };
230   }
231 #endif
232 }
233 #include <boost/config/abi_suffix.hpp>
234 
235 #endif
236