rid.h
1 /*************************************************************************/
2 /* rid.h */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* http://www.godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
9 /* */
10 /* Permission is hereby granted, free of charge, to any person obtaining */
11 /* a copy of this software and associated documentation files (the */
12 /* "Software"), to deal in the Software without restriction, including */
13 /* without limitation the rights to use, copy, modify, merge, publish, */
14 /* distribute, sublicense, and/or sell copies of the Software, and to */
15 /* permit persons to whom the Software is furnished to do so, subject to */
16 /* the following conditions: */
17 /* */
18 /* The above copyright notice and this permission notice shall be */
19 /* included in all copies or substantial portions of the Software. */
20 /* */
21 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
22 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
23 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
24 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
25 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
26 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
27 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
28 /*************************************************************************/
29 #ifndef RID_H
30 #define RID_H
31 
32 
33 #include "safe_refcount.h"
34 #include "typedefs.h"
35 #include "os/memory.h"
36 #include "hash_map.h"
37 #include "list.h"
38 
43 class RID_OwnerBase;
44 
45 typedef uint32_t ID;
46 
47 class RID {
48 friend class RID_OwnerBase;
49  ID _id;
50  RID_OwnerBase *owner;
51 public:
52 
53  _FORCE_INLINE_ ID get_id() const { return _id; }
54  bool operator==(const RID& p_rid) const {
55 
56  return _id==p_rid._id;
57  }
58  _FORCE_INLINE_ bool operator<(const RID& p_rid) const {
59 
60  return _id < p_rid._id;
61  }
62  _FORCE_INLINE_ bool operator<=(const RID& p_rid) const {
63 
64  return _id <= p_rid._id;
65  }
66  _FORCE_INLINE_ bool operator>(const RID& p_rid) const {
67 
68  return _id > p_rid._id;
69  }
70  bool operator!=(const RID& p_rid) const {
71 
72  return _id!=p_rid._id;
73  }
74  _FORCE_INLINE_ bool is_valid() const { return _id>0; }
75 
76  operator const void*() const {
77  return is_valid() ? this : 0;
78  };
79 
80  _FORCE_INLINE_ RID() {
81  _id = 0;
82  owner=0;
83  }
84 };
85 
86 
88 protected:
89 friend class RID;
90  void set_id(RID& p_rid, ID p_id) const { p_rid._id=p_id; }
91  void set_ownage(RID& p_rid) const { p_rid.owner=const_cast<RID_OwnerBase*>(this); }
92  ID new_ID();
93 public:
94 
95  virtual bool owns(const RID& p_rid) const=0;
96  virtual void get_owned_list(List<RID> *p_owned) const=0;
97 
98  static void init_rid();
99 
100  virtual ~RID_OwnerBase() {}
101 };
102 
103 template<class T,bool thread_safe=false>
104 class RID_Owner : public RID_OwnerBase {
105 public:
106 
107  typedef void (*ReleaseNotifyFunc)(void*user,T *p_data);
108 private:
109 
110  Mutex *mutex;
111  mutable HashMap<ID,T*> id_map;
112 
113 public:
114 
115  RID make_rid(T * p_data) {
116 
117  if (thread_safe) {
118  mutex->lock();
119  }
120 
121  ID id = new_ID();
122  id_map[id]=p_data;
123  RID rid;
124  set_id(rid,id);
125  set_ownage(rid);
126 
127  if (thread_safe) {
128  mutex->unlock();
129  }
130 
131  return rid;
132  }
133 
134  _FORCE_INLINE_ T * get(const RID& p_rid) {
135 
136  if (thread_safe) {
137  mutex->lock();
138  }
139 
140  T**elem = id_map.getptr(p_rid.get_id());
141 
142  if (thread_safe) {
143  mutex->unlock();
144  }
145 
146  ERR_FAIL_COND_V(!elem,NULL);
147 
148  return *elem;
149 
150  }
151 
152  virtual bool owns(const RID& p_rid) const {
153 
154  if (thread_safe) {
155  mutex->lock();
156  }
157 
158  T**elem = id_map.getptr(p_rid.get_id());
159 
160  if (thread_safe) {
161  mutex->lock();
162  }
163 
164  return elem!=NULL;
165  }
166 
167  virtual void free(RID p_rid) {
168 
169  if (thread_safe) {
170  mutex->lock();
171  }
172  ERR_FAIL_COND(!owns(p_rid));
173  id_map.erase(p_rid.get_id());
174  }
175  virtual void get_owned_list(List<RID> *p_owned) const {
176 
177  if (thread_safe) {
178  mutex->lock();
179  }
180 
181  const ID*id=NULL;
182  while((id=id_map.next(id))) {
183 
184  RID rid;
185  set_id(rid,*id);
186  set_ownage(rid);
187  p_owned->push_back(rid);
188 
189  }
190 
191  if (thread_safe) {
192  mutex->lock();
193  }
194 
195  }
196  RID_Owner() {
197 
198  if (thread_safe) {
199 
200  mutex = Mutex::create();
201  }
202 
203  }
204 
205 
206  ~RID_Owner() {
207 
208  if (thread_safe) {
209 
210  memdelete(mutex);
211  }
212  }
213 };
214 
215 
216 #endif
Element * push_back(const T &value)
Definition: list.h:220
Definition: mutex.h:45
Definition: rid.h:104
virtual void unlock()=0
Unlock the mutex, let other threads continue.
Definition: rid.h:47
virtual void lock()=0
Lock the mutex, block if locked by someone else.
const TKey * next(const TKey *p_key) const
Definition: hash_map.h:514
static Mutex * create(bool p_recursive=true)
Create a mutex.
Definition: mutex.cpp:37
bool erase(const TKey &p_key)
Definition: hash_map.h:431
_FORCE_INLINE_ TData * getptr(const TKey &p_key)
Definition: hash_map.h:341
Definition: rid.h:87