Pothos  0.7.0-gf7fbae99
The Pothos dataflow programming software suite
ObjectImpl.hpp
Go to the documentation of this file.
1 
11 #pragma once
12 #include <Pothos/Config.hpp>
13 #include <Pothos/Object/Object.hpp>
15 #include <Pothos/Util/Templates.hpp> //special_decay_t
16 #include <type_traits> //std::decay
17 #include <utility> //std::forward
18 #include <atomic>
19 
20 namespace Pothos {
21 namespace Detail {
22 
23 /***********************************************************************
24  * ObjectContainer interface
25  **********************************************************************/
26 struct POTHOS_API ObjectContainer
27 {
28  ObjectContainer(const std::type_info &);
29 
30  virtual ~ObjectContainer(void);
31 
32  void *internal;
33 
34  const std::type_info &type;
35 
36  std::atomic<unsigned> counter;
37 };
38 
39 /***********************************************************************
40  * ObjectContainer templated subclass
41  **********************************************************************/
42 template <typename ValueType>
43 struct ObjectContainerT : ObjectContainer
44 {
45  template <typename... Args>
46  ObjectContainerT(Args&&... args):
47  ObjectContainer(typeid(ValueType)),
48  value(std::forward<Args>(args)...)
49  {
50  internal = (void*)std::addressof(this->value);
51  }
52 
53  ~ObjectContainerT(void)
54  {
55  return;
56  }
57 
58  ValueType value;
59 };
60 
61 template <typename ValueType, typename... Args>
62 typename std::enable_if<!std::is_same<NullObject, ValueType>::value, ObjectContainer *>::type
63 makeObjectContainer(Args&&... args)
64 {
65  return new ObjectContainerT<Pothos::Util::special_decay_t<ValueType>>(std::forward<Args>(args)...);
66 }
67 
68 template <typename ValueType, typename... Args>
69 typename std::enable_if<std::is_same<NullObject, ValueType>::value, ObjectContainer *>::type
70 makeObjectContainer(Args&&...)
71 {
72  return nullptr;
73 }
74 
75 /***********************************************************************
76  * extract implementation: either null type or direct pointer cast
77  **********************************************************************/
78 template <typename ValueType>
79 ValueType &extractObject(const Object &obj)
80 {
81  //Support for the special NullObject case when the _impl is nullptr.
82  //Otherwise, check the type for a match and then extract the internal value
83  typedef typename std::decay<ValueType>::type DecayValueType;
84  return *(reinterpret_cast<DecayValueType *>((obj._impl == nullptr)?0:obj._impl->internal));
85 }
86 
87 [[noreturn]] POTHOS_API void throwExtract(const Object &obj, const std::type_info &type);
88 
89 /***********************************************************************
90  * convertObject either converts a object to a desired type
91  * or returns a object if the requested type was a object
92  **********************************************************************/
93 template <typename T>
94 typename std::enable_if<!std::is_same<T, Object>::value, T>::type
95 convertObject(const Object &obj)
96 {
97  return extractObject<T>(obj.convert(typeid(T)));
98 }
99 
100 template <typename T>
101 typename std::enable_if<std::is_same<T, Object>::value, T>::type
102 convertObject(const Object &obj)
103 {
104  return obj;
105 }
106 
107 } //namespace Detail
108 
109 template <typename ValueType>
110 Object Object::make(ValueType &&value)
111 {
112  return Object(Emplace<ValueType>(), std::forward<ValueType>(value));
113 }
114 
115 template <typename ValueType, typename... Args>
116 Object Object::emplace(Args&&... args)
117 {
118  return Object(Emplace<ValueType>(), std::forward<Args>(args)...);
119 }
120 
121 template <typename ValueType, typename>
122 Object::Object(ValueType &&value):
123  _impl(Detail::makeObjectContainer<ValueType>(std::forward<ValueType>(value)))
124 {
125  return;
126 }
127 
128 template <typename ValueType, typename... Args>
130  _impl(Detail::makeObjectContainer<ValueType>(std::forward<Args>(args)...))
131 {
132  return;
133 }
134 
135 inline Object::Object(const char *s):
136  _impl(Detail::makeObjectContainer<std::string>(s))
137 {
138  return;
139 }
140 
141 inline const std::type_info &Pothos::Object::type(void) const
142 {
143  return (_impl == nullptr)?typeid(NullObject):_impl->type;
144 }
145 
146 template <typename ValueType>
147 const ValueType &Object::extract(void) const
148 {
149  if (this->type() == typeid(ValueType))
150  {
151  return Detail::extractObject<ValueType>(*this);
152  }
153  Detail::throwExtract(*this, typeid(ValueType));
154 }
155 
156 template <typename ValueType>
157 ValueType &Object::ref(void)
158 {
159  if (not this->unique()) throw ObjectConvertError("Pothos::Object::ref()",
160  "Multiple object ownership, access denied to non-const reference");
161  return const_cast<ValueType &>(this->extract<ValueType>());
162 }
163 
164 template <typename ValueType>
165 ValueType Object::convert(void) const
166 {
167  if (this->type() == typeid(ValueType))
168  {
169  return Detail::extractObject<ValueType>(*this);
170  }
171  return Detail::convertObject<ValueType>(*this);
172 }
173 
174 template <typename ValueType>
175 Object::operator ValueType(void) const
176 {
177  return this->convert<ValueType>();
178 }
179 
180 } //namespace Pothos
Emplace dummy type to pass type to Object emplacement constructor.
Definition: Object.hpp:102
#define POTHOS_API
Definition: Config.hpp:41
static Object make(ValueType &&value)
Definition: ObjectImpl.hpp:110
const ValueType & extract(void) const
Definition: ObjectImpl.hpp:147
Definition: ArchiveEntry.hpp:20
const std::type_info & type(void) const
Definition: ObjectImpl.hpp:141
Detail::ObjectContainer * _impl
Private implementation details.
Definition: Object.hpp:293
bool unique(void) const
Definition: Object.hpp:47
ValueType convert(void) const
Definition: ObjectImpl.hpp:165
static Object emplace(Args &&... args)
Definition: ObjectImpl.hpp:116
Definition: Object.hpp:29
ValueType & ref(void)
Definition: ObjectImpl.hpp:157