forked from solidoss/solidframe
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dynamictype.hpp
155 lines (131 loc) · 3.76 KB
/
dynamictype.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// solid/utility/dynamic.hpp
//
// Copyright (c) 2010 Valentin Palade (vipalade @ gmail . com)
//
// This file is part of SolidFrame framework.
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.
//
#ifndef UTILITY_DYNAMIC_TYPE_HPP
#define UTILITY_DYNAMIC_TYPE_HPP
#include <vector>
#include "solid/system/common.hpp"
#include "solid/system/cassert.hpp"
#include "solid/utility/common.hpp"
#include "solid/utility/dynamicpointer.hpp"
#include <atomic>
namespace solid{
//----------------------------------------------------------------
// DynamicBase
//----------------------------------------------------------------
typedef std::vector<size_t> DynamicIdVectorT;
//struct DynamicPointerBase;
//! A base for all types that needs dynamic typeid.
struct DynamicBase{
static bool isType(const size_t _id){
return false;
}
//! Get the type id for a Dynamic object.
virtual size_t dynamicTypeId()const = 0;
static bool isTypeDynamic(const size_t _id);
static void staticTypeIds(DynamicIdVectorT &_rv){
}
virtual void dynamicTypeIds(DynamicIdVectorT &_rv)const{
}
protected:
static size_t generateId();
DynamicBase():usecount(0){}
friend class DynamicPointerBase;
virtual ~DynamicBase();
//! Used by DynamicPointer - smartpointers
size_t use();
//! Used by DynamicPointer to know if the object must be deleted
/*!
* For the return value, think of use count. Returning zero means the object should
* be deleted. Returning non zero means the object should not be deleted.
*/
size_t release();
private:
typedef std::atomic<size_t> AtomicSizeT;
AtomicSizeT usecount;
};
//----------------------------------------------------------------
// Dynamic
//----------------------------------------------------------------
//! Template class to provide dynamic type functionality
/*!
If you need to have dynamic type functionality for your objects,
you need to inherit them through Dynamic. Here's an example:<br>
if you need to have:<br>
C: public B <br>
B: public A <br>
you will actually have:<br>
C: public Dynamic\<C,B><br>
B: public Dynamic\<B,A><br>
A: public Dynamic\<A>
*/
template <class X, class T = DynamicBase>
struct Dynamic: T{
typedef Dynamic<X,T> BaseT;
template <typename ...Args>
explicit Dynamic(Args&&..._args):T(std::forward<Args>(_args)...){
}
//!The static type id
#ifdef SOLID_USE_SAFE_STATIC
static size_t staticTypeId(){
static const size_t id(DynamicBase::generateId());
return id;
}
#else
private:
static size_t staticTypeIdStub(){
static const size_t id(DynamicBase::generateId());
return id;
}
static void once_cbk(){
staticTypeIdStub();
}
public:
static size_t staticTypeId(){
static boost::once_flag once = BOOST_ONCE_INIT;
boost::call_once(&once_cbk, once);
return staticTypeIdStub();
}
#endif
//TODO: add:
//static bool isTypeExplicit(const DynamicBase*);
static bool isType(const size_t _id){
if(_id == staticTypeId()) return true;
return T::isType(_id);
}
//! The dynamic typeid
virtual size_t dynamicTypeId()const{
return staticTypeId();
}
static bool isTypeDynamic(const size_t _id){
if(_id == staticTypeId()) return true;
return T::isTypeDynamic(_id);
}
static X* cast(DynamicBase *_pdb){
if(_pdb and isTypeDynamic(_pdb->dynamicTypeId())){
return static_cast<X*>(_pdb);
}
return nullptr;
}
static const X* cast(const DynamicBase *_pdb){
if(isTypeDynamic(_pdb->dynamicTypeId())){
return static_cast<const X*>(_pdb);
}
return nullptr;
}
static void staticTypeIds(DynamicIdVectorT &_rv){
_rv.push_back(BaseT::staticTypeId());
T::staticTypeIds(_rv);
}
/*virtual*/ void dynamicTypeIds(DynamicIdVectorT &_rv)const{
staticTypeIds(_rv);
}
};
}//namespace solid
#endif