UCommon
typeref.h
Go to the documentation of this file.
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
28#ifndef _UCOMMON_TYPEREF_H_
29#define _UCOMMON_TYPEREF_H_
30
31#ifndef _UCOMMON_CPR_H_
32#include <ucommon/cpr.h>
33#endif
34
35#ifndef _UCOMMON_ATOMIC_H_
36#include <ucommon/atomic.h>
37#endif
38
39#ifndef _UCOMMON_PROTOCOLS_H_
40#include <ucommon/protocols.h>
41#endif
42
43#ifndef _UCOMMON_GENERICS_H_
44#include <ucommon/generics.h>
45#endif
46
47#ifndef _UCOMMON_OBJECT_H_
48#include <ucommon/object.h>
49#endif
50
51#ifndef _UCOMMON_THREAD_H_
52#include <ucommon/thread.h>
53#endif
54
55namespace ucommon {
56
57class TypeRelease;
58class typeref_guard;
59
68class __EXPORT TypeRef
69{
70protected:
71 friend class ArrayRef;
72 friend class SharedRef;
73 friend class MapRef;
74 friend class TypeRelease;
75
76 class Release;
77
78public:
86 class __EXPORT Counted : public __PROTOCOL ObjectProtocol
87 {
88 private:
89 __DELETE_COPY(Counted);
90
91 protected:
92 friend class TypeRef;
93 friend class TypeRelease;
94
95 union {
96 TypeRelease *autorelease;
97 Counted *linkrelease;
98 };
99
100 mutable Atomic::counter count;
101 unsigned offset;
102 size_t size;
103
112 explicit Counted(void *address, size_t size, TypeRelease *ar = NULL);
113
119 virtual void dealloc(void);
120
121 public:
126 inline bool is() const {
127 return (count.get() > 0);
128 }
129
134 inline unsigned copies() const {
135 return ((unsigned)count.get());
136 }
137
138 inline TypeRelease *getRelease() const {
139 return autorelease;
140 }
141
148 void operator delete(void *address);
149
154 void retain();
155
160 void release();
161 };
162
163protected:
164 Counted *ref; // heap reference...
165
170 TypeRef(Counted *object);
171
178
183
189 void set(Counted *object);
190
194 void assign(const typeref_guard& ref);
195
201 static caddr_t mem(caddr_t address);
202
203public:
208 virtual ~TypeRef();
209
215 void set(const TypeRef& pointer);
216
220 void clear(void);
221
226 size_t size(void) const;
227
232 unsigned copies() const;
233
238 inline operator bool() const {
239 return ref != NULL;
240 }
241
246 inline bool operator!() const {
247 return ref == NULL;
248 }
249
259 inline static void put(TypeRef& target, Counted *object) {
260 target.set(object);
261 }
262
263 bool is_released(void);
264};
265
266class __EXPORT TypeRelease
267{
268public:
269 inline TypeRelease() {
270 delegate = nullptr;
271 }
272
273 inline TypeRelease(TypeRelease *target) {
274 delegate = target;
275 }
276
277 virtual unsigned purge();
278
279 virtual caddr_t allocate(size_t size);
280
281protected:
282 friend class TypeRef::Counted;
283
284 TypeRelease *delegate;
285
286 void enlist(TypeRef::Counted **root, TypeRef::Counted *obj);
287
288 TypeRef::Counted *delist(TypeRef::Counted **root);
289
290 virtual void release(TypeRef::Counted *obj);
291
292 void dealloc(TypeRef::Counted *obj);
293
294 inline size_t size(TypeRef::Counted *obj) {
295 return obj->size;
296 }
297};
298
299extern __EXPORT TypeRelease auto_release;
300extern __EXPORT TypeRelease secure_release;
301extern __EXPORT TypeRelease release_later;
302
303class __EXPORT typeref_guard : protected TypeRef
304{
305private:
306 friend class TypeRef;
307
308 mutable Mutex sync;
309
310public:
311 inline typeref_guard() : TypeRef() {}
312
313 inline typeref_guard(const typeref_guard& copy) : TypeRef(copy) {}
314
315 inline typeref_guard(const TypeRef& pointer) : TypeRef(pointer) {}
316
317 void set(const TypeRef& pointer);
318
319 inline typeref_guard& operator=(const TypeRef& pointer) {
320 set(pointer);
321 return *this;
322 }
323};
324
325template<typename T, TypeRelease& R = auto_release>
326class typeref : public TypeRef
327{
328private:
329 class value : public Counted
330 {
331 private:
332 __DELETE_COPY(value);
333
334 public:
335 T data;
336
337 inline value(caddr_t mem, const T& object, TypeRelease *ar = &R) :
338 Counted(mem, sizeof(value), ar) {
339 data = object;
340 }
341 };
342
343public:
344 inline typeref() : TypeRef() {}
345
346 inline typeref(const typeref_guard& global) : TypeRef() {
347 TypeRef::assign(global);
348 }
349
350 inline typeref(const typeref& copy) : TypeRef(copy) {}
351
352 inline typeref(const T& object, TypeRelease *ar = &R) : TypeRef() {
353 caddr_t p = R.allocate(sizeof(value));
354 TypeRef::set(new(mem(p)) value(p, object, ar));
355 }
356
357 inline explicit typeref(Counted *object) : TypeRef(object) {}
358
359 inline const T* operator->() const {
360 if(!ref)
361 return NULL;
362 value *v = polystatic_cast<value *>(ref);
363 return &(v->data);
364 }
365
366 inline const T& operator*() const {
367 value *v = polystatic_cast<value*>(ref);
368 __THROW_DEREF(v);
369 return *(&(v->data));
370 }
371
372 inline const T* operator()() const {
373 value *v = polystatic_cast<value*>(ref);
374 if(!v)
375 return nullptr;
376
377 return &(v->data);
378 }
379
380 inline operator const T&() const {
381 value *v = polystatic_cast<value*>(ref);
382 __THROW_DEREF(v);
383 return *(&(v->data));
384 }
385
386 inline typeref& operator=(const typeref_guard& ptr) {
387 TypeRef::assign(ptr);
388 return *this;
389 }
390
391 inline typeref& operator=(const typeref& ptr) {
392 TypeRef::set(ptr);
393 return *this;
394 }
395
396 inline bool operator==(const typeref& ptr) const {
397 value *v1 = polystatic_cast<value*>(ref);
398 value *v2 = polystatic_cast<value*>(ptr.ref);
399 if(!v1 || !v2)
400 return false;
401 return v1->data == v2->data;
402 }
403
404 inline bool operator==(const T& obj) const {
405 value *v = polystatic_cast<value *>(ref);
406 if(!v)
407 return false;
408 return v->data == obj;
409 }
410
411 inline bool operator!=(const typeref& ptr) const {
412 return !(*this == ptr);
413 }
414
415 inline bool operator!=(const T& obj) const {
416 return !(*this == obj);
417 }
418
419 inline void set(T& object, TypeRelease *pool = &R) {
420 clear();
421 caddr_t p = R.allocate(sizeof(value));
422 TypeRef::set(new(mem(p)) value(p, object, pool));
423 }
424
425 inline typeref& operator=(T& object) {
426 set(object);
427 return *this;
428 }
429};
430
431// The specializations are done as simple template specializations so that the
432// hard parts can be hard-coded rather than inline members. This means we do
433// not pass the autorelease as a specialization here, but we can do a secondary
434// template that does use releases with a lot less overhead.
435
436template<>
437class __EXPORT typeref<const char *> : public TypeRef
438{
439public:
440 class value : public Counted
441 {
442 private:
443 __DELETE_COPY(value);
444
445 protected:
446 friend class typeref;
447
448 char mem[1];
449
450 value(caddr_t addr, size_t size, const char *str, TypeRelease *ar = &auto_release);
451
452 void destroy(void);
453
454 public:
455 inline char *get() {
456 return &mem[0];
457 }
458
459 inline size_t len() {
460 return strlen(mem);
461 }
462
463 inline size_t max() {
464 return size;
465 }
466
467 inline operator char *() {
468 return &mem[0];
469 }
470 };
471
472 typeref();
473
474 typeref(const typeref& copy);
475
476 typeref(const char *str, TypeRelease *ar = &auto_release);
477
478 typeref(size_t size, TypeRelease *ar = &auto_release);
479
480 inline typeref(const typeref_guard& global) : TypeRef() {
481 TypeRef::assign(global);
482 }
483
484 inline explicit typeref(Counted *object) : TypeRef(object) {}
485
486 inline explicit typeref(value *value) : TypeRef(value) {}
487
488 const char *operator*() const;
489
490 inline operator const char *() const {
491 return operator*();
492 }
493
494 size_t len() const;
495
496 bool operator==(const typeref& ptr) const;
497
498 bool operator==(const char *obj) const;
499
500 bool operator==(value *chars) const;
501
502 inline bool operator!=(const typeref& ptr) const {
503 return !(*this == ptr);
504 }
505
506 inline bool operator!=(value *chars) const {
507 return !(*this == chars);
508 }
509
510 inline bool operator!=(const char *obj) const {
511 return !(*this == obj);
512 }
513
514 bool operator<(const typeref& ptr) const;
515
516 inline bool operator>(const typeref& ptr) const {
517 return (ptr < *this);
518 }
519
520 inline bool operator<=(const typeref& ptr) const {
521 return !(*this > ptr);
522 }
523
524 inline bool operator>=(const typeref& ptr) const {
525 return !(*this < ptr);
526 }
527
528 typeref& operator=(const typeref& objref);
529
530 typeref& operator=(const char *str);
531
532 typeref& operator=(value *chars);
533
534 const typeref operator+(const char *str) const;
535
536 const typeref operator+(const typeref& ptr) const;
537
538 const char *operator()(ssize_t offset) const;
539
540 void set(const char *str, TypeRelease *ar = &auto_release);
541
542 void hex(const uint8_t *mem, size_t size, TypeRelease *ar = &auto_release);
543
544 void b64(const uint8_t *mem, size_t size, TypeRelease *ar = &auto_release);
545
546 void assign(value *chars);
547
548 static void expand(value **handle, size_t size);
549
550 static value *create(size_t size, TypeRelease *ar = &auto_release);
551
552 static void destroy(value *bytes);
553};
554
555template<>
556class __EXPORT typeref<const uint8_t *> : public TypeRef
557{
558public:
559 class value : public Counted
560 {
561 private:
562 __DELETE_COPY(value);
563
564 protected:
565 friend class typeref;
566
567 uint8_t mem[1];
568
569 value(caddr_t addr, size_t size, const uint8_t *data = nullptr, TypeRelease *ar = &auto_release);
570
571 void destroy(void);
572
573 public:
574 inline size_t max() {
575 return size;
576 }
577
578 inline uint8_t *get() {
579 return &mem[0];
580 }
581
582 inline operator uint8_t*() {
583 return &mem[0];
584 }
585 };
586
587 typeref();
588
589 typeref(const typeref& copy);
590
591 typeref(uint8_t *str, size_t size, TypeRelease *ar = &auto_release);
592
593 typeref(size_t size, TypeRelease *ar = &auto_release);
594
595 typeref(bool mode, size_t bits, TypeRelease *ar = &auto_release);
596
597 inline typeref(const typeref_guard& global) : TypeRef() {
598 TypeRef::assign(global);
599 }
600
601 inline explicit typeref(Counted *object) : TypeRef(object) {}
602
603 const uint8_t *operator*() const;
604
605 inline operator const uint8_t *() const {
606 return operator*();
607 }
608
609 typeref& operator=(const typeref& objref);
610
611 typeref& operator=(value *bytes);
612
613 bool operator==(const typeref& ptr) const;
614
615 bool operator==(value *bytes) const;
616
617 inline bool operator!=(const typeref& ptr) const {
618 return !(*this == ptr);
619 }
620
621 inline bool operator!=(value *bytes) const {
622 return !(*this == bytes);
623 }
624
625 const typeref operator+(const typeref& ptr) const;
626
627 void set(const uint8_t *str, size_t size, TypeRelease *ar = &auto_release);
628
629 size_t set(bool bit, size_t offset, size_t bits = 1);
630
631 size_t hex(const char *str, bool ws = false, TypeRelease *ar = &auto_release);
632
633 size_t b64(const char *str, bool ws = false, TypeRelease *ar = &auto_release);
634
635 uint8_t *data(void);
636
637 bool get(size_t offset);
638
639 size_t count(size_t offset, size_t bits = 1);
640
641 void assign(value *bytes);
642
643 typeref<const char *> hex();
644
645 typeref<const char *> b64();
646
647 static value *create(size_t size, TypeRelease *ar = &auto_release);
648
649 static void destroy(value *bytes);
650};
651
652// convenience classes that roll up autorelease behavior for strings and
653// byte arrays into templates.
654
655template<TypeRelease& R>
656class stringref : public typeref<const char *>
657{
658public:
659 inline stringref() : typeref<const char *>() {}
660
661 inline stringref(const stringref& copy) : typeref<const char *>(copy) {}
662
663 inline stringref(const char *str) : typeref<const char *>(str, &R) {}
664
665 inline stringref(size_t size) : typeref<const char *>(size, &R) {}
666
667 inline explicit stringref(Counted *object) : typeref<const char *>(object) {}
668
669 inline void set(const char *str) {
670 typeref<const char *>::set(str, &R);
671 }
672
673 inline static value *create(size_t size) {
674 return typeref<const char *>::create(size, &R);
675 }
676
677 inline static stringref promote(typeref<const char *>& str) {
678 stringref result = *str;
679 return result;
680 }
681};
682
683template<TypeRelease& R>
684class byteref : public typeref<const uint8_t *>
685{
686public:
687 inline byteref() : typeref<const uint8_t *>() {}
688
689 inline byteref(uint8_t *str, size_t size) : typeref<const uint8_t *>(str, size, &R) {}
690
691 inline byteref(size_t size) : typeref<const uint8_t *>(size, &R) {}
692
693 inline byteref(bool mode, size_t bits) : typeref<const uint8_t *>(mode, bits, &R) {}
694
695 inline explicit byteref(Counted *object) : typeref<const uint8_t *>(object) {}
696
697 inline void set(const uint8_t *str, size_t size) {
698 typeref<const uint8_t *>::set(str, size, &R);
699 }
700
701 inline size_t hex(const char *str, bool ws = false) {
702 return typeref<const uint8_t *>::hex(str, ws, &R);
703 }
704
705 inline size_t b64(const char *str, bool ws = false) {
706 return typeref<const uint8_t *>::b64(str, ws, &R);
707 }
708
709 inline stringref<R> hex() {
710 typeref<const char *> str = typeref<const uint8_t *>::hex();
711 stringref<R> result = *str;
712 return result;
713 }
714
715 inline stringref<R> b64() {
716 typeref<const char *> str = typeref<const uint8_t *>::b64();
717 stringref<R> result = *str;
718 return result;
719 }
720
721 inline static value *create(size_t size) {
722 return typeref<const uint8_t *>::create(size, &R);
723 }
724
725 inline static byteref promote(typeref<const uint8_t *>& str) {
726 byteref result = *str;
727 return result;
728 }
729};
730
731// a namespace for aliasing things we may typically use as a typeref
732
733namespace Type {
734 typedef int32_t Integer;
735 typedef double Real;
736 typedef const char *Chars;
737 typedef const uint8_t *Bytes;
738 typedef const uint8_t *Bools;
739}
740
741typedef typeref<Type::Chars>::value *charvalues_t;
742typedef typeref<Type::Bytes>::value *bytevalues_t;
743typedef typeref<Type::Chars> stringref_t;
744typedef typeref<Type::Bytes> byteref_t;
745typedef typeref<Type::Bools> boolref_t;
746
747template<typename T>
748inline typeref<T> typeref_cast(T x) {
749 return typeref<T>(x);
750}
751
752} // namespace
753
754#endif
Runtime functions.
Atomic pointers and locks.
Abstract interfaces and support.
Generic templates for C++.
Common namespace for all ucommon objects.
Definition access.h:47
T & max(T &o1, T &o2)
Convenience function to return max of two objects.
Definition generics.h:445
T copy(const T &src)
Convenience function to copy objects.
Definition generics.h:395
Atomic counter class.
Definition atomic.h:61
Generic smart pointer class.
Definition generics.h:55
Create a linked list of auto-releasable objects.
Definition memory.h:742
A common base class for all managed objects.
Definition protocols.h:174
Smart pointer base class for auto-retained objects.
Definition typeref.h:69
bool operator!() const
Check if we are currently not pointing to anything.
Definition typeref.h:246
void set(Counted *object)
Set our smart pointer to a specific heap container.
static caddr_t mem(caddr_t address)
Adjust memory pointer to atomic boundry.
TypeRef(const TypeRef &pointer)
Create a smart pointer based on another pointer.
void assign(const typeref_guard &ref)
Assign from a guarded typeref.
unsigned copies() const
Get number of references to container.
TypeRef(Counted *object)
Create a smart pointer referencing an existing heap object.
TypeRef()
Create a smart pointer referencing nothing.
size_t size(void) const
Get size of referenced heap object.
void clear(void)
Manually release the current container.
void set(const TypeRef &pointer)
Set our smart pointer based on another pointer instance.
static void put(TypeRef &target, Counted *object)
Special weak-public means to copy a container reference.
Definition typeref.h:259
virtual ~TypeRef()
Destroy pointer when falling out of scope.
Heap base-class container for typeref objects.
Definition typeref.h:87
Counted(void *address, size_t size, TypeRelease *ar=NULL)
Construction of aligned container.
unsigned copies() const
Number of retains (smart pointers) referencing us.
Definition typeref.h:134
void retain()
Retain a copy of this object.
bool is() const
Is this object not empty?
Definition typeref.h:126
virtual void dealloc(void)
Release memory and delete object when no longer referenced.
void release()
Release a copy of this object.
A common object base class with auto-pointer support.
Thread classes and sychronization objects.