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