Smolgui
Immediate gui library based on SFML
Loading...
Searching...
No Matches
ObjectPool.tpp
Go to the documentation of this file.
1namespace sgui
2{
3/////////////////////////////////////////////////
4// Ctor
5/////////////////////////////////////////////////
6template <typename Object, typename ObjectId>
7ObjectPool <Object, ObjectId>::ObjectPool (ObjectPool <Object, ObjectId>&& rhs)
8{
9 WriteLock rhsLock (rhs.mMutex);
10 mIdToSlot = std::move (rhs.mIdToSlot);
11 mSlotToId = std::move (rhs.mSlotToId);
12 mObjects = std::move (rhs.mObjects);
13}
14
15/////////////////////////////////////////////////
16template <typename Object, typename ObjectId>
17ObjectPool <Object, ObjectId>::ObjectPool (const ObjectPool <Object, ObjectId>& rhs)
18{
19 WriteLock rhsLock (rhs.mMutex);
20 mIdToSlot = rhs.mIdToSlot;
21 mSlotToId = rhs.mSlotToId;
22 mObjects = rhs.mObjects;
23}
24
25/////////////////////////////////////////////////
26template <typename Object, typename ObjectId>
27ObjectPool <Object, ObjectId>&
28ObjectPool <Object, ObjectId>::operator= (ObjectPool <Object, ObjectId>&& rhs)
29{
30 if (this != &rhs) {
31 WriteLock lhsLock (mMutex, std::defer_lock);
32 WriteLock rhsLock (rhs.mMutex, std::defer_lock);
33 std::lock (lhsLock, rhsLock);
34 mIdToSlot = std::move (rhs.mIdToSlot);
35 mSlotToId = std::move (rhs.mSlotToId);
36 mObjects = std::move (rhs.mObjects);
37 }
38 return *this;
39}
40
41/////////////////////////////////////////////////
42template <typename Object, typename ObjectId>
43ObjectPool <Object, ObjectId>&
44ObjectPool <Object, ObjectId>::operator= (const ObjectPool <Object, ObjectId>& rhs)
45{
46 if (this != &rhs) {
47 WriteLock lhsLock (mMutex, std::defer_lock);
48 ReadLock rhsLock (rhs.mMutex, std::defer_lock);
49 std::lock (lhsLock, rhsLock);
50 mIdToSlot = rhs.mIdToSlot;
51 mSlotToId = rhs.mSlotToId;
52 mObjects = rhs.mObjects;
53 }
54 return *this;
55}
56
57
58/////////////////////////////////////////////////
59// Class impl
60/////////////////////////////////////////////////
61template <typename Object, typename ObjectId>
62Object& ObjectPool <Object, ObjectId>::add (Object&& object, const ObjectId& id)
63{
64 // quit if id exist in pool
65 if (has (id)) return mObjects.back ();
66
67 // add object in pool and return it
68 trackSlot (id);
69 WriteLock lock (mMutex);
70 mObjects.emplace_back (std::forward <Object> (object));
71 return mObjects.back ();
72}
73
74/////////////////////////////////////////////////
75template <typename Object, typename ObjectId>
76Object& ObjectPool <Object, ObjectId>::add (const Object& object, const ObjectId& id)
77{
78 // quit if id exist in pool
79 if (has (id)) return mObjects.back ();
80
81 // add object in pool and return it
82 trackSlot (id);
83 WriteLock lock (mMutex);
84 mObjects.push_back (object);
85 return mObjects.back ();
86}
87
88/////////////////////////////////////////////////
89template <typename Object, typename ObjectId>
90template <typename... ObjectArgs>
91Object& ObjectPool <Object, ObjectId>::emplace (const ObjectId& id, ObjectArgs&&... constructorArgs)
92{
93 // quit if id exist in pool
94 if (has (id)) return mObjects.back ();
95
96 // emplace object in pool and return it
97 trackSlot (id);
98 WriteLock lock (mMutex);
99 mObjects.emplace_back (std::forward <ObjectArgs> (constructorArgs)...);
100 return mObjects.back ();
101}
102
103/////////////////////////////////////////////////
104template <typename Object, typename ObjectId>
105void ObjectPool <Object, ObjectId>::remove (const ObjectId& object)
106{
107 // quit if id does not exist in pool
108 if (!has (object)) return;
109
110 // get corresponding slot of object to be removed
111 WriteLock lock (mMutex);
112 const auto slot = mIdToSlot [object];
113 // swap object to be removed with the last one and removes it
114 std::swap (mObjects [slot], mObjects.back ());
115 mObjects.pop_back ();
116
117 // store new slot of the swapped last object
118 const auto lastObject = mSlotToId.back ();
119 mIdToSlot [lastObject] = slot;
120 mSlotToId [slot] = lastObject;
121 // erase id and slot of the removed object
122 mIdToSlot.erase (object);
123 mSlotToId.pop_back ();
124}
125
126/////////////////////////////////////////////////
127template <typename Object, typename ObjectId>
128void ObjectPool <Object, ObjectId>::reserve (const size_t amount)
129{
130 WriteLock lock (mMutex);
131 mIdToSlot.reserve (amount);
132 mSlotToId.reserve (amount);
133 mObjects.reserve (amount);
134}
135
136/////////////////////////////////////////////////
137template <typename Object, typename ObjectId>
138void ObjectPool <Object, ObjectId>::clear ()
139{
140 WriteLock lock (mMutex);
141 mIdToSlot.clear ();
142 mSlotToId.clear ();
143 mObjects.clear ();
144}
145
146/////////////////////////////////////////////////
147template <typename Object, typename ObjectId>
148bool ObjectPool <Object, ObjectId>::has (const ObjectId& object) const
149{
150 ReadLock lock (mMutex);
151 return mIdToSlot.find (object) != std::cend (mIdToSlot);
152}
153
154/////////////////////////////////////////////////
155template <typename Object, typename ObjectId>
156bool ObjectPool <Object, ObjectId>::empty () const
157{
158 ReadLock lock (mMutex);
159 return mObjects.empty ();
160}
161
162/////////////////////////////////////////////////
163template <typename Object, typename ObjectId>
164Object& ObjectPool <Object, ObjectId>::get (const ObjectId& object)
165{
166 ReadLock lock (mMutex);
167 return mObjects [mIdToSlot [object]];
168}
169
170/////////////////////////////////////////////////
171template <typename Object, typename ObjectId>
172const Object& ObjectPool <Object, ObjectId>::get (const ObjectId& object) const
173{
174 ReadLock lock (mMutex);
175 return mObjects [mIdToSlot.at (object)];
176}
177
178/////////////////////////////////////////////////
179template <typename Object, typename ObjectId>
180void ObjectPool <Object, ObjectId>::changeId (const ObjectId& oldId, const ObjectId& newId)
181{
182 WriteLock lock (mMutex);
183 const auto slot = mIdToSlot [oldId];
184 mIdToSlot [newId] = slot;
185 mSlotToId [slot] = newId;
186 mIdToSlot.erase (oldId);
187}
188
189/////////////////////////////////////////////////
190template <typename Object, typename ObjectId>
191std::vector <ObjectId>
192ObjectPool <Object, ObjectId>::ids () const
193{
194 WriteLock lock (mMutex);
195 auto list = std::vector <ObjectId> ();
196 list.reserve (mIdToSlot.size ());
197 for (const auto& idAndSlot : mIdToSlot) {
198 list.push_back (idAndSlot.first);
199 }
200 return list;
201}
202
203/////////////////////////////////////////////////
204template <typename Object, typename ObjectId>
205size_t ObjectPool <Object, ObjectId>::size () const
206{
207 ReadLock lock (mMutex);
208 return mObjects.size ();
209}
210
211/////////////////////////////////////////////////
212template <typename Object, typename ObjectId>
213void ObjectPool <Object, ObjectId>::trackSlot (const ObjectId& id)
214{
215 // compute slot and keep track of it and of id
216 WriteLock lock (mMutex);
217 mIdToSlot [id] = mSlotToId.size ();
218 mSlotToId.push_back (id);
219}
220
221} // namespace sgui