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
|
/*
* Copyright Andrey Semashev 2007 - 2014.
* 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)
*/
/*!
* \file locking_ptr.hpp
* \author Andrey Semashev
* \date 15.07.2009
*
* This header is the Boost.Log library implementation, see the library documentation
* at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
*/
#ifndef BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_
#define BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_
#include <cstddef>
#include <boost/move/core.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/thread/lock_options.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/utility/explicit_operator_bool.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
//! A pointer type that locks the backend until it's destroyed
template< typename T, typename LockableT >
class locking_ptr
{
typedef locking_ptr this_type;
BOOST_COPYABLE_AND_MOVABLE_ALT(this_type)
public:
//! Pointed type
typedef T element_type;
private:
//! Lockable type
typedef LockableT lockable_type;
private:
//! The pointer to the backend
shared_ptr< element_type > m_pElement;
//! Reference to the shared lock control object
lockable_type* m_pLock;
public:
//! Default constructor
locking_ptr() BOOST_NOEXCEPT : m_pLock(NULL)
{
}
//! Constructor
locking_ptr(shared_ptr< element_type > const& p, lockable_type& l) : m_pElement(p), m_pLock(&l)
{
m_pLock->lock();
}
//! Constructor
locking_ptr(shared_ptr< element_type > const& p, lockable_type& l, try_to_lock_t const&) : m_pElement(p), m_pLock(&l)
{
if (!m_pLock->try_lock())
{
m_pElement.reset();
m_pLock = NULL;
}
}
//! Copy constructor
locking_ptr(locking_ptr const& that) : m_pElement(that.m_pElement), m_pLock(that.m_pLock)
{
if (m_pLock)
m_pLock->lock();
}
//! Move constructor
locking_ptr(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT : m_pLock(that.m_pLock)
{
m_pElement.swap(that.m_pElement);
that.m_pLock = NULL;
}
//! Destructor
~locking_ptr()
{
if (m_pLock)
m_pLock->unlock();
}
//! Assignment
locking_ptr& operator= (locking_ptr that) BOOST_NOEXCEPT
{
this->swap(that);
return *this;
}
//! Indirection
element_type* operator-> () const BOOST_NOEXCEPT { return m_pElement.get(); }
//! Dereferencing
element_type& operator* () const BOOST_NOEXCEPT { return *m_pElement; }
//! Accessor to the raw pointer
element_type* get() const BOOST_NOEXCEPT { return m_pElement.get(); }
//! Checks for null pointer
BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
//! Checks for null pointer
bool operator! () const BOOST_NOEXCEPT { return !m_pElement; }
//! Swaps two pointers
void swap(locking_ptr& that) BOOST_NOEXCEPT
{
m_pElement.swap(that.m_pElement);
lockable_type* p = m_pLock;
m_pLock = that.m_pLock;
that.m_pLock = p;
}
};
//! Free raw pointer getter to assist generic programming
template< typename T, typename LockableT >
inline T* get_pointer(locking_ptr< T, LockableT > const& p) BOOST_NOEXCEPT
{
return p.get();
}
//! Free swap operation
template< typename T, typename LockableT >
inline void swap(locking_ptr< T, LockableT >& left, locking_ptr< T, LockableT >& right) BOOST_NOEXCEPT
{
left.swap(right);
}
} // namespace aux
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_
|