Chris@16
|
1 /*
|
Chris@16
|
2 * Copyright Andrey Semashev 2007 - 2013.
|
Chris@16
|
3 * Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
4 * (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
5 * http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 */
|
Chris@16
|
7 /*!
|
Chris@16
|
8 * \file locking_ptr.hpp
|
Chris@16
|
9 * \author Andrey Semashev
|
Chris@16
|
10 * \date 15.07.2009
|
Chris@16
|
11 *
|
Chris@16
|
12 * This header is the Boost.Log library implementation, see the library documentation
|
Chris@16
|
13 * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
|
Chris@16
|
14 */
|
Chris@16
|
15
|
Chris@16
|
16 #ifndef BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_
|
Chris@16
|
17 #define BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_
|
Chris@16
|
18
|
Chris@16
|
19 #include <boost/smart_ptr/shared_ptr.hpp>
|
Chris@16
|
20 #include <boost/log/detail/config.hpp>
|
Chris@16
|
21 #include <boost/utility/explicit_operator_bool.hpp>
|
Chris@16
|
22 #include <boost/log/detail/header.hpp>
|
Chris@16
|
23
|
Chris@16
|
24 #ifdef BOOST_HAS_PRAGMA_ONCE
|
Chris@16
|
25 #pragma once
|
Chris@16
|
26 #endif
|
Chris@16
|
27
|
Chris@16
|
28 namespace boost {
|
Chris@16
|
29
|
Chris@16
|
30 BOOST_LOG_OPEN_NAMESPACE
|
Chris@16
|
31
|
Chris@16
|
32 namespace aux {
|
Chris@16
|
33
|
Chris@16
|
34 //! Shared lock object to support locking_ptr
|
Chris@16
|
35 struct BOOST_LOG_NO_VTABLE locking_ptr_counter_base
|
Chris@16
|
36 {
|
Chris@16
|
37 unsigned int m_RefCounter;
|
Chris@16
|
38
|
Chris@16
|
39 locking_ptr_counter_base() : m_RefCounter(0)
|
Chris@16
|
40 {
|
Chris@16
|
41 }
|
Chris@16
|
42
|
Chris@16
|
43 virtual ~locking_ptr_counter_base() {}
|
Chris@16
|
44 virtual void lock() = 0;
|
Chris@16
|
45 virtual bool try_lock() = 0;
|
Chris@16
|
46 virtual void unlock() = 0;
|
Chris@16
|
47
|
Chris@16
|
48 private:
|
Chris@16
|
49 locking_ptr_counter_base(locking_ptr_counter_base const&);
|
Chris@16
|
50 locking_ptr_counter_base& operator= (locking_ptr_counter_base const&);
|
Chris@16
|
51 };
|
Chris@16
|
52
|
Chris@16
|
53 struct try_lock_tag {};
|
Chris@16
|
54 BOOST_CONSTEXPR_OR_CONST try_lock_tag try_lock = {};
|
Chris@16
|
55
|
Chris@16
|
56 //! A pointer type that locks the backend until it's destroyed
|
Chris@16
|
57 template< typename T >
|
Chris@16
|
58 class locking_ptr
|
Chris@16
|
59 {
|
Chris@16
|
60 public:
|
Chris@16
|
61 //! Pointed type
|
Chris@16
|
62 typedef T element_type;
|
Chris@16
|
63
|
Chris@16
|
64 private:
|
Chris@16
|
65 //! The pointer to the backend
|
Chris@16
|
66 shared_ptr< element_type > m_pElement;
|
Chris@16
|
67 //! Reference to the shared lock control object
|
Chris@16
|
68 locking_ptr_counter_base* m_pLock;
|
Chris@16
|
69
|
Chris@16
|
70 public:
|
Chris@16
|
71 //! Constructor
|
Chris@16
|
72 locking_ptr(shared_ptr< element_type > const& p, locking_ptr_counter_base& l)
|
Chris@16
|
73 : m_pElement(p), m_pLock(&l)
|
Chris@16
|
74 {
|
Chris@16
|
75 if (m_pLock->m_RefCounter == 0)
|
Chris@16
|
76 m_pLock->lock();
|
Chris@16
|
77 ++m_pLock->m_RefCounter;
|
Chris@16
|
78 }
|
Chris@16
|
79 //! Constructor
|
Chris@16
|
80 locking_ptr(shared_ptr< element_type > const& p, locking_ptr_counter_base& l, try_lock_tag const&)
|
Chris@16
|
81 : m_pElement(p), m_pLock(&l)
|
Chris@16
|
82 {
|
Chris@16
|
83 if (m_pLock->m_RefCounter > 0 || m_pLock->try_lock())
|
Chris@16
|
84 {
|
Chris@16
|
85 ++m_pLock->m_RefCounter;
|
Chris@16
|
86 }
|
Chris@16
|
87 else
|
Chris@16
|
88 {
|
Chris@16
|
89 m_pElement.reset();
|
Chris@16
|
90 m_pLock = NULL;
|
Chris@16
|
91 }
|
Chris@16
|
92 }
|
Chris@16
|
93 //! Copy constructor
|
Chris@16
|
94 locking_ptr(locking_ptr const& that) : m_pElement(that.m_pElement), m_pLock(that.m_pLock)
|
Chris@16
|
95 {
|
Chris@16
|
96 if (m_pLock)
|
Chris@16
|
97 ++m_pLock->m_RefCounter;
|
Chris@16
|
98 }
|
Chris@16
|
99 //! Destructor
|
Chris@16
|
100 ~locking_ptr()
|
Chris@16
|
101 {
|
Chris@16
|
102 if (m_pLock && --m_pLock->m_RefCounter == 0)
|
Chris@16
|
103 m_pLock->unlock();
|
Chris@16
|
104 }
|
Chris@16
|
105
|
Chris@16
|
106 //! Assignment
|
Chris@16
|
107 locking_ptr& operator= (locking_ptr that)
|
Chris@16
|
108 {
|
Chris@16
|
109 this->swap(that);
|
Chris@16
|
110 return *this;
|
Chris@16
|
111 }
|
Chris@16
|
112
|
Chris@16
|
113 //! Indirection
|
Chris@16
|
114 element_type* operator-> () const { return m_pElement.get(); }
|
Chris@16
|
115 //! Dereferencing
|
Chris@16
|
116 element_type& operator* () const { return *m_pElement; }
|
Chris@16
|
117
|
Chris@16
|
118 //! Accessor to the raw pointer
|
Chris@16
|
119 element_type* get() const { return m_pElement.get(); }
|
Chris@16
|
120
|
Chris@16
|
121 //! Checks for null pointer
|
Chris@16
|
122 BOOST_EXPLICIT_OPERATOR_BOOL()
|
Chris@16
|
123 //! Checks for null pointer
|
Chris@16
|
124 bool operator! () const { return !m_pElement; }
|
Chris@16
|
125
|
Chris@16
|
126 //! Swaps two pointers
|
Chris@16
|
127 void swap(locking_ptr& that)
|
Chris@16
|
128 {
|
Chris@16
|
129 m_pElement.swap(that.m_pElement);
|
Chris@16
|
130 register locking_ptr_counter_base* p = m_pLock;
|
Chris@16
|
131 m_pLock = that.m_pLock;
|
Chris@16
|
132 that.m_pLock = p;
|
Chris@16
|
133 }
|
Chris@16
|
134 };
|
Chris@16
|
135
|
Chris@16
|
136 //! Free raw pointer getter to assist generic programming
|
Chris@16
|
137 template< typename T >
|
Chris@16
|
138 inline T* get_pointer(locking_ptr< T > const& p)
|
Chris@16
|
139 {
|
Chris@16
|
140 return p.get();
|
Chris@16
|
141 }
|
Chris@16
|
142 //! Free swap operation
|
Chris@16
|
143 template< typename T >
|
Chris@16
|
144 inline void swap(locking_ptr< T >& left, locking_ptr< T >& right)
|
Chris@16
|
145 {
|
Chris@16
|
146 left.swap(right);
|
Chris@16
|
147 }
|
Chris@16
|
148
|
Chris@16
|
149 } // namespace aux
|
Chris@16
|
150
|
Chris@16
|
151 BOOST_LOG_CLOSE_NAMESPACE // namespace log
|
Chris@16
|
152
|
Chris@16
|
153 } // namespace boost
|
Chris@16
|
154
|
Chris@16
|
155 #include <boost/log/detail/footer.hpp>
|
Chris@16
|
156
|
Chris@16
|
157 #endif // BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_
|