Simulant  21.12-574
A portable game engine for Windows, OSX, Linux, Dreamcast, and PSP
unique_id.h
1 /* * Copyright (c) 2011-2017 Luke Benstead https://simulant-engine.appspot.com
2  *
3  * This file is part of Simulant.
4  *
5  * Simulant is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Simulant 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 Simulant. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include <cstdint>
22 #include <cassert>
23 #include <functional>
24 #include <memory>
25 #include <type_traits>
26 #include <ostream>
27 #include <typeindex>
28 
29 namespace smlt {
30 
31 namespace _unique_id_impl {
32  template<class T>
33  struct is_shared_ptr : std::false_type {};
34 
35  template<class T>
36  struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};
37 
38  template<typename ResourceTypePtr, bool IsSharedPtr>
39  struct Members;
40 
41  template<typename ResourceTypePtr>
42  struct Members<ResourceTypePtr, false> {
43  ResourceTypePtr ptr;
44 
45  Members():
46  ptr(nullptr) {}
47 
48  Members(ResourceTypePtr ptr):
49  ptr(ptr) {}
50 
51  ResourceTypePtr as_pointer() const {
52  return ptr;
53  }
54  };
55 
56  template<typename ResourceTypePtr>
57  struct Members<ResourceTypePtr, true> {
58  typedef std::weak_ptr<typename ResourceTypePtr::element_type> weak_ptr_type;
59  weak_ptr_type ptr;
60 
61  Members() = default;
62 
63  Members(weak_ptr_type ptr):
64  ptr(ptr) {}
65 
66  Members(ResourceTypePtr ptr):
67  ptr(ptr) {}
68 
69  ResourceTypePtr as_pointer() const {
70  return ptr.lock();
71  }
72  };
73 }
74 
75 
76 template<typename ResourceTypePtr>
77 class UniqueID {
78 public:
79  typedef ResourceTypePtr resource_pointer_type;
80  typedef typename ResourceTypePtr::element_type element_type;
81 
82  explicit operator bool() const {
83  return id_ > 0;
84  }
85 
86  UniqueID():
87  id_(0) {}
88 
89  /* Unbound. This should only happen during instantiation by a manager */
90  UniqueID(uint32_t id):
91  id_(id) {
92  }
93 
94  UniqueID(const UniqueID<ResourceTypePtr>& other):
95  id_(other.id_),
96  members_(other.members_.ptr) {
97 
98  }
99 
100  /* Private API */
101  void _bind(resource_pointer_type ptr) {
102  members_ = MembersType(ptr);
103  }
104 
105  ResourceTypePtr fetch() const {
106  auto ret = members_.as_pointer();
107  return ret;
108  }
109 
110  template<typename T>
111  T* fetch_as() const {
112  /* The weird &(* casting is to handle smart pointers */
113  return dynamic_cast<T*>(&(*fetch()));
114  }
115 
116  bool is_bound() const {
117  return bool(members_.ptr);
118  }
119 
120  explicit UniqueID(uint32_t id, ResourceTypePtr ptr):
121  id_(id),
122  members_(ptr) {
123 
124  }
125 
126  bool operator==(const UniqueID<ResourceTypePtr>& other) const {
127  return this->id_ == other.id_;
128  }
129 
130  /* Implicit conversion from shared ptr type */
131  template<typename=std::enable_if<_unique_id_impl::is_shared_ptr<resource_pointer_type>::value>>
132  UniqueID(const resource_pointer_type& pointer) {
133  this->id_ = pointer->id().id_;
134  _bind(pointer);
135  }
136 
137  template<typename=std::enable_if<_unique_id_impl::is_shared_ptr<resource_pointer_type>::value>>
138  UniqueID& operator=(const resource_pointer_type& pointer) {
139  this->id_ = pointer->id().id_;
140  _bind(pointer);
141 
142  return *this;
143  }
144  /* Conversion ends */
145 
146  UniqueID& operator=(const UniqueID<ResourceTypePtr>& other) {
147  if(&other == this) {
148  return *this;
149  }
150 
151  this->id_ = other.id_;
152  this->members_.ptr = other.members_.ptr;
153  return *this;
154  }
155 
156  bool operator<(const UniqueID<ResourceTypePtr>& other) const {
157  return this->id_ < other.id_;
158  }
159 
160  bool operator!=(const UniqueID<ResourceTypePtr>& other) const {
161  return !(*this == other);
162  }
163 
164  friend std::ostream& operator<< (std::ostream& o, UniqueID<ResourceTypePtr> const& instance) {
165  return o << typeid(ResourceTypePtr).name() << ":" << instance.value();
166  }
167 
168  uint32_t value() const { return id_; }
169 
170 private:
171  uint32_t id_ = 0;
172 
173  typedef _unique_id_impl::Members<
174  ResourceTypePtr,
176  > MembersType;
177 
178  MembersType members_;
179 };
180 
181 typedef std::pair<std::type_index, uint32_t> UniqueIDKey;
182 
183 template<typename ID>
184 UniqueIDKey make_unique_id_key(const ID& id) {
185  return std::make_pair(
186  std::type_index(typeid(typename ID::element_type)),
187  id.value()
188  );
189 }
190 
191 template<typename UniqueID>
192 UniqueID make_unique_id_from_key(const UniqueIDKey& key) {
193  assert(key.first == std::type_index(typeid(typename UniqueID::element_type)));
194  return UniqueID(key.second);
195 }
196 
197 
198 }
199 
200 namespace std {
201  template<typename ResourcePtrType>
202  struct hash< smlt::UniqueID<ResourcePtrType> > {
203  size_t operator()(const smlt::UniqueID<ResourcePtrType>& id) const {
204  hash<uint32_t> make_hash;
205  return make_hash(id.value());
206  }
207  };
208 }
209 
210 
smlt::_unique_id_impl::Members
Definition: unique_id.h:39
smlt
Definition: animation.cpp:25
smlt::UniqueID
Definition: unique_id.h:77
smlt::_unique_id_impl::is_shared_ptr
Definition: unique_id.h:33
std
Extensions to the C++ standard library.
Definition: unique_id.h:200