Atlas  0.7.0
Networking protocol for the Worldforge system.
BaseObject.h
1 // This file may be redistributed and modified only under the terms of
2 // the GNU Lesser General Public License (See COPYING for details).
3 // Copyright (C) 2000-2004 Stefanus Du Toit, Aloril and Al Riddoch
4 
5 // $Id$
6 
7 #ifndef ATLAS_OBJECTS_BASEOBJECT_H
8 #define ATLAS_OBJECTS_BASEOBJECT_H
9 
10 #include <Atlas/Message/MEncoder.h>
11 #include <Atlas/Message/Element.h>
12 #include <Atlas/Bridge.h>
13 #include <Atlas/Exception.h>
14 
15 #include <map>
16 #include <list>
17 #include <string>
18 
19 #include <cassert>
20 #include <mutex>
21 
22 namespace Atlas {
23 
27 namespace Objects {
28 
29 class Factories;
30 
36 {
38  std::string m_name;
39  public:
40  explicit NoSuchAttrException(const std::string& name) noexcept :
41  Atlas::Exception("No such attribute '" + name + "'."),
42  m_name(name) {}
43 
45  Atlas::Exception(rhs),
46  m_name(rhs.m_name)
47  { }
48 
49  NoSuchAttrException& operator=(NoSuchAttrException&& rhs) noexcept
50  {
51  m_name = std::move(rhs.m_name);
52  Atlas::Exception::operator=(rhs);
53  return *this;
54  }
55 
56  ~NoSuchAttrException() noexcept override = default;
58  const std::string & getName() const {
59  return m_name;
60  }
61 };
62 
63 class BaseObjectData;
64 
77 template <typename T>
78 class Allocator {
79 protected:
84 
85 
90  std::mutex m_begin_Data_mutex;
91 
98 
99 public:
100 
104  std::map<std::string, uint32_t> attr_flags_Data;
105 
110 
115 
126 
134  T *alloc();
135 
143  void free(T *instance);
144 
148  void release();
149 
150 };
151 
152 template <typename T>
153 Allocator<T>::Allocator() : m_begin_Data(nullptr)
154 {
155  T::fillDefaultObjectInstance(m_defaults_Data, attr_flags_Data);
156 }
157 
158 template <typename T>
160  release();
161 }
162 
163 template <typename T>
165 {
166  return &m_defaults_Data;
167 }
168 
169 template <typename T>
171 {
172  {
173  std::unique_lock<std::mutex> lock(m_begin_Data_mutex);
174  if (m_begin_Data) {
175  auto res = m_begin_Data;
176  m_begin_Data = static_cast<T*>(m_begin_Data->m_next);
177  lock.unlock();
178  assert(res->m_refCount == 0);
179  res->m_attrFlags = 0;
180  res->m_attributes.clear();
181  return res;
182  }
183  }
184  return new T(&m_defaults_Data);
185 }
186 
187 template <typename T>
188 inline void Allocator<T>::free(T *instance)
189 {
190  instance->reset();
191  {
192  std::lock_guard<std::mutex> lock(m_begin_Data_mutex);
193  instance->m_next = m_begin_Data;
194  m_begin_Data = instance;
195  }
196 }
197 
198 template <typename T>
200 {
201  //Delete all chained instances. This does not use the mutex as destruction can only happen in one thread,
202  // and trying to use the allocator while it's being destroyed is an illegal state.
203  T* next = m_begin_Data;
204  m_begin_Data = nullptr;
205  while (next) {
206  T* toDelete = next;
207  next = static_cast<T*>(next->m_next);
208  delete toDelete;
209  }
210 }
211 
212 static const int BASE_OBJECT_NO = 0;
213 
244 {
245 public:
246  template <typename>
247  friend class Allocator;
248  template <typename>
249  friend class SmartPtr;
250 
255  explicit BaseObjectData(BaseObjectData *defaults);
256 
257  virtual ~BaseObjectData();
258 
260  int getClassNo() const
261  {
262  return m_class_no;
263  }
264 
265  uint32_t getAttrFlags() const
266  {
267  return m_attrFlags;
268  }
269 
270  virtual BaseObjectData * copy() const = 0;
271 
273  virtual bool instanceOf(int classNo) const;
274 
276  bool hasAttr(const std::string& name) const;
278  bool hasAttrFlag(uint32_t flag) const;
281  Atlas::Message::Element getAttr(const std::string& name) const;
284  virtual int copyAttr(const std::string& name,
285  Atlas::Message::Element & attr) const;
287  virtual void setAttr(std::string name,
288  Atlas::Message::Element attr, const Atlas::Objects::Factories* factories = nullptr);
290  virtual void removeAttr(const std::string& name);
292  virtual void removeAttrFlag(uint32_t flag);
293 
296  Atlas::Message::MapType asMessage() const;
297 
299  virtual void addToMessage(Atlas::Message::MapType &) const;
300 
302  virtual void sendContents(Atlas::Bridge & b) const;
303 
304 protected:
305 
310  virtual void free() = 0;
311  virtual void reset() = 0;
312  void incRef();
313  void decRef();
314 
316  virtual int getAttrClass(const std::string& name) const;
317 
319  virtual bool getAttrFlag(const std::string& name, uint32_t& flag) const;
320 
321  template<typename T>
322  static T * copyInstance(const T& instance);
323 
324  int m_class_no; //each class has different enum
325  int m_refCount; //how many instances
326 
331 
336  std::map<std::string, Atlas::Message::Element> m_attributes;
337  // is attribute in this object or in default object?
338  uint32_t m_attrFlags;
339 };
340 
341 inline void BaseObjectData::incRef() {
342  m_refCount++;
343 }
344 
345 inline void BaseObjectData::decRef() {
346  //why zero based refCount? avoids one m_refCount-- ;-)
347  assert( m_refCount >= 0 );
348  if(!m_refCount) {
349  free();
350  return;
351  }
352  m_refCount--;
353 }
354 
355 template<typename T>
356 T * BaseObjectData::copyInstance(const T& instance) {
357  T * copied = T::allocator.alloc();
358  *copied = instance;
359  copied->m_refCount = -1;
360  return copied;
361 }
362 
363 } } // namespace Atlas::Objects
364 
365 #endif
std::mutex m_begin_Data_mutex
Definition: BaseObject.h:90
std::map< std::string, uint32_t > attr_flags_Data
Definition: BaseObject.h:104
void free(T *instance)
Definition: BaseObject.h:188
virtual void addToMessage(Atlas::Message::MapType &) const
Write this object to an existing Element.
Definition: BaseObject.cpp:99
virtual void removeAttr(const std::string &name)
Remove the attribute "name".
Definition: BaseObject.cpp:77
virtual int getAttrClass(const std::string &name) const
Find the class which contains the attribute "name".
Definition: BaseObject.cpp:114
Atlas::Message::MapType asMessage() const
Definition: BaseObject.cpp:92
virtual void free()=0
Free an instance of this class, returning it to the memory pool.
bool hasAttr(const std::string &name) const
Check whether the attribute "name" exists.
Definition: BaseObject.cpp:35
virtual void removeAttrFlag(uint32_t flag)
Remove the attribute "name".
Definition: BaseObject.cpp:87
BaseObjectData * m_defaults
Definition: BaseObject.h:330
virtual bool getAttrFlag(const std::string &name, uint32_t &flag) const
Find the flag for the attribute "name".
Definition: BaseObject.cpp:119
int getClassNo() const
Get class number:
Definition: BaseObject.h:260
Atlas::Message::Element getAttr(const std::string &name) const
Definition: BaseObject.cpp:52
virtual int copyAttr(const std::string &name, Atlas::Message::Element &attr) const
Definition: BaseObject.cpp:62
virtual void setAttr(std::string name, Atlas::Message::Element attr, const Atlas::Objects::Factories *factories=nullptr)
Set the attribute "name" to the value given by "attr".
Definition: BaseObject.cpp:72
virtual void sendContents(Atlas::Bridge &b) const
Send the contents of this object to a Bridge.
Definition: BaseObject.cpp:106
BaseObjectData(BaseObjectData *defaults)
Definition: BaseObject.cpp:14
bool hasAttrFlag(uint32_t flag) const
Check whether the attribute "name" exists.
Definition: BaseObject.cpp:47
virtual bool instanceOf(int classNo) const
Is this instance of some class?
Definition: BaseObject.cpp:30
const std::string & getName() const
Get the name of the attribute which does not exist.
Definition: BaseObject.h:58
Definition: Bridge.h:20