1 // Copyright (C) 2015 Cherokees of Idaho.
2 //
3 // This file is part of GNU uCommon C++.
4 //
5 // GNU uCommon C++ is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // GNU uCommon C++ is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with GNU uCommon C++.  If not, see <http://www.gnu.org/licenses/>.
17 
18 /**
19  * Arrays of thread-safe strongly typed heap objects.  This is used for
20  * arrays of smart pointers to immutable heap instances of object types
21  * that are reference counted and automatically deleted when no longer used.
22  * @file ucommon/arrayref.h
23  */
24 
25 #ifndef _UCOMMON_ARRAYREF_H_
26 #define _UCOMMON_ARRAYREF_H_
27 
28 #ifndef _UCOMMON_CPR_H_
29 #include <ucommon/cpr.h>
30 #endif
31 
32 #ifndef _UCOMMON_ATOMIC_H_
33 #include <ucommon/atomic.h>
34 #endif
35 
36 #ifndef _UCOMMON_PROTOCOLS_H_
37 #include <ucommon/protocols.h>
38 #endif
39 
40 #ifndef _UCOMMON_OBJECT_H_
41 #include <ucommon/object.h>
42 #endif
43 
44 #ifndef	_UCOMMON_TYPEREF_H_
45 #include <ucommon/typeref.h>
46 #endif
47 
48 #ifndef _UCOMMON_THREAD_H_
49 #include <ucommon/thread.h>
50 #endif
51 
52 namespace ucommon {
53 
54 class __EXPORT ArrayRef : public TypeRef
55 {
56 protected:
57 	typedef enum {ARRAY, STACK, QUEUE, FALLBACK} arraytype_t;
58 
59 	class __EXPORT Array : public Counted, public ConditionalAccess
60 	{
61 	private:
62 		__DELETE_DEFAULTS(Array);
63 
64 	protected:
65 		friend class ArrayRef;
66 
67 		size_t head, tail;
68 
69 		arraytype_t type;
70 
71 		explicit Array(arraytype_t mode, void *addr, size_t size);
72 
73 		void assign(size_t index, Counted *object);
74 
75 		Counted *remove(size_t index);
76 
77 		size_t count(void);
78 
79 		virtual void dealloc() __OVERRIDE;
80 
get(void)81 		inline Counted **get(void) {
82 			return reinterpret_cast<Counted **>(((caddr_t)(this)) + sizeof(Array));
83 		}
84 
85 		Counted *get(size_t index);
86 	};
87 
88 	ArrayRef(arraytype_t mode, size_t size);
89 	ArrayRef(arraytype_t mode, size_t size, TypeRef& object);
90 	ArrayRef(const ArrayRef& copy);
91 	ArrayRef();
92 
93 	void assign(size_t index, TypeRef& t);
94 
95 	void reset(TypeRef& object);
96 
97 	void reset(Counted *object);
98 
99 	Counted *get(size_t index);
100 
101 	bool is(size_t index);
102 
103 	static Array *create(arraytype_t type, size_t size);
104 
105 protected:
106 	void push(const TypeRef& object);
107 
108 	void pull(TypeRef& object);
109 
110 	bool push(const TypeRef& object, timeout_t timeout);
111 
112 	void pull(TypeRef& object, timeout_t timeout);
113 
114 public:
115 	size_t count(void);
116 
117 	void resize(size_t size);
118 
119 	void realloc(size_t size);
120 
121 	void clear(void);
122 
123 	void pop(void);
124 };
125 
126 template<typename T>
127 class stackref : public ArrayRef
128 {
129 public:
stackref()130 	inline stackref() :	ArrayRef() {};
131 
stackref(const stackref & copy)132 	inline stackref(const stackref& copy) : ArrayRef(copy) {};
133 
stackref(size_t size)134 	inline stackref(size_t size) : ArrayRef(STACK, size + 1) {};
135 
136 	inline stackref& operator=(const stackref& copy) {
137 		TypeRef::set(copy);
138 		return *this;
139 	}
140 
141 	inline typeref<T> operator[](size_t index) {
142 		return typeref<T>(ArrayRef::get(index));
143 	}
144 
operator()145 	inline typeref<T> operator()(size_t index) {
146 		return typeref<T>(ArrayRef::get(index));
147 	}
148 
at(size_t index)149 	inline typeref<T> at(size_t index) {
150 		return typeref<T>(ArrayRef::get(index));
151 	}
152 
release(void)153 	inline void release(void) {
154 		TypeRef::set(nullptr);
155 	}
156 
pull()157 	inline typeref<T> pull() {
158 		typeref<T> obj;
159 		ArrayRef::pull(obj);
160 		return obj;
161 	}
162 
pull(timeout_t timeout)163 	inline typeref<T> pull(timeout_t timeout) {
164 		typeref<T> obj;
165 		ArrayRef::pull(obj, timeout);
166 		return obj;
167 	}
168 
169 	inline stackref& operator>>(typeref<T>& target) {
170 		ArrayRef::pull(target);
171 		return *this;
172 	}
173 
push(const typeref<T> & source)174 	inline void push(const typeref<T>& source) {
175 		ArrayRef::push(source);
176 	}
177 
push(const typeref<T> & source,timeout_t timeout)178 	inline bool push(const typeref<T>& source, timeout_t timeout) {
179 		return ArrayRef::push(source, timeout);
180 	}
181 
182 	inline stackref& operator<<(const typeref<T>& source) {
183 		ArrayRef::push(source);
184 		return *this;
185 	}
186 
187 	inline stackref& operator<<(T t) {
188 		typeref<T> v(t);
189 		ArrayRef::push(v);
190 		return *this;
191 	}
192 };
193 
194 template<typename T>
195 class queueref : public ArrayRef
196 {
197 public:
queueref()198 	inline queueref() :	ArrayRef() {};
199 
queueref(const queueref & copy)200 	inline queueref(const queueref& copy) : ArrayRef(copy) {};
201 
202 	inline queueref(size_t size, bool fallback = false) : ArrayRef(fallback ? FALLBACK : QUEUE, size + 1) {};
203 
204 	inline queueref& operator=(const queueref& copy) {
205 		TypeRef::set(copy);
206 		return *this;
207 	}
208 
209 	inline typeref<T> operator[](size_t index) {
210 		return typeref<T>(ArrayRef::get(index));
211 	}
212 
operator()213 	inline typeref<T> operator()(size_t index) {
214 		return typeref<T>(ArrayRef::get(index));
215 	}
216 
at(size_t index)217 	inline typeref<T> at(size_t index) {
218 		return typeref<T>(ArrayRef::get(index));
219 	}
220 
release(void)221 	inline void release(void) {
222 		TypeRef::set(nullptr);
223 	}
224 
pull()225 	inline typeref<T> pull() {
226 		typeref<T> obj;
227 		ArrayRef::pull(obj);
228 		return obj;
229 	}
230 
pull(timeout_t timeout)231 	inline typeref<T> pull(timeout_t timeout) {
232 		typeref<T> obj;
233 		ArrayRef::pull(obj, timeout);
234 		return obj;
235 	}
236 
237 	inline queueref& operator>>(typeref<T>& target) {
238 		ArrayRef::pull(target);
239 		return *this;
240 	}
241 
push(const typeref<T> & source)242 	inline void push(const typeref<T>& source) {
243 		ArrayRef::push(source);
244 	}
245 
push(const typeref<T> & source,timeout_t timeout)246 	inline bool push(const typeref<T>& source, timeout_t timeout) {
247 		return ArrayRef::push(source, timeout);
248 	}
249 
250 	inline queueref& operator<<(const typeref<T>& source) {
251 		ArrayRef::push(source);
252 		return *this;
253 	}
254 
255 	inline queueref& operator<<(T t) {
256 		typeref<T> v(t);
257 		ArrayRef::push(v);
258 		return *this;
259 	}
260 };
261 
262 template<typename T>
263 class arrayref : public ArrayRef
264 {
265 public:
arrayref()266 	inline arrayref() :	ArrayRef() {};
267 
arrayref(const arrayref & copy)268 	inline arrayref(const arrayref& copy) : ArrayRef(copy) {};
269 
arrayref(size_t size)270 	inline arrayref(size_t size) : ArrayRef(ARRAY, size) {};
271 
arrayref(size_t size,typeref<T> & t)272 	inline arrayref(size_t size, typeref<T>& t) : ArrayRef(ARRAY, size, t) {};
273 
arrayref(size_t size,T t)274 	inline arrayref(size_t size, T t) : ArrayRef(ARRAY, size) {
275 		typeref<T> v(t);
276 		reset(v);
277 	}
278 
279 	inline arrayref& operator=(const arrayref& copy) {
280 		TypeRef::set(copy);
281 		return *this;
282 	}
283 
284 	inline arrayref& operator=(typeref<T>& t) {
285 		reset(t);
286 		return *this;
287 	}
288 
289 	inline arrayref& operator=(T t) {
290 		typeref<T> v(t);
291 		reset(v);
292 	}
293 
294 	inline typeref<T> operator[](size_t index) {
295 		return typeref<T>(ArrayRef::get(index));
296 	}
297 
operator()298 	inline typeref<T> operator()(size_t index) {
299 		return typeref<T>(ArrayRef::get(index));
300 	}
301 
at(size_t index)302 	inline typeref<T> at(size_t index) {
303 		return typeref<T>(ArrayRef::get(index));
304 	}
305 
value(size_t index)306 	inline typeref<T>  value(size_t index) {
307 		return typeref<T>(ArrayRef::get(index));
308 	}
309 
value(size_t index,typeref<T> & t)310 	inline void value(size_t index, typeref<T>& t) {
311 		ArrayRef::assign(index, t);
312 	}
313 
put(typeref<T> & target,size_t index)314 	inline void put(typeref<T>& target, size_t index) {
315 		TypeRef::put(target, ArrayRef::get(index));
316 	}
317 
operator()318 	inline void operator()(size_t index, typeref<T>& t) {
319 		ArrayRef::assign(index, t);
320 	}
321 
operator()322 	inline void operator()(size_t index, T t) {
323 		typeref<T> v(t);
324 		ArrayRef::assign(index, v);
325 	}
326 
release(void)327 	inline void release(void) {
328 		TypeRef::set(nullptr);
329 	}
330 };
331 
332 typedef arrayref<Type::Bytes> bytearray_t;
333 typedef arrayref<Type::Chars> stringarray_t;
334 
335 } // namespace
336 
337 #endif
338