piranha  0.10
atomic_flag_array.hpp
1 /* Copyright 2009-2017 Francesco Biscani (bluescarni@gmail.com)
2 
3 This file is part of the Piranha library.
4 
5 The Piranha library is free software; you can redistribute it and/or modify
6 it under the terms of either:
7 
8  * the GNU Lesser General Public License as published by the Free
9  Software Foundation; either version 3 of the License, or (at your
10  option) any later version.
11 
12 or
13 
14  * the GNU General Public License as published by the Free Software
15  Foundation; either version 3 of the License, or (at your option) any
16  later version.
17 
18 or both in parallel, as here.
19 
20 The Piranha library is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 for more details.
24 
25 You should have received copies of the GNU General Public License and the
26 GNU Lesser General Public License along with the Piranha library. If not,
27 see https://www.gnu.org/licenses/. */
28 
29 #ifndef PIRANHA_DETAIL_ATOMIC_FLAG_ARRAY_HPP
30 #define PIRANHA_DETAIL_ATOMIC_FLAG_ARRAY_HPP
31 
32 #include <atomic>
33 #include <cstddef>
34 #include <limits>
35 #include <memory>
36 #include <new>
37 
38 #include <piranha/config.hpp>
39 #include <piranha/exceptions.hpp>
40 
41 namespace piranha
42 {
43 
44 namespace detail
45 {
46 
47 // A simple RAII holder for an array of atomic flags. Bare minimum functionality.
48 struct atomic_flag_array {
49  using value_type = std::atomic_flag;
50  // This constructor will init all the flags in the array to false.
51  explicit atomic_flag_array(const std::size_t &size) : m_size(size)
52  {
53  if (unlikely(size > std::numeric_limits<std::size_t>::max() / sizeof(value_type))) {
54  piranha_throw(std::bad_alloc, );
55  }
56  // Dynamically create an array of unsigned char with enough storage.
57  // This will throw bad_alloc in case the memory cannot be allocated.
58  // NOTE: this is required to return memory sufficiently aligned for any type
59  // which does not have extended alignment requirements:
60  // https://stackoverflow.com/questions/10587879/does-new-char-actually-guarantee-aligned-memory-for-a-class-type
61  m_ptr.reset(::new unsigned char[size * sizeof(value_type)]);
62  // Now we use the unsigned char buffer to provide storage for the atomic flags. See:
63  // http://eel.is/c++draft/intro.object
64  // From now on, everything is noexcept.
65  const auto end_ptr = m_ptr.get() + size * sizeof(value_type);
66  for (auto ptr = m_ptr.get(); ptr != end_ptr; ptr += sizeof(value_type)) {
67  // NOTE: atomic_flag should support aggregate init syntax:
68  // http://en.cppreference.com/w/cpp/atomic/atomic
69  // But it results in warnings, let's avoid initialisation
70  // via ctor and just set the flag to false later.
71  ::new (static_cast<void *>(ptr)) value_type;
72  reinterpret_cast<value_type *>(ptr)->clear();
73  }
74  }
75  // atomic_flag is guaranteed to have a trivial dtor,
76  // so we can just let unique_ptr free the storage. No need
77  // for custom dtor.
78  // http://en.cppreference.com/w/cpp/atomic/atomic
79  // Delete explicitly all other ctors/assignment operators.
80  atomic_flag_array() = delete;
81  atomic_flag_array(const atomic_flag_array &) = delete;
82  atomic_flag_array(atomic_flag_array &&) = delete;
83  atomic_flag_array &operator=(const atomic_flag_array &) = delete;
84  atomic_flag_array &operator=(atomic_flag_array &&) = delete;
85  value_type &operator[](const std::size_t &i)
86  {
87  return *reinterpret_cast<value_type *>(m_ptr.get() + sizeof(value_type) * i);
88  }
89  const value_type &operator[](const std::size_t &i) const
90  {
91  return *reinterpret_cast<const value_type *>(m_ptr.get() + sizeof(value_type) * i);
92  }
93  // Data members.
94  std::unique_ptr<unsigned char[]> m_ptr;
95  const std::size_t m_size;
96 };
97 }
98 }
99 
100 #endif
Exceptions.
#define piranha_throw(exception_type,...)
Exception-throwing macro.
Definition: exceptions.hpp:118
Root piranha namespace.
Definition: array_key.hpp:52