qxLib
threads_shared.inl
Go to the documentation of this file.
1 /**
2 
3  @file threads_shared.inl
4  @author Khrapov
5  @date 4.03.2021
6  @copyright © Nick Khrapov, 2021. All right reserved.
7 
8 **/
9 
10 namespace qx
11 {
12 
13 //-------------------------------- shared_proxy --------------------------------
14 
15 template<class data_t, class synchronization_primitive_t>
16 inline shared_proxy<data_t, synchronization_primitive_t>::shared_proxy(
17  data_t* pData,
18  synchronization_primitive_t* pSynchronizationPrimitive,
19  bool bTryLock)
20  : m_pSynchronizationPrimitive(pSynchronizationPrimitive)
21  , m_pData(pData)
22 {
23  if (!bTryLock)
24  {
25  lock_synchronization_primitive(m_pSynchronizationPrimitive);
26  }
27  else
28  {
29  if (!try_lock_synchronization_primitive(m_pSynchronizationPrimitive))
30  {
31  m_pSynchronizationPrimitive = nullptr;
32  m_pData = nullptr;
33  }
34  }
35 }
36 
37 template<class data_t, class synchronization_primitive_t>
38 inline shared_proxy<data_t, synchronization_primitive_t>::shared_proxy(shared_proxy&& other) noexcept
39 {
40  std::swap(m_pSynchronizationPrimitive, other.m_pSynchronizationPrimitive);
41  std::swap(m_pData, other.m_pData);
42 }
43 
44 template<class data_t, class synchronization_primitive_t>
45 inline shared_proxy<data_t, synchronization_primitive_t>& shared_proxy<data_t, synchronization_primitive_t>::operator=(
46  shared_proxy&& other) noexcept
47 {
48  std::swap(m_pSynchronizationPrimitive, other.m_pSynchronizationPrimitive);
49  std::swap(m_pData, other.m_pData);
50  return *this;
51 }
52 
53 template<class data_t, class synchronization_primitive_t>
54 inline shared_proxy<data_t, synchronization_primitive_t>::~shared_proxy()
55 {
56  if (m_pSynchronizationPrimitive && m_pData)
57  unlock_synchronization_primitive(m_pSynchronizationPrimitive);
58 }
59 
60 template<class data_t, class synchronization_primitive_t>
61 inline data_t* shared_proxy<data_t, synchronization_primitive_t>::operator->(void) noexcept
62 {
63  return m_pData;
64 }
65 
66 template<class data_t, class synchronization_primitive_t>
67 inline const data_t* shared_proxy<data_t, synchronization_primitive_t>::operator->(void) const noexcept
68 {
69  return m_pData;
70 }
71 
72 template<class data_t, class synchronization_primitive_t>
73 inline data_t& shared_proxy<data_t, synchronization_primitive_t>::operator*(void) noexcept
74 {
75  return *m_pData;
76 }
77 
78 template<class data_t, class synchronization_primitive_t>
79 inline const data_t& shared_proxy<data_t, synchronization_primitive_t>::operator*(void) const noexcept
80 {
81  return *m_pData;
82 }
83 
84 
85 
86 //----------------------- synchronization_primitive_raii -----------------------
87 
88 template<class data_t, class synchronization_primitive_t>
89 inline threads_shared<data_t, synchronization_primitive_t>::synchronization_primitive_raii::
90  synchronization_primitive_raii()
91 {
92  lock_synchronization_primitive(&sp);
93 }
94 
95 template<class data_t, class synchronization_primitive_t>
96 inline threads_shared<data_t, synchronization_primitive_t>::synchronization_primitive_raii::
97  ~synchronization_primitive_raii()
98 {
99  unlock_synchronization_primitive(&sp);
100 }
101 
102 template<class data_t, class synchronization_primitive_t>
103 inline synchronization_primitive_t* threads_shared<data_t, synchronization_primitive_t>::
104  synchronization_primitive_raii::get_object() noexcept
105 {
106  return &sp;
107 }
108 
109 
110 
111 //------------------------------- threads_shared -------------------------------
112 
113 template<class data_t, class synchronization_primitive_t>
114 template<class... args_t>
116  : m_Data(std::forward<args_t>(args)...)
117 {
118  // unlock the state that was locked in
119  // synchronization_primitive_raii::synchronization_primitive_raii()
120  unlock_synchronization_primitive(m_SynchronizationPrimitiveRAII.get_object());
121 }
122 
123 template<class data_t, class synchronization_primitive_t>
125 {
126  // wait for the rest of the threads to finish working
127  // unlocking will be carried out in
128  // synchronization_primitive_raii::~synchronization_primitive_raii()
129  lock_synchronization_primitive(m_SynchronizationPrimitiveRAII.get_object());
130 }
131 
132 template<class data_t, class synchronization_primitive_t>
134  data_t,
135  synchronization_primitive_t>::lock()
136 {
137  return proxy(&m_Data, m_SynchronizationPrimitiveRAII.get_object(), false);
138 }
139 
140 template<class data_t, class synchronization_primitive_t>
141 inline std::optional<typename threads_shared<data_t, synchronization_primitive_t>::proxy> threads_shared<
142  data_t,
143  synchronization_primitive_t>::try_lock()
144 {
145  auto object = proxy(&m_Data, m_SynchronizationPrimitiveRAII.get_object(), true);
146  if (object.m_pSynchronizationPrimitive && object.m_pData)
147  return { std::move(object) };
148  else
149  return std::nullopt;
150 }
151 
152 } // namespace qx
A proxy class that provides access to an object stored in threads_shared and provides raii for synchr...
A class that provides thread-safe access to an object, including construction and destruction.
~threads_shared()
threads_shared object destructor