1    	//
2    	// detail/conditionally_enabled_mutex.hpp
3    	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4    	//
5    	// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6    	//
7    	// Distributed under the Boost Software License, Version 1.0. (See accompanying
8    	// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9    	//
10   	
11   	#ifndef BOOST_ASIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP
12   	#define BOOST_ASIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP
13   	
14   	#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15   	# pragma once
16   	#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17   	
18   	#include <boost/asio/detail/config.hpp>
19   	#include <boost/asio/detail/mutex.hpp>
20   	#include <boost/asio/detail/noncopyable.hpp>
21   	#include <boost/asio/detail/scoped_lock.hpp>
22   	
23   	#include <boost/asio/detail/push_options.hpp>
24   	
25   	namespace boost {
26   	namespace asio {
27   	namespace detail {
28   	
29   	// Mutex adapter used to conditionally enable or disable locking.
30   	class conditionally_enabled_mutex
31   	  : private noncopyable
32   	{
33   	public:
34   	  // Helper class to lock and unlock a mutex automatically.
35   	  class scoped_lock
36   	    : private noncopyable
37   	  {
38   	  public:
39   	    // Tag type used to distinguish constructors.
40   	    enum adopt_lock_t { adopt_lock };
41   	
42   	    // Constructor adopts a lock that is already held.
43   	    scoped_lock(conditionally_enabled_mutex& m, adopt_lock_t)
44   	      : mutex_(m),
45   	        locked_(m.enabled_)
46   	    {
47   	    }
48   	
49   	    // Constructor acquires the lock.
50   	    explicit scoped_lock(conditionally_enabled_mutex& m)
51   	      : mutex_(m)
52   	    {
53   	      if (m.enabled_)
54   	      {
55   	        mutex_.mutex_.lock();
56   	        locked_ = true;
57   	      }
58   	      else
59   	        locked_ = false;
60   	    }
61   	
62   	    // Destructor releases the lock.
63   	    ~scoped_lock()
64   	    {
65   	      if (locked_)
66   	        mutex_.mutex_.unlock();
67   	    }
68   	
69   	    // Explicitly acquire the lock.
70   	    void lock()
71   	    {
72   	      if (mutex_.enabled_ && !locked_)
73   	      {
(3) Event example_lock: Example 1: Locking "boost::asio::detail::posix_mutex.mutex_".
Also see events: [missing_lock][example_access]
74   	        mutex_.mutex_.lock();
(4) Event example_access: Example 1 (cont.): "boost::asio::detail::conditionally_enabled_mutex::scoped_lock.locked_" is accessed with lock "boost::asio::detail::posix_mutex.mutex_" held.
Also see events: [missing_lock][example_lock]
75   	        locked_ = true;
76   	      }
77   	    }
78   	
79   	    // Explicitly release the lock.
80   	    void unlock()
81   	    {
(1) Event cond_true: Condition "this->locked_", taking true branch.
82   	      if (locked_)
83   	      {
84   	        mutex_.unlock();
(2) Event missing_lock: Accessing "this->locked_" without holding lock "boost::asio::detail::posix_mutex.mutex_". Elsewhere, "_ZN5boost4asio6detail27conditionally_enabled_mutex11scoped_lockE.locked_" is accessed with "boost::asio::detail::posix_mutex.mutex_" held 1 out of 2 times (1 of these accesses strongly imply that it is necessary).
Also see events: [example_lock][example_access]
85   	        locked_ = false;
86   	      }
87   	    }
88   	
89   	    // Test whether the lock is held.
90   	    bool locked() const
91   	    {
92   	      return locked_;
93   	    }
94   	
95   	    // Get the underlying mutex.
96   	    boost::asio::detail::mutex& mutex()
97   	    {
98   	      return mutex_.mutex_;
99   	    }
100  	
101  	  private:
102  	    friend class conditionally_enabled_event;
103  	    conditionally_enabled_mutex& mutex_;
104  	    bool locked_;
105  	  };
106  	
107  	  // Constructor.
108  	  explicit conditionally_enabled_mutex(bool enabled)
109  	    : enabled_(enabled)
110  	  {
111  	  }
112  	
113  	  // Destructor.
114  	  ~conditionally_enabled_mutex()
115  	  {
116  	  }
117  	
118  	  // Determine whether locking is enabled.
119  	  bool enabled() const
120  	  {
121  	    return enabled_;
122  	  }
123  	
124  	  // Lock the mutex.
125  	  void lock()
126  	  {
127  	    if (enabled_)
128  	      mutex_.lock();
129  	  }
130  	
131  	  // Unlock the mutex.
132  	  void unlock()
133  	  {
134  	    if (enabled_)
135  	      mutex_.unlock();
136  	  }
137  	
138  	private:
139  	  friend class scoped_lock;
140  	  friend class conditionally_enabled_event;
141  	  boost::asio::detail::mutex mutex_;
142  	  const bool enabled_;
143  	};
144  	
145  	} // namespace detail
146  	} // namespace asio
147  	} // namespace boost
148  	
149  	#include <boost/asio/detail/pop_options.hpp>
150  	
151  	#endif // BOOST_ASIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP
152