Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

1005 linhas
27 KiB

  1. #pragma once
  2. #include <limits>
  3. #include <vector>
  4. #include <string>
  5. #include <cstdint>
  6. #include "./Misc.h"
  7. #include "./Exception.h"
  8. namespace utl
  9. {
  10. struct Handle
  11. {
  12. uint64_t value;
  13. inline explicit operator bool () const;
  14. inline operator uint64_t() const;
  15. inline Handle& operator = (uint64_t);
  16. inline Handle& operator = (const Handle&);
  17. inline bool operator == (const Handle&) const;
  18. inline bool operator != (const Handle&) const;
  19. inline bool operator <= (const Handle&) const;
  20. inline bool operator >= (const Handle&) const;
  21. inline bool operator < (const Handle&) const;
  22. inline bool operator > (const Handle&) const;
  23. inline bool operator == (const uint64_t&) const;
  24. inline bool operator != (const uint64_t&) const;
  25. inline bool operator <= (const uint64_t&) const;
  26. inline bool operator >= (const uint64_t&) const;
  27. inline bool operator < (const uint64_t&) const;
  28. inline bool operator > (const uint64_t&) const;
  29. inline std::string toString () const;
  30. inline Handle();
  31. inline Handle(const uint64_t&);
  32. inline Handle(const Handle&);
  33. static inline bool fromString(const std::string& str, Handle& handle);
  34. static inline const Handle& empty();
  35. };
  36. using TypeId = uint8_t;
  37. using SystemId = uint8_t;
  38. namespace __impl
  39. {
  40. using Index = size_t;
  41. using InternIndex = ssize_t;
  42. static constexpr InternIndex INVALID_INDEX = -1;
  43. static constexpr size_t GROW_SIZE = 100;
  44. enum class EntryStatus
  45. {
  46. Unknown,
  47. Used,
  48. Free,
  49. };
  50. #pragma pack(push, 1)
  51. struct HandleData
  52. {
  53. SystemId systemId; // 0..7 system id (to manage handles for multiple (dedicated) subsystems)
  54. TypeId typeId; // 8..15 type id (defined by user)
  55. uint16_t counter; // 16..31 reusage counter
  56. uint32_t entryIndex; // 32..64 index in data array (unique for each system)
  57. };
  58. #pragma pack(pop)
  59. static_assert(sizeof(Handle) == sizeof(HandleData), "mismatching size of Handle and HandleData");
  60. static_assert(sizeof(Handle) == 8, "size of Handle is not equal 64");
  61. inline HandleData makeHandleData(const Handle& handle);
  62. inline Handle makeHandle (HandleData hd);
  63. template<class TEntry>
  64. struct System;
  65. template<class TValue>
  66. struct Entry
  67. {
  68. public:
  69. using value_type = TValue;
  70. using this_type = Entry<value_type>;
  71. using wrapper_type = wrapper<value_type>;
  72. private:
  73. InternIndex _next;
  74. InternIndex _prev;
  75. uint16_t _counter;
  76. EntryStatus _status;
  77. TypeId _typeId;
  78. wrapper_type _data;
  79. public:
  80. inline InternIndex next () const;
  81. inline void next (InternIndex value);
  82. inline InternIndex prev () const;
  83. inline void prev (InternIndex value);
  84. inline EntryStatus status () const;
  85. inline void link (InternIndex prev, InternIndex next, EntryStatus status);
  86. inline void unlink ();
  87. inline uint16_t counter () const;
  88. inline void assign (value_type value, const TypeId& tId, const uint16_t cntr = 0);
  89. inline value_type data ();
  90. inline void data (value_type v);
  91. inline Entry();
  92. inline Entry(Entry&&);
  93. inline Entry(const Entry&);
  94. };
  95. template<class TEntry>
  96. struct System
  97. {
  98. public:
  99. using entry_type = TEntry;
  100. using this_type = System<entry_type>;
  101. using entry_vector_type = std::vector<entry_type>;
  102. private:
  103. InternIndex _firstFree;
  104. InternIndex _lastFree;
  105. InternIndex _firstUsed;
  106. InternIndex _lastUsed;
  107. entry_vector_type _entries;
  108. inline void pushFront (Index index, InternIndex& first, InternIndex& last, EntryStatus status);
  109. inline void pushBack (Index index, InternIndex& first, InternIndex& last, EntryStatus status);
  110. inline Index popFront (bool canGrow, InternIndex& first, InternIndex& last, EntryStatus status);
  111. inline Index popBack (bool canGrow, InternIndex& first, InternIndex& last, EntryStatus status);
  112. inline void remove (Index index, InternIndex& first, InternIndex& last, EntryStatus status);
  113. public:
  114. inline void grow (size_t size = 0);
  115. inline void pushFrontFree (Index index);
  116. inline void pushFrontUsed (Index index);
  117. inline void pushBackFree (Index index);
  118. inline void pushBackUsed (Index index);
  119. inline Index popFrontFree ();
  120. inline Index popFrontUsed ();
  121. inline Index popBackFree ();
  122. inline Index popBackUsed ();
  123. inline void removeFree (Index index);
  124. inline void removeUsed (Index index);
  125. inline size_t size () const;
  126. inline entry_type& operator[] (const Index& index);
  127. inline const entry_type& operator[] (const Index& index) const;
  128. inline System();
  129. inline System(System&&);
  130. inline System(const System&&);
  131. };
  132. template<class TEntry>
  133. struct Systems
  134. {
  135. public:
  136. using entry_type = TEntry;
  137. using this_type = System<entry_type>;
  138. using system_type = System<entry_type>;
  139. using system_vector_type = std::vector<system_type>;
  140. private:
  141. system_vector_type _systems;
  142. public:
  143. inline system_type& operator[] (const Index& index);
  144. inline const system_type& operator[] (const Index& index) const;
  145. inline size_t size () const;
  146. inline void clear ();
  147. };
  148. }
  149. inline TypeId getTypeId(const Handle& handle)
  150. { return __impl::makeHandleData(handle).typeId; }
  151. inline SystemId getSystemId(const Handle& handle)
  152. { return __impl::makeHandleData(handle).systemId; }
  153. template<class T>
  154. class HandleManager
  155. {
  156. public:
  157. using value_type = T;
  158. using this_type = HandleManager<value_type>;
  159. using entry_type = __impl::Entry<value_type>;
  160. using systems_type = __impl::Systems<entry_type>;
  161. private:
  162. systems_type _systems;
  163. public:
  164. /** check if an given handle is valid
  165. * @param handle handle to check
  166. * @return TRUE if handle is valid, FALSE otherwise */
  167. inline bool isValid(const Handle& handle) const;
  168. /** try to get the value for a given handle
  169. * @param handle handle to get value for
  170. * @param value parameter to store value at
  171. * @return TRUE on success, FALSE otherwise */
  172. inline bool tryGet(const Handle& handle, value_type& value);
  173. /** get the value for a given handle
  174. * @param handle handle to get value for
  175. * @return valid stored for handle */
  176. inline value_type get(const Handle& handle);
  177. /** update the value of a given handle (only valid handles are accepted)
  178. * @param handle handle to update value for
  179. * @param value new value to store
  180. * @return TRUE on success, FALSE otherwise (invalid handle) */
  181. inline bool update(const Handle& handle, value_type value);
  182. /** set the value for a given handle (this will add the item to the manager if the handle is unknown)
  183. * @param handle handle to set value for
  184. * @param value value to store
  185. * @return TRUE on success, FALSE otherwise (the storage entry is used by an other value) */
  186. inline bool set(const Handle& handle, value_type value);
  187. /** insert a new value to the manager
  188. * @param tId type id of the value
  189. * @param sId system id of the value
  190. * @param value value to add
  191. * @return Handle of the stored value */
  192. inline Handle insert(const TypeId& tId, const SystemId& sId, value_type value);
  193. /** remove the value of a given handle
  194. * @param handle handle to remove value for
  195. * @return TRUE on success, FALSE otherwise (handle is invalid) */
  196. inline bool remove(const Handle& handle);
  197. /** access values by a given handle
  198. * @param handle handle to get value for
  199. * @return reference to the value */
  200. inline value_type& operator[](const Handle& handle);
  201. /** remove all stored valus and reset the handle manager completely */
  202. inline void clear();
  203. };
  204. }
  205. /* HELPER ****************************************************************************************/
  206. inline
  207. utl::Handle::operator bool() const
  208. { return static_cast<bool>(value); }
  209. inline
  210. utl::Handle::operator uint64_t() const
  211. { return value; }
  212. inline utl::Handle&
  213. utl::Handle::operator =(uint64_t v)
  214. {
  215. value = v;
  216. return *this;
  217. }
  218. inline utl::Handle&
  219. utl::Handle::operator =(const Handle& other)
  220. {
  221. value = other.value;
  222. return *this;
  223. }
  224. inline bool
  225. utl::Handle::operator ==(const Handle& other) const
  226. { return value == other.value; }
  227. inline bool
  228. utl::Handle::operator !=(const Handle& other) const
  229. { return value != other.value; }
  230. inline bool
  231. utl::Handle::operator <=(const Handle& other) const
  232. { return value <= other.value; }
  233. inline bool
  234. utl::Handle::operator >=(const Handle& other) const
  235. { return value >= other.value; }
  236. inline bool
  237. utl::Handle::operator <(const Handle& other) const
  238. { return value < other.value; }
  239. inline bool
  240. utl::Handle::operator >(const Handle& other) const
  241. { return value > other.value; }
  242. inline bool
  243. utl::Handle::operator ==(const uint64_t& other) const
  244. { return value == other; }
  245. inline bool
  246. utl::Handle::operator !=(const uint64_t& other) const
  247. { return value != other; }
  248. inline bool
  249. utl::Handle::operator <=(const uint64_t& other) const
  250. { return value <= other; }
  251. inline bool
  252. utl::Handle::operator >=(const uint64_t& other) const
  253. { return value >= other; }
  254. inline bool
  255. utl::Handle::operator <(const uint64_t& other) const
  256. { return value < other; }
  257. inline bool
  258. utl::Handle::operator >(const uint64_t& other) const
  259. { return value > other; }
  260. inline std::string
  261. utl::Handle::toString() const
  262. {
  263. char buffer[2*sizeof(*this)+3];
  264. memset(&buffer[0], 0, sizeof(buffer));
  265. const uint8_t *p = reinterpret_cast<const uint8_t*>(this);
  266. int x = 0;
  267. for (size_t i = 0; i < sizeof(*this); ++i)
  268. {
  269. if (i == 1 || i == 2 || i == 4)
  270. {
  271. buffer[2*i+x] = '-';
  272. ++x;
  273. }
  274. buffer[2*i+x] = static_cast<char>((p[i] >> 4) & 0x0F);
  275. buffer[2*i+x+1] = static_cast<char>((p[i] >> 0) & 0x0F);
  276. buffer[2*i+x] = static_cast<char>(buffer[2*i+x] + (buffer[2*i+x] > 9 ? 'A' - 10 : '0'));
  277. buffer[2*i+x+1] = static_cast<char>(buffer[2*i+x+1] + (buffer[2*i+x+1] > 9 ? 'A' - 10 : '0'));
  278. }
  279. return std::string(&buffer[0], sizeof(buffer));
  280. }
  281. inline utl::Handle::Handle() :
  282. value(0)
  283. { }
  284. inline utl::Handle::Handle(const uint64_t& v) :
  285. value(v)
  286. { }
  287. inline utl::Handle::Handle(const Handle& other) :
  288. value(other.value)
  289. { }
  290. inline bool
  291. utl::Handle::fromString(const std::string& str, Handle& handle)
  292. {
  293. memset(&handle, 0, sizeof(handle));
  294. const char *c = str.c_str();
  295. const char *e = c + str.size();
  296. uint8_t* p = reinterpret_cast<uint8_t*>(&handle);
  297. size_t i = 0;
  298. while(c < e && i < 2*sizeof(handle))
  299. {
  300. if (*c != '-')
  301. {
  302. uint8_t v;
  303. if (*c >= '0' && *c <= '9')
  304. v = static_cast<uint8_t>(*c - '0');
  305. else if (*c >= 'a' && *c <= 'f')
  306. v = static_cast<uint8_t>(*c - 'a');
  307. else if (*c >= 'A' && *c <= 'F')
  308. v = static_cast<uint8_t>(*c - 'A');
  309. else
  310. return false;
  311. if (i & 1)
  312. v = static_cast<uint8_t>(v << 4);
  313. p[i >> 1] |= v;
  314. ++i;
  315. }
  316. ++c;
  317. }
  318. return (c == e && i == 2*sizeof(handle));
  319. }
  320. inline const utl::Handle&
  321. utl::Handle::empty()
  322. {
  323. static const Handle value;
  324. return value;
  325. }
  326. inline utl::__impl::HandleData utl::__impl::makeHandleData(const Handle& handle)
  327. {
  328. HandleData hd = reinterpret_cast<const HandleData&>(handle);
  329. hd.systemId = ntoh(hd.systemId);
  330. hd.typeId = ntoh(hd.typeId);
  331. hd.counter = ntoh(hd.counter);
  332. hd.entryIndex = ntoh(hd.entryIndex);
  333. return hd;
  334. }
  335. inline utl::Handle utl::__impl::makeHandle(HandleData hd)
  336. {
  337. hd.systemId = hton(hd.systemId);
  338. hd.typeId = hton(hd.typeId);
  339. hd.counter = hton(hd.counter);
  340. hd.entryIndex = hton(hd.entryIndex);
  341. return reinterpret_cast<const Handle&>(hd);
  342. }
  343. /* ENTRY *****************************************************************************************/
  344. template<class T>
  345. inline utl::__impl::InternIndex
  346. utl::__impl::Entry<T>::next() const
  347. {
  348. return _next;
  349. }
  350. template<class T>
  351. inline void
  352. utl::__impl::Entry<T>::next(
  353. InternIndex value)
  354. {
  355. _next = value;
  356. }
  357. template<class T>
  358. inline utl::__impl::InternIndex
  359. utl::__impl::Entry<T>::prev() const
  360. {
  361. return _prev;
  362. }
  363. template<class T>
  364. inline void
  365. utl::__impl::Entry<T>::prev(
  366. InternIndex value)
  367. {
  368. _prev = value;
  369. }
  370. template<class T>
  371. inline utl::__impl::EntryStatus
  372. utl::__impl::Entry<T>::status() const
  373. {
  374. return _status;
  375. }
  376. template<class T>
  377. inline void
  378. utl::__impl::Entry<T>::link(InternIndex prev, InternIndex next, EntryStatus status)
  379. {
  380. assert(status != EntryStatus::Unknown);
  381. _prev = prev;
  382. _next = next;
  383. _status = status;
  384. }
  385. template<class T>
  386. inline void
  387. utl::__impl::Entry<T>::unlink()
  388. {
  389. _prev = INVALID_INDEX;
  390. _next = INVALID_INDEX;
  391. _status = EntryStatus::Unknown;
  392. }
  393. template<class T>
  394. inline uint16_t
  395. utl::__impl::Entry<T>::counter() const
  396. { return _counter; }
  397. template<class T>
  398. inline void
  399. utl::__impl::Entry<T>::assign(
  400. value_type value,
  401. const TypeId& tId,
  402. const uint16_t cntr)
  403. {
  404. using namespace ::utl;
  405. using namespace ::utl::__impl;
  406. assert(_status == EntryStatus::Used);
  407. _typeId = tId;
  408. _data = value;
  409. if (cntr != 0)
  410. _counter = cntr;
  411. else if (++_counter == 0)
  412. _counter = 1;
  413. }
  414. template<class T>
  415. inline typename utl::__impl::Entry<T>::value_type
  416. utl::__impl::Entry<T>::data()
  417. {
  418. return *_data;
  419. }
  420. template<class T>
  421. inline void
  422. utl::__impl::Entry<T>::data(
  423. value_type v)
  424. {
  425. _data = v;
  426. }
  427. template<class T>
  428. inline utl::__impl::Entry<T>::Entry() :
  429. _next (INVALID_INDEX),
  430. _prev (INVALID_INDEX),
  431. _counter(0),
  432. _status (EntryStatus::Unknown),
  433. _typeId (0)
  434. { }
  435. template<class T>
  436. inline utl::__impl::Entry<T>::Entry(Entry&& other) :
  437. _next (std::move(other)._next),
  438. _prev (std::move(other)._prev),
  439. _counter(std::move(other)._counter),
  440. _status (std::move(other)._status),
  441. _typeId (std::move(other)._typeId),
  442. _data (std::move(other)._data)
  443. { }
  444. template<class T>
  445. inline utl::__impl::Entry<T>::Entry(const Entry& other) :
  446. _next (other._next),
  447. _prev (other._prev),
  448. _counter(other._counter),
  449. _status (other._status),
  450. _typeId (other._typeId),
  451. _data (other._data)
  452. { }
  453. /* SYSTEM ****************************************************************************************/
  454. template<class T>
  455. inline void
  456. utl::__impl::System<T>::pushFront(
  457. Index index,
  458. InternIndex& first,
  459. InternIndex& last,
  460. EntryStatus status)
  461. {
  462. assert(index < _entries.size());
  463. auto& entry = _entries[index];
  464. assert(entry.status() == EntryStatus::Unknown);
  465. if (first != INVALID_INDEX)
  466. {
  467. assert(first >= 0);
  468. assert(first < _entries.size());
  469. auto& firstEntry = _entries[first];
  470. assert(firstEntry.status() == status);
  471. firstEntry.prev(index);
  472. }
  473. entry.link(INVALID_INDEX, first, status);
  474. first = index;
  475. if (last == INVALID_INDEX)
  476. last = index;
  477. }
  478. template<class T>
  479. inline void
  480. utl::__impl::System<T>::pushBack(
  481. Index index,
  482. InternIndex& first,
  483. InternIndex& last,
  484. EntryStatus status)
  485. {
  486. assert(index < _entries.size());
  487. auto& entry = _entries[index];
  488. assert(entry.status() == EntryStatus::Unknown);
  489. if (last != INVALID_INDEX)
  490. {
  491. assert(last >= 0);
  492. assert(last < _entries.size());
  493. auto& lastEntry = _entries[last];
  494. assert(lastEntry.status() == status);
  495. lastEntry.next(index);
  496. }
  497. entry.link(last, INVALID_INDEX, status);
  498. last = index;
  499. if (first == INVALID_INDEX)
  500. first = index;
  501. }
  502. template<class T>
  503. inline utl::__impl::Index
  504. utl::__impl::System<T>::popFront(
  505. bool canGrow,
  506. InternIndex& first,
  507. InternIndex& last,
  508. EntryStatus status)
  509. {
  510. if ( canGrow
  511. && ( first >= static_cast<InternIndex>(_entries.size())
  512. || first == INVALID_INDEX))
  513. grow(first + GROW_SIZE);
  514. assert(first >= 0);
  515. assert(first < _entries.size());
  516. auto& entry = _entries[first];
  517. assert(entry.status() == status);
  518. Index ret = first;
  519. if (last == first)
  520. last = entry.next();
  521. first = entry.next();
  522. entry.unlink();
  523. if (first != INVALID_INDEX)
  524. {
  525. assert(first >= 0);
  526. assert(first < _entries.size());
  527. auto& firstEntry = _entries[first];
  528. assert(firstEntry.status() == status);
  529. firstEntry.prev(INVALID_INDEX);
  530. }
  531. return ret;
  532. }
  533. template<class T>
  534. inline utl::__impl::Index
  535. utl::__impl::System<T>::popBack(
  536. bool canGrow,
  537. InternIndex& first,
  538. InternIndex& last,
  539. EntryStatus status)
  540. {
  541. if ( canGrow
  542. && last >= _entries.size())
  543. grow(last + GROW_SIZE);
  544. assert(last >= 0);
  545. assert(last < _entries.size());
  546. auto& entry = _entries[last];
  547. assert(entry.status() == status);
  548. Index ret = last;
  549. if (first == last)
  550. first = entry._prev;
  551. last = entry._prev;
  552. entry.unlink();
  553. if (last != INVALID_INDEX)
  554. {
  555. assert(last >= 0);
  556. assert(last < _entries.size());
  557. auto& lastEntry = _entries[last];
  558. assert(lastEntry.status() == status);
  559. lastEntry.next(INVALID_INDEX);
  560. }
  561. return ret;
  562. }
  563. template<class T>
  564. inline void
  565. utl::__impl::System<T>::remove(
  566. Index index,
  567. InternIndex& first,
  568. InternIndex& last,
  569. EntryStatus status)
  570. {
  571. assert(index >= 0);
  572. assert(index < _entries.size());
  573. auto& entry = _entries[index];
  574. assert(entry.status() == status);
  575. if (entry.prev() != INVALID_INDEX)
  576. {
  577. assert(entry.prev() >= 0);
  578. assert(entry.prev() < _entries.size());
  579. _entries[entry.prev()].next(entry.next());
  580. }
  581. if (entry.next() != INVALID_INDEX)
  582. {
  583. assert(entry.next() >= 0);
  584. assert(entry.next() < _entries.size());
  585. _entries[entry.next()].prev(entry.prev());
  586. }
  587. if (first == static_cast<InternIndex>(index))
  588. first = entry.next();
  589. if (last == static_cast<InternIndex>(index))
  590. last = entry.prev();
  591. entry.unlink();
  592. }
  593. template<class T>
  594. inline void
  595. utl::__impl::System<T>::grow(
  596. size_t size)
  597. {
  598. if (size == 0)
  599. size = _entries.size() + GROW_SIZE;
  600. if (size < _entries.size())
  601. return;
  602. size_t idx = _entries.size();
  603. _entries.resize(size);
  604. while (idx < _entries.size())
  605. {
  606. pushBackFree(idx);
  607. ++idx;
  608. }
  609. }
  610. template<class T>
  611. inline void
  612. utl::__impl::System<T>::pushFrontFree(
  613. Index index)
  614. {
  615. pushFront(index, _firstFree, _lastFree, EntryStatus::Free);
  616. }
  617. template<class T>
  618. inline void
  619. utl::__impl::System<T>::pushFrontUsed(
  620. Index index)
  621. {
  622. pushFront(index, _firstUsed, _lastUsed, EntryStatus::Used);
  623. }
  624. template<class T>
  625. inline void
  626. utl::__impl::System<T>::pushBackFree(
  627. Index index)
  628. {
  629. pushBack(index, _firstFree, _lastFree, EntryStatus::Free);
  630. }
  631. template<class T>
  632. inline void
  633. utl::__impl::System<T>::pushBackUsed(
  634. Index index)
  635. {
  636. pushBack(index, _firstUsed, _lastUsed, EntryStatus::Used);
  637. }
  638. template<class T>
  639. inline utl::__impl::Index
  640. utl::__impl::System<T>::popFrontFree()
  641. {
  642. return popFront(true, _firstFree, _lastFree, EntryStatus::Free);
  643. }
  644. template<class T>
  645. inline utl::__impl::Index
  646. utl::__impl::System<T>::popFrontUsed()
  647. {
  648. return popFront(false, _firstUsed, _lastUsed, EntryStatus::Used);
  649. }
  650. template<class T>
  651. inline utl::__impl::Index
  652. utl::__impl::System<T>::popBackFree()
  653. {
  654. return popBack(true, _firstFree, _lastFree, EntryStatus::Free);
  655. }
  656. template<class T>
  657. inline utl::__impl::Index
  658. utl::__impl::System<T>::popBackUsed()
  659. {
  660. return popBack(false, _firstUsed, _lastUsed, EntryStatus::Used);
  661. }
  662. template<class T>
  663. inline void
  664. utl::__impl::System<T>::removeFree(
  665. Index index)
  666. {
  667. remove(index, _firstFree, _lastFree, EntryStatus::Free);
  668. }
  669. template<class T>
  670. inline void
  671. utl::__impl::System<T>::removeUsed(
  672. Index index)
  673. {
  674. remove(index, _firstUsed, _lastUsed, EntryStatus::Used);
  675. }
  676. template<class T>
  677. inline size_t
  678. utl::__impl::System<T>::size() const
  679. {
  680. return _entries.size();
  681. }
  682. template<class T>
  683. inline typename utl::__impl::System<T>::entry_type&
  684. utl::__impl::System<T>::operator[](
  685. const Index& index)
  686. {
  687. if (index >= _entries.size())
  688. grow(index + GROW_SIZE);
  689. return _entries[index];
  690. }
  691. template<class T>
  692. inline const typename utl::__impl::System<T>::entry_type&
  693. utl::__impl::System<T>::operator[](
  694. const Index& index) const
  695. {
  696. return _entries.at(index);
  697. }
  698. template<class T>
  699. inline utl::__impl::System<T>::System() :
  700. _firstFree (INVALID_INDEX),
  701. _lastFree (INVALID_INDEX),
  702. _firstUsed (INVALID_INDEX),
  703. _lastUsed (INVALID_INDEX)
  704. { }
  705. template<class T>
  706. inline utl::__impl::System<T>::System(System&& other) :
  707. _firstFree (std::move(other)._firstFree),
  708. _lastFree (std::move(other)._lastFree),
  709. _firstUsed (std::move(other)._firstUsed),
  710. _lastUsed (std::move(other)._lastUsed),
  711. _entries (std::move(other)._entries)
  712. { }
  713. template<class T>
  714. inline utl::__impl::System<T>::System(const System&& other) :
  715. _firstFree (other._firstFree),
  716. _lastFree (other._lastFree),
  717. _firstUsed (other._firstUsed),
  718. _lastUsed (other._lastUsed),
  719. _entries (other._entries)
  720. { }
  721. /* SYSTEMS ***************************************************************************************/
  722. template<class T>
  723. inline typename utl::__impl::Systems<T>::system_type&
  724. utl::__impl::Systems<T>::operator[](
  725. const Index& index)
  726. {
  727. if (index >= _systems.size())
  728. _systems.resize(index + 1);
  729. return _systems[index];
  730. }
  731. template<class T>
  732. inline const typename utl::__impl::Systems<T>::system_type&
  733. utl::__impl::Systems<T>::operator[](
  734. const Index& index) const
  735. {
  736. return _systems[index];
  737. }
  738. template<class T>
  739. inline size_t
  740. utl::__impl::Systems<T>::size() const
  741. {
  742. return _systems.size();
  743. }
  744. template<class T>
  745. inline void
  746. utl::__impl::Systems<T>::clear()
  747. {
  748. _systems.clear();
  749. }
  750. /* HANDLEMANAGER *********************************************************************************/
  751. template<class T>
  752. inline bool
  753. utl::HandleManager<T>::isValid(
  754. const utl::Handle& handle) const
  755. {
  756. using namespace __impl;
  757. auto hd = makeHandleData(handle);
  758. if (hd.systemId >= _systems.size())
  759. return false;
  760. auto& system = _systems[hd.systemId];
  761. if (hd.entryIndex >= system.size())
  762. return false;
  763. auto& entry = system[hd.entryIndex];
  764. return entry.status() == EntryStatus::Used
  765. && entry.counter() == hd.counter;
  766. }
  767. template<class T>
  768. inline bool
  769. utl::HandleManager<T>::tryGet(
  770. const utl::Handle& handle,
  771. typename utl::HandleManager<T>::value_type& value)
  772. {
  773. using namespace __impl;
  774. auto ret = isValid(handle);
  775. if (ret)
  776. {
  777. auto hd = makeHandleData(handle);
  778. value = _systems[hd.systemId][hd.entryIndex].data();
  779. }
  780. return ret;
  781. }
  782. template<class T>
  783. inline typename utl::HandleManager<T>::value_type
  784. utl::HandleManager<T>::get(
  785. const utl::Handle& handle)
  786. {
  787. value_type ret;
  788. if (!tryGet(handle, ret))
  789. throw Exception("invalid handle");
  790. return ret;
  791. }
  792. template<class T>
  793. inline bool
  794. utl::HandleManager<T>::update(
  795. const utl::Handle& handle,
  796. typename utl::HandleManager<T>::value_type value)
  797. {
  798. using namespace __impl;
  799. if (isValid(handle))
  800. {
  801. auto hd = makeHandleData(handle);
  802. _systems[hd.systemId][hd.entryIndex].data(value);
  803. return true;
  804. }
  805. return false;
  806. }
  807. template<class T>
  808. inline bool
  809. utl::HandleManager<T>::set(
  810. const utl::Handle& handle,
  811. typename utl::HandleManager<T>::value_type value)
  812. {
  813. using namespace __impl;
  814. if (!isValid(handle))
  815. {
  816. auto hd = makeHandleData(handle);
  817. auto& system = _systems[hd.systemId];
  818. auto& entry = system[hd.entryIndex];
  819. bool ret = entry.status() == EntryStatus::Free;
  820. if (ret)
  821. {
  822. system.removeFree (hd.entryIndex);
  823. system.pushBackUsed(hd.entryIndex);
  824. entry.assign(value, hd.typeId, hd.counter);
  825. }
  826. return ret;
  827. }
  828. else
  829. {
  830. return update(handle, value);
  831. }
  832. }
  833. template<class T>
  834. inline utl::Handle
  835. utl::HandleManager<T>::insert(
  836. const TypeId& tId,
  837. const SystemId& sId,
  838. typename utl::HandleManager<T>::value_type value)
  839. {
  840. using namespace __impl;
  841. auto& system = _systems[sId];
  842. auto index = system.popFrontFree();
  843. system.pushBackUsed(index);
  844. auto& entry = system[index];
  845. entry.assign(value, tId);
  846. HandleData hd;
  847. hd.entryIndex = static_cast<uint32_t>(index);
  848. hd.counter = entry.counter();
  849. hd.typeId = tId,
  850. hd.systemId = sId;
  851. return makeHandle(hd);
  852. }
  853. template<class T>
  854. inline bool
  855. utl::HandleManager<T>::remove(
  856. const utl::Handle& handle)
  857. {
  858. using namespace __impl;
  859. if (!isValid(handle))
  860. return false;
  861. auto hd = makeHandleData(handle);
  862. auto& system = _systems[hd.systemId];
  863. system.removeUsed(hd.entryIndex);
  864. system.pushFrontFree(hd.entryIndex);
  865. return true;
  866. }
  867. template<class T>
  868. inline typename utl::HandleManager<T>::value_type&
  869. utl::HandleManager<T>::operator[](
  870. const utl::Handle& handle)
  871. {
  872. using namespace __impl;
  873. if (!isValid(handle))
  874. throw Exception("invalid handle");
  875. auto hd = makeHandleData(handle);
  876. auto& system = _systems[hd.systemId];
  877. auto& entry = system[hd.entryIndex];
  878. return entry.data;
  879. }
  880. template<class T>
  881. inline void
  882. utl::HandleManager<T>::clear()
  883. { _systems.clear(); }