KTL
threaded.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "../utility/aligned_malloc.h"
4 #include "../utility/alignment.h"
5 #include "../utility/empty_base.h"
6 #include "../utility/meta.h"
7 #include "threaded_fwd.h"
8 
9 #include <atomic>
10 #include <memory>
11 #include <mutex>
12 #include <type_traits>
13 
14 namespace ktl
15 {
16  template<typename Alloc>
17  class threaded
18  {
19  private:
20  static_assert(detail::has_no_value_type_v<Alloc>, "Building on top of typed allocators is not allowed. Use allocators without a type");
21 
22  public:
24 
25  template<typename A = Alloc>
27  noexcept(std::is_nothrow_default_constructible_v<Alloc>) :
28  m_Alloc(),
29  m_Lock() {}
30 
34  template<typename... Args,
35  typename = std::enable_if_t<
36  std::is_constructible_v<Alloc, Args...>>>
37  explicit threaded(Args&&... args)
38  noexcept(std::is_nothrow_constructible_v<Alloc, Args...>) :
39  m_Alloc(std::forward<Args>(args) ...),
40  m_Lock() {}
41 
42  threaded(const threaded&) = delete;
43  threaded(threaded&&) = delete;
44 
45  threaded& operator=(const threaded&) = delete;
46  threaded& operator=(threaded&&) = delete;
47 
48  bool operator==(const threaded& rhs) const
49  noexcept(detail::has_nothrow_equal_v<Alloc>)
50  {
51  return m_Alloc == rhs.m_Alloc;
52  }
53 
54  bool operator!=(const threaded& rhs) const
55  noexcept(detail::has_nothrow_not_equal_v<Alloc>)
56  {
57  return m_Alloc != rhs.m_Alloc;
58  }
59 
60 #pragma region Allocation
61  void* allocate(size_t n) // Lock cannot be noexcept
62  {
63  std::lock_guard<std::mutex> lock(m_Lock);
64 
65  return m_Alloc.allocate(n);
66  }
67 
68  void deallocate(void* p, size_t n) // Lock cannot be noexcept
69  {
70  std::lock_guard<std::mutex> lock(m_Lock);
71 
72  m_Alloc.deallocate(p, n);
73  }
74 #pragma endregion
75 
76 #pragma region Construction
77  template<typename T, typename... Args>
78  typename std::enable_if<detail::has_construct_v<Alloc, T*, Args...>, void>::type
79  construct(T* p, Args&&... args)
80  noexcept(detail::has_nothrow_construct_v<Alloc, T*, Args...>)
81  {
82  //std::lock_guard<std::mutex> lock(m_Lock); // Does it need to lock on construction?
83 
84  m_Alloc.construct(p, std::forward<Args>(args)...);
85  }
86 
87  template<typename T>
88  typename std::enable_if<detail::has_destroy_v<Alloc, T*>, void>::type
89  destroy(T* p)
90  noexcept(detail::has_nothrow_destroy_v<Alloc, T*>)
91  {
92  //std::lock_guard<std::mutex> lock(m_Lock);
93 
94  m_Alloc.destroy(p);
95  }
96 #pragma endregion
97 
98 #pragma region Utility
99  template<typename A = Alloc>
100  typename std::enable_if<detail::has_max_size_v<A>, size_type>::type
101  max_size() const
102  noexcept(detail::has_nothrow_max_size_v<A>)
103  {
104  return m_Alloc.max_size();
105  }
106 
107  template<typename A = Alloc>
108  typename std::enable_if<detail::has_owns_v<A>, bool>::type
109  owns(void* p) const
110  noexcept(detail::has_nothrow_owns_v<A>)
111  {
112  return m_Alloc.owns(p);
113  }
114 #pragma endregion
115 
116  Alloc& get_allocator() noexcept
117  {
118  return m_Alloc;
119  }
120 
121  const Alloc& get_allocator() const noexcept
122  {
123  return m_Alloc;
124  }
125 
126  private:
127  KTL_EMPTY_BASE Alloc m_Alloc;
128  std::mutex m_Lock;
129  };
130 }
Definition: threaded.h:18
std::enable_if< detail::has_destroy_v< Alloc, T * >, void >::type destroy(T *p) noexcept(detail::has_nothrow_destroy_v< Alloc, T * >)
Definition: threaded.h:89
bool operator!=(const threaded &rhs) const noexcept(detail::has_nothrow_not_equal_v< Alloc >)
Definition: threaded.h:54
threaded(threaded &&)=delete
std::enable_if< detail::has_construct_v< Alloc, T *, Args... >, void >::type construct(T *p, Args &&... args) noexcept(detail::has_nothrow_construct_v< Alloc, T *, Args... >)
Definition: threaded.h:79
const Alloc & get_allocator() const noexcept
Definition: threaded.h:121
bool operator==(const threaded &rhs) const noexcept(detail::has_nothrow_equal_v< Alloc >)
Definition: threaded.h:48
threaded(Args &&... args) noexcept(std::is_nothrow_constructible_v< Alloc, Args... >)
Constructor for forwarding any arguments to the underlying allocator.
Definition: threaded.h:37
Alloc & get_allocator() noexcept
Definition: threaded.h:116
void * allocate(size_t n)
Definition: threaded.h:61
threaded & operator=(const threaded &)=delete
std::enable_if< detail::has_max_size_v< A >, size_type >::type max_size() const noexcept(detail::has_nothrow_max_size_v< A >)
Definition: threaded.h:101
void deallocate(void *p, size_t n)
Definition: threaded.h:68
threaded() noexcept(std::is_nothrow_default_constructible_v< Alloc >)
Definition: threaded.h:26
threaded & operator=(threaded &&)=delete
threaded(const threaded &)=delete
std::enable_if< detail::has_owns_v< A >, bool >::type owns(void *p) const noexcept(detail::has_nothrow_owns_v< A >)
Definition: threaded.h:109
detail::get_size_type_t< Alloc > size_type
Definition: threaded.h:20
#define KTL_EMPTY_BASE
Definition: empty_base.h:6
constexpr bool has_construct_v
Definition: meta.h:41
typename get_size_type< Alloc, void >::type get_size_type_t
Definition: meta.h:31
constexpr bool has_nothrow_max_size_v
Definition: meta.h:122
Definition: cascading.h:15