CuteHMI - Modbus (CuteHMI.Modbus.2)
DataContainer.hpp
1 #ifndef H_EXTENSIONS_CUTEHMI_MODBUS_2_INCLUDE_CUTEHMI_MODBUS_INTERNAL_DATACONTAINER_HPP
2 #define H_EXTENSIONS_CUTEHMI_MODBUS_2_INCLUDE_CUTEHMI_MODBUS_INTERNAL_DATACONTAINER_HPP
3 
4 #include "common.hpp"
5 
6 #include <QLinkedList>
7 #include <QReadWriteLock>
8 
9 #include <array>
10 #include <algorithm>
11 #include <memory>
12 
13 namespace cutehmi {
14 namespace modbus {
15 namespace internal {
16 
20 template <typename T, std::size_t N = 65536>
22 {
24  friend class KeysIterator;
25 
26  public:
27  typedef T value_type;
28  typedef T & reference;
29  typedef const T & const_reference;
30  typedef T * pointer;
31  typedef const T * const_pointer;
32  // <Qt-Qt_5_11_2_Reference_Documentation-Qt_Core-Container_Classes-The_Container_Classes-QLinkedList_iterator_semantics.principle>
33  // "Iterators pointing to an item in a QLinkedList remain valid as long as the item exists, whereas iterators to a QList can
34  // become invalid after any insertion or removal."
36  // </Qt-Qt_5_11_2_Reference_Documentation-Qt_Core-Container_Classes-The_Container_Classes-QLinkedList_iterator_semantics.principle>
37 
38  static constexpr std::size_t ADDRESS_SPACE = N;
39 
45  {
46  public:
47  KeysIterator(const DataContainer<T, N> * container);
48 
49  bool hasNext() const;
50 
52 
54 
55  private:
56  mutable QReadWriteLock * m_lock;
58  };
59 
60  DataContainer();
61 
68  constexpr std::size_t size() const noexcept;
69 
79  const T * at(std::size_t i) const;
80 
90  T * at(std::size_t i);
91 
103  T * value(std::size_t i);
104 
114  void insert(std::size_t i, T * value);
115 
123  void clear();
124 
132  void free();
133 
140  const KeysContainer & keys() const;
141 
142  protected:
143  QReadWriteLock & lock() const;
144 
145  void insertKey(std::size_t i);
146 
150 };
151 
152 template <typename T, std::size_t N>
153 DataContainer<T, N>::KeysIterator::KeysIterator(const DataContainer<T, N> * container):
154  m_lock(& container->lock()),
155  m_it(container->keys())
156 {
157 }
158 
159 template <typename T, std::size_t N>
161 {
162  QReadLocker locker(m_lock);
163 
164  return m_it.hasNext();
165 }
166 
167 template <typename T, std::size_t N>
169 {
170  QReadLocker locker(m_lock);
171 
172  return m_it.next();
173 }
174 
175 template <typename T, std::size_t N>
177 {
178  QReadLocker locker(m_lock);
179 
180  return m_it.previous();
181 }
182 
183 template <typename T, std::size_t N>
184 
186  m_array()
187 {
188 }
189 
190 template <typename T, std::size_t N>
191 constexpr std::size_t DataContainer<T, N>::size() const noexcept
192 {
193  // <cppreference.com-C++-Containers_library-Thread_safety-2.principle>
194  // "2. All const member functions can be called concurrently by different threads on the same container."
195  // -- https://en.cppreference.com/w/cpp/container
196  return m_array.size();
197  // </cppreference.com-C++-Containers_library-Thread_safety-2.principle>
198 }
199 
200 template <typename T, std::size_t N>
202 {
203  QReadLocker locker(& m_lock);
204 
205  return m_array.at(i);
206 }
207 
208 template <typename T, std::size_t N>
210 {
211  QReadLocker locker(& m_lock);
212 
213  return m_array.at(i);
214 }
215 
216 template <typename T, std::size_t N>
218 {
219  T * result;
220 
221  {
222  QReadLocker readLocker(& m_lock);
223 
224  result = m_array.at(i);
225  }
226 
227  if (result == nullptr) {
228  QWriteLocker writeLocker(& m_lock);
229 
230  // In a meanwhile value may have been created from another thread, so perform a lookup again - this time it is serialized by write locker.
231  result = m_array.at(i);
232 
233  if (result == nullptr) {
234  result = new T;
235  m_array[i] = result;
236  insertKey(i);
237  }
238  }
239 
240  return result;
241 }
242 
243 template <typename T, std::size_t N>
245 {
246  QWriteLocker locker(& m_lock);
247 
248  m_array[i] = value;
249  insertKey(i);
250 }
251 
252 template <typename T, std::size_t N>
254 {
255  QWriteLocker locker(& m_lock);
256 
257  m_keys.clear();
258 
259  std::fill(m_array.begin(), m_array.end(), nullptr);
260 }
261 
262 template <typename T, std::size_t N>
264 {
265  QWriteLocker locker(& m_lock);
266 
267  for (typename DataContainer<T, N>::KeysContainer::const_iterator it = keys().begin(); it != keys().end(); ++it)
268  delete m_array.at(*it);
269 
270  m_keys.clear();
271 
272  std::fill(m_array.begin(), m_array.end(), nullptr);
273 }
274 
275 template <typename T, std::size_t N>
277 {
278  return m_keys;
279 }
280 
281 template <typename T, std::size_t N>
283 {
284  return m_lock;
285 }
286 
287 template <typename T, std::size_t N>
289 {
290  KeysContainer::iterator it = m_keys.begin();
291  while (it != m_keys.end()) {
292  if (*it < i)
293  ++it;
294  else
295  break;
296  }
297 
298  m_keys.insert(it, i);
299 }
300 
301 }
302 }
303 }
304 
305 #endif
306 
307 //(c)C: Copyright © 2019-2020, Michał Policht <michal@policht.pl>. All rights reserved.
308 //(c)C: SPDX-License-Identifier: LGPL-3.0-or-later OR MIT
309 //(c)C: This file is a part of CuteHMI.
310 //(c)C: CuteHMI is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
311 //(c)C: CuteHMI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
312 //(c)C: You should have received a copy of the GNU Lesser General Public License along with CuteHMI. If not, see <https://www.gnu.org/licenses/>.
313 //(c)C: Additionally, this file is licensed under terms of MIT license as expressed below.
314 //(c)C: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
315 //(c)C: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
316 //(c)C: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cutehmi::modbus::internal::DataContainer::lock
QReadWriteLock & lock() const
Definition: DataContainer.hpp:282
cutehmi::modbus::internal::DataContainer::KeysIterator::hasNext
bool hasNext() const
Definition: DataContainer.hpp:160
cutehmi::modbus::internal::DataContainer::size
constexpr std::size_t size() const noexcept
Get container size.
Definition: DataContainer.hpp:191
cutehmi::modbus::internal::DataContainer::const_pointer
const typedef T * const_pointer
Definition: DataContainer.hpp:31
cutehmi::modbus::internal::DataContainer::KeysIterator::previous
KeysContainer::value_type previous()
Definition: DataContainer.hpp:176
cutehmi::modbus::internal::DataContainer::insertKey
void insertKey(std::size_t i)
Definition: DataContainer.hpp:288
cutehmi::modbus::internal::DataContainer::free
void free()
Delete container contents.
Definition: DataContainer.hpp:263
cutehmi::modbus::internal::DataContainer::KeysIterator::KeysIterator
KeysIterator(const DataContainer< T, N > *container)
Definition: DataContainer.hpp:153
cutehmi::modbus::internal::DataContainer::KeysIterator::next
KeysContainer::value_type next()
Definition: DataContainer.hpp:168
std::fill
T fill(T... args)
cutehmi::modbus::internal::DataContainer::KeysContainer
QLinkedList< std::size_t > KeysContainer
Definition: DataContainer.hpp:35
QReadLocker
cutehmi::modbus::internal::DataContainer::m_lock
QReadWriteLock m_lock
Definition: DataContainer.hpp:149
QLinkedList< std::size_t >
cutehmi
cutehmi::modbus::internal::DataContainer::DataContainer
DataContainer()
Definition: DataContainer.hpp:185
QLinkedList::const_iterator
cutehmi::modbus::internal::DataContainer::KeysIterator
Keys iterator.
Definition: DataContainer.hpp:44
cutehmi::modbus::internal::DataContainer::const_reference
const typedef T & const_reference
Definition: DataContainer.hpp:29
std::array
cutehmi::modbus::internal::DataContainer::clear
void clear()
Clear container.
Definition: DataContainer.hpp:253
QLinkedList::iterator
cutehmi::modbus::internal::DataContainer::ADDRESS_SPACE
static constexpr std::size_t ADDRESS_SPACE
Definition: DataContainer.hpp:38
cutehmi::modbus::internal::DataContainer::m_array
InternalContainer m_array
Definition: DataContainer.hpp:147
cutehmi::modbus::internal::DataContainer::insert
void insert(std::size_t i, T *value)
Insert value.
Definition: DataContainer.hpp:244
std::internal
T internal(T... args)
std
QLinkedList::value_type
typedef value_type
QWriteLocker
cutehmi::modbus::internal::DataContainer::value_type
T value_type
Definition: DataContainer.hpp:27
QLinkedListIterator< KeysContainer::value_type >
cutehmi::modbus::internal::DataContainer::at
const T * at(std::size_t i) const
Get value at given index.
Definition: DataContainer.hpp:201
cutehmi::modbus::internal::DataContainer::keys
const KeysContainer & keys() const
Get keys container.
Definition: DataContainer.hpp:276
cutehmi::modbus::internal::DataContainer
Data container.
Definition: DataContainer.hpp:21
std::size_t
cutehmi::modbus::internal::DataContainer::m_keys
KeysContainer m_keys
Definition: DataContainer.hpp:148
QReadWriteLock
cutehmi::modbus::internal::DataContainer::pointer
T * pointer
Definition: DataContainer.hpp:30
cutehmi::modbus::internal::DataContainer::value
T * value(std::size_t i)
Get value at given index.
Definition: DataContainer.hpp:217
cutehmi::modbus::internal::DataContainer::reference
T & reference
Definition: DataContainer.hpp:28