]> git.sesse.net Git - casparcg/blob - common/array.h
- Removed need of non-deterministic sleeps during server shutdown.
[casparcg] / common / array.h
1 #pragma once
2
3 #include "memory.h"
4 #include "forward.h"
5
6 #include <boost/any.hpp>
7
8 #include <cstddef>
9 #include <cstdint>
10
11 #include "assert.h"
12
13 namespace caspar {
14         
15 template<typename T>
16 class array final
17 {
18         array(const array<std::uint8_t>&);
19         array& operator=(const array<std::uint8_t>&);
20
21         template<typename> friend class array;
22 public:
23
24         // Static Members
25
26         // Constructors
27         
28         template<typename T2>
29         explicit array(std::uint8_t* ptr, std::size_t size, bool cacheable, T2&& storage)
30                 : ptr_(ptr)
31                 , size_(size)
32                 , cacheable_(cacheable)
33                 , storage_(new boost::any(std::forward<T2>(storage)))
34         {
35         }
36
37         array(array&& other)
38                 : ptr_(other.ptr_)
39                 , size_(other.size_)
40                 , cacheable_(other.cacheable_)
41                 , storage_(std::move(other.storage_))
42         {
43                 CASPAR_ASSERT(storage_);
44         }
45
46         // Methods
47         
48         array& operator=(array&& other)
49         {
50                 std::swap(ptr_, other.ptr_);
51                 std::swap(size_, other.size_);
52                 std::swap(storage_,     other.storage_);
53                 std::swap(cacheable_, other.cacheable_);
54
55                 CASPAR_ASSERT(storage_);
56
57                 return *this;
58         }
59
60         // Properties   
61                         
62         T* begin() const                        {return ptr_;}          
63         T* data() const                         {return ptr_;}
64         T* end() const                          {return reinterpret_cast<T*>(reinterpret_cast<char*>(ptr_) + size_);}
65         std::size_t size() const        {return size_;}
66         bool empty() const                      {return size() == 0;}
67         bool cacheable() const          {return cacheable_;}
68         
69         template<typename T2>
70         T2* storage() const
71         {
72                 return boost::any_cast<T2>(storage_.get());
73         }
74 private:
75         T*                      ptr_;
76         std::size_t     size_;
77         bool            cacheable_;
78         std::unique_ptr<boost::any>     storage_;
79 };
80
81 template<typename T>
82 class array<const T> final
83 {
84 public:
85
86         // Static Members
87
88         // Constructors
89         array() = default; // Needed by std::future
90
91         template<typename T2>
92         explicit array(const std::uint8_t* ptr, std::size_t size, bool cacheable, T2&& storage)
93                 : ptr_(ptr)
94                 , size_(size)
95                 , cacheable_(cacheable)
96                 , storage_(new boost::any(std::forward<T2>(storage)))
97         {
98         }
99
100         explicit array(const std::uint8_t* ptr, std::size_t size, bool cacheable)
101                 : ptr_(ptr)
102                 , size_(size)
103                 , cacheable_(cacheable)
104                 , storage_(new boost::any)
105         {
106         }
107
108         array(const array& other)
109                 : ptr_(other.ptr_)
110                 , size_(other.size_)
111                 , cacheable_(other.cacheable_)
112                 , storage_(other.storage_)
113         {
114                 CASPAR_ASSERT(storage_);
115         }
116
117         array(array<T>&& other)
118                 : ptr_(other.ptr_)
119                 , size_(other.size_)
120                 , cacheable_(other.cacheable_)
121                 , storage_(std::move(other.storage_))
122         {
123                 CASPAR_ASSERT(storage_);
124         }
125
126         // Methods
127
128         array& operator=(array other)
129         {
130                 other.swap(*this);
131                 return *this;
132         }
133
134         void swap(array& other)
135         {
136                 std::swap(ptr_, other.ptr_);
137                 std::swap(size_, other.size_);
138                 std::swap(storage_,     other.storage_);
139                 std::swap(cacheable_, other.cacheable_);
140         }
141
142         // Properties
143                         
144         const T* begin() const          {return ptr_;}          
145         const T* data() const           {return ptr_;}
146         const T* end() const            {return reinterpret_cast<const T*>(reinterpret_cast<const char*>(ptr_) + size_);}
147         std::size_t size() const        {return size_;}
148         bool empty() const                      {return size() == 0;}
149         bool cacheable() const          {return cacheable_;}
150         
151         template<typename T2>
152         T2* storage() const
153         {
154                 return boost::any_cast<T2>(storage_.get());
155         }
156
157 private:
158         const T*                                        ptr_            = nullptr;
159         std::size_t                                     size_           = 0;
160         bool                                            cacheable_      = false;
161         std::shared_ptr<boost::any>     storage_;
162 };
163
164 }
165
166 namespace std {
167         
168 template<typename T>
169 void swap(caspar::array<const T>& lhs, caspar::array<const T>& rhs)
170 {
171         lhs.swap(rhs);
172 }
173
174 }
175