You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1006 rivejä
28 KiB

  1. #pragma once
  2. #include <limits>
  3. #include <vector>
  4. #include <string>
  5. #include <cstdint>
  6. #include <cpputils/misc/convert.h>
  7. #include <cpputils/misc/exception.h>
  8. #include <cpputils/container/wrapper.h>
  9. namespace utl
  10. {
  11. struct handle
  12. {
  13. uint64_t value;
  14. inline explicit operator bool () const;
  15. inline operator uint64_t() const;
  16. inline handle& operator = (uint64_t);
  17. inline handle& operator = (const handle&);
  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 handle&) 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 bool operator > (const uint64_t&) const;
  30. inline std::string to_string () const;
  31. inline handle();
  32. inline handle(const uint64_t&);
  33. inline handle(const handle&);
  34. static inline bool from_string(const std::string& str, handle& handle);
  35. static inline const handle& empty();
  36. };
  37. using type_id_type = uint8_t;
  38. using system_id_type = uint8_t;
  39. namespace __impl
  40. {
  41. using index_type = size_t;
  42. static constexpr index_type invalid_index(std::numeric_limits<index_type>::max());
  43. static constexpr size_t grow_size (100);
  44. enum class entry_status
  45. {
  46. unknown,
  47. used,
  48. free,
  49. };
  50. #pragma pack(push, 1)
  51. struct handle_data
  52. {
  53. system_id_type system_id; // 0..7 system id (to manage handles for multiple (dedicated) subsystems)
  54. type_id_type type_id; // 8..15 type id (defined by user)
  55. uint16_t counter; // 16..31 reusage counter
  56. uint32_t entry_index; // 32..64 index in data array (unique for each system)
  57. };
  58. #pragma pack(pop)
  59. static_assert(sizeof(handle) == sizeof(handle_data), "mismatching size of handle and handle_data");
  60. static_assert(sizeof(handle) == 8, "size of handle is not equal 64");
  61. inline handle_data make_handle_data(const handle& handle);
  62. inline handle make_handle (handle_data hd);
  63. template<class T_entry>
  64. struct system;
  65. template<class T_value>
  66. struct entry
  67. {
  68. public:
  69. using value_type = T_value;
  70. using this_type = entry<value_type>;
  71. using wrapper_type = wrapper<value_type>;
  72. private:
  73. index_type _next;
  74. index_type _prev;
  75. uint16_t _counter;
  76. entry_status _status;
  77. type_id_type _type_id;
  78. wrapper_type _data;
  79. public:
  80. inline index_type next () const;
  81. inline void next (index_type value);
  82. inline index_type prev () const;
  83. inline void prev (index_type value);
  84. inline entry_status status () const;
  85. inline void link (index_type prev, index_type next, entry_status status);
  86. inline void unlink ();
  87. inline uint16_t counter () const;
  88. inline void assign (value_type value, const type_id_type& 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 T_entry>
  96. struct system
  97. {
  98. public:
  99. using entry_type = T_entry;
  100. using this_type = system<entry_type>;
  101. using entry_vector_type = std::vector<entry_type>;
  102. private:
  103. index_type _firstFree;
  104. index_type _lastFree;
  105. index_type _firstUsed;
  106. index_type _lastUsed;
  107. entry_vector_type _entries;
  108. inline void pushFront (index_type index, index_type& first, index_type& last, entry_status status);
  109. inline void pushBack (index_type index, index_type& first, index_type& last, entry_status status);
  110. inline index_type popFront (bool canGrow, index_type& first, index_type& last, entry_status status);
  111. inline index_type popBack (bool canGrow, index_type& first, index_type& last, entry_status status);
  112. inline void remove (index_type index, index_type& first, index_type& last, entry_status status);
  113. public:
  114. inline void grow (size_t size = 0);
  115. inline void pushFrontFree (index_type index);
  116. inline void pushFrontUsed (index_type index);
  117. inline void pushBackFree (index_type index);
  118. inline void pushBackUsed (index_type index);
  119. inline index_type popFrontFree ();
  120. inline index_type popFrontUsed ();
  121. inline index_type popBackFree ();
  122. inline index_type popBackUsed ();
  123. inline void removeFree (index_type index);
  124. inline void removeUsed (index_type index);
  125. inline size_t size () const;
  126. inline entry_type& operator[] (const index_type& index);
  127. inline const entry_type& operator[] (const index_type& index) const;
  128. inline system();
  129. inline system(system&&);
  130. inline system(const system&&);
  131. };
  132. template<class T_entry>
  133. struct systems
  134. {
  135. public:
  136. using entry_type = T_entry;
  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_type& index);
  144. inline const system_type& operator[] (const index_type& index) const;
  145. inline size_t size () const;
  146. inline void clear ();
  147. };
  148. }
  149. inline type_id_type get_type_id(const handle& handle)
  150. { return __impl::make_handle_data(handle).type_id; }
  151. inline system_id_type get_system_id(const handle& handle)
  152. { return __impl::make_handle_data(handle).system_id; }
  153. template<class T>
  154. class handle_manager
  155. {
  156. public:
  157. using value_type = T;
  158. using this_type = handle_manager<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 is_valid(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 try_get(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 type_id_type& tId, const system_id_type& 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::to_string() 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. size_t 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::from_string(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::handle_data utl::__impl::make_handle_data(const handle& handle)
  327. {
  328. handle_data hd = reinterpret_cast<const handle_data&>(handle);
  329. hd.system_id = ntoh(hd.system_id);
  330. hd.type_id = ntoh(hd.type_id);
  331. hd.counter = ntoh(hd.counter);
  332. hd.entry_index = ntoh(hd.entry_index);
  333. return hd;
  334. }
  335. inline utl::handle utl::__impl::make_handle(handle_data hd)
  336. {
  337. hd.system_id = hton(hd.system_id);
  338. hd.type_id = hton(hd.type_id);
  339. hd.counter = hton(hd.counter);
  340. hd.entry_index = hton(hd.entry_index);
  341. return reinterpret_cast<const handle&>(hd);
  342. }
  343. /* ENTRY *****************************************************************************************/
  344. template<class T>
  345. inline utl::__impl::index_type
  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. index_type value)
  354. {
  355. _next = value;
  356. }
  357. template<class T>
  358. inline utl::__impl::index_type
  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. index_type value)
  367. {
  368. _prev = value;
  369. }
  370. template<class T>
  371. inline utl::__impl::entry_status
  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(index_type prev, index_type next, entry_status status)
  379. {
  380. assert(status != entry_status::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 = entry_status::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 type_id_type& tId,
  402. const uint16_t cntr)
  403. {
  404. using namespace ::utl;
  405. using namespace ::utl::__impl;
  406. assert(_status == entry_status::used);
  407. _type_id = 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 (entry_status::unknown),
  433. _type_id (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. _type_id (std::move(other)._type_id),
  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. _type_id (other._type_id),
  451. _data (other._data)
  452. { }
  453. /* SYSTEM ****************************************************************************************/
  454. template<class T>
  455. inline void
  456. utl::__impl::system<T>::pushFront(
  457. index_type index,
  458. index_type& first,
  459. index_type& last,
  460. entry_status status)
  461. {
  462. assert(index < _entries.size());
  463. auto& entry = _entries[index];
  464. assert(entry.status() == entry_status::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_type index,
  482. index_type& first,
  483. index_type& last,
  484. entry_status status)
  485. {
  486. assert(index < _entries.size());
  487. auto& entry = _entries[index];
  488. assert(entry.status() == entry_status::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_type
  504. utl::__impl::system<T>::popFront(
  505. bool canGrow,
  506. index_type& first,
  507. index_type& last,
  508. entry_status status)
  509. {
  510. if ( canGrow
  511. && ( first >= _entries.size()
  512. || first == invalid_index))
  513. grow((first != invalid_index ? first : 0) + grow_size);
  514. assert(first >= 0);
  515. assert(first < _entries.size());
  516. auto& entry = _entries[first];
  517. assert(entry.status() == status);
  518. index_type 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_type
  535. utl::__impl::system<T>::popBack(
  536. bool canGrow,
  537. index_type& first,
  538. index_type& last,
  539. entry_status status)
  540. {
  541. if ( canGrow
  542. && ( last >= _entries.size()
  543. || last == invalid_index))
  544. grow((last != invalid_index ? last : 0) + grow_size);
  545. assert(last >= 0);
  546. assert(last < _entries.size());
  547. auto& entry = _entries[last];
  548. assert(entry.status() == status);
  549. index_type ret = last;
  550. if (first == last)
  551. first = entry._prev;
  552. last = entry._prev;
  553. entry.unlink();
  554. if (last != invalid_index)
  555. {
  556. assert(last >= 0);
  557. assert(last < _entries.size());
  558. auto& lastEntry = _entries[last];
  559. assert(lastEntry.status() == status);
  560. lastEntry.next(invalid_index);
  561. }
  562. return ret;
  563. }
  564. template<class T>
  565. inline void
  566. utl::__impl::system<T>::remove(
  567. index_type index,
  568. index_type& first,
  569. index_type& last,
  570. entry_status status)
  571. {
  572. assert(index >= 0);
  573. assert(index < _entries.size());
  574. auto& entry = _entries[index];
  575. assert(entry.status() == status);
  576. if (entry.prev() != invalid_index)
  577. {
  578. assert(entry.prev() >= 0);
  579. assert(entry.prev() < _entries.size());
  580. _entries[entry.prev()].next(entry.next());
  581. }
  582. if (entry.next() != invalid_index)
  583. {
  584. assert(entry.next() >= 0);
  585. assert(entry.next() < _entries.size());
  586. _entries[entry.next()].prev(entry.prev());
  587. }
  588. if (first == index)
  589. first = entry.next();
  590. if (last == index)
  591. last = entry.prev();
  592. entry.unlink();
  593. }
  594. template<class T>
  595. inline void
  596. utl::__impl::system<T>::grow(
  597. size_t size)
  598. {
  599. if (size == 0)
  600. size = _entries.size() + grow_size;
  601. if (size < _entries.size())
  602. return;
  603. size_t idx = _entries.size();
  604. _entries.resize(size);
  605. while (idx < _entries.size())
  606. {
  607. pushBackFree(idx);
  608. ++idx;
  609. }
  610. }
  611. template<class T>
  612. inline void
  613. utl::__impl::system<T>::pushFrontFree(
  614. index_type index)
  615. {
  616. pushFront(index, _firstFree, _lastFree, entry_status::free);
  617. }
  618. template<class T>
  619. inline void
  620. utl::__impl::system<T>::pushFrontUsed(
  621. index_type index)
  622. {
  623. pushFront(index, _firstUsed, _lastUsed, entry_status::used);
  624. }
  625. template<class T>
  626. inline void
  627. utl::__impl::system<T>::pushBackFree(
  628. index_type index)
  629. {
  630. pushBack(index, _firstFree, _lastFree, entry_status::free);
  631. }
  632. template<class T>
  633. inline void
  634. utl::__impl::system<T>::pushBackUsed(
  635. index_type index)
  636. {
  637. pushBack(index, _firstUsed, _lastUsed, entry_status::used);
  638. }
  639. template<class T>
  640. inline utl::__impl::index_type
  641. utl::__impl::system<T>::popFrontFree()
  642. {
  643. return popFront(true, _firstFree, _lastFree, entry_status::free);
  644. }
  645. template<class T>
  646. inline utl::__impl::index_type
  647. utl::__impl::system<T>::popFrontUsed()
  648. {
  649. return popFront(false, _firstUsed, _lastUsed, entry_status::used);
  650. }
  651. template<class T>
  652. inline utl::__impl::index_type
  653. utl::__impl::system<T>::popBackFree()
  654. {
  655. return popBack(true, _firstFree, _lastFree, entry_status::free);
  656. }
  657. template<class T>
  658. inline utl::__impl::index_type
  659. utl::__impl::system<T>::popBackUsed()
  660. {
  661. return popBack(false, _firstUsed, _lastUsed, entry_status::used);
  662. }
  663. template<class T>
  664. inline void
  665. utl::__impl::system<T>::removeFree(
  666. index_type index)
  667. {
  668. remove(index, _firstFree, _lastFree, entry_status::free);
  669. }
  670. template<class T>
  671. inline void
  672. utl::__impl::system<T>::removeUsed(
  673. index_type index)
  674. {
  675. remove(index, _firstUsed, _lastUsed, entry_status::used);
  676. }
  677. template<class T>
  678. inline size_t
  679. utl::__impl::system<T>::size() const
  680. {
  681. return _entries.size();
  682. }
  683. template<class T>
  684. inline typename utl::__impl::system<T>::entry_type&
  685. utl::__impl::system<T>::operator[](
  686. const index_type& index)
  687. {
  688. if (index >= _entries.size())
  689. grow(index + grow_size);
  690. return _entries[index];
  691. }
  692. template<class T>
  693. inline const typename utl::__impl::system<T>::entry_type&
  694. utl::__impl::system<T>::operator[](
  695. const index_type& index) const
  696. {
  697. return _entries.at(index);
  698. }
  699. template<class T>
  700. inline utl::__impl::system<T>::system() :
  701. _firstFree (invalid_index),
  702. _lastFree (invalid_index),
  703. _firstUsed (invalid_index),
  704. _lastUsed (invalid_index)
  705. { }
  706. template<class T>
  707. inline utl::__impl::system<T>::system(system&& other) :
  708. _firstFree (std::move(other)._firstFree),
  709. _lastFree (std::move(other)._lastFree),
  710. _firstUsed (std::move(other)._firstUsed),
  711. _lastUsed (std::move(other)._lastUsed),
  712. _entries (std::move(other)._entries)
  713. { }
  714. template<class T>
  715. inline utl::__impl::system<T>::system(const system&& other) :
  716. _firstFree (other._firstFree),
  717. _lastFree (other._lastFree),
  718. _firstUsed (other._firstUsed),
  719. _lastUsed (other._lastUsed),
  720. _entries (other._entries)
  721. { }
  722. /* SYSTEMS ***************************************************************************************/
  723. template<class T>
  724. inline typename utl::__impl::systems<T>::system_type&
  725. utl::__impl::systems<T>::operator[](
  726. const index_type& index)
  727. {
  728. if (index >= _systems.size())
  729. _systems.resize(index + 1);
  730. return _systems[index];
  731. }
  732. template<class T>
  733. inline const typename utl::__impl::systems<T>::system_type&
  734. utl::__impl::systems<T>::operator[](
  735. const index_type& index) const
  736. {
  737. return _systems[index];
  738. }
  739. template<class T>
  740. inline size_t
  741. utl::__impl::systems<T>::size() const
  742. {
  743. return _systems.size();
  744. }
  745. template<class T>
  746. inline void
  747. utl::__impl::systems<T>::clear()
  748. {
  749. _systems.clear();
  750. }
  751. /* handleMANAGER *********************************************************************************/
  752. template<class T>
  753. inline bool
  754. utl::handle_manager<T>::is_valid(
  755. const utl::handle& handle) const
  756. {
  757. using namespace __impl;
  758. auto hd = make_handle_data(handle);
  759. if (hd.system_id >= _systems.size())
  760. return false;
  761. auto& system = _systems[hd.system_id];
  762. if (hd.entry_index >= system.size())
  763. return false;
  764. auto& entry = system[hd.entry_index];
  765. return entry.status() == entry_status::used
  766. && entry.counter() == hd.counter;
  767. }
  768. template<class T>
  769. inline bool
  770. utl::handle_manager<T>::try_get(
  771. const utl::handle& handle,
  772. typename utl::handle_manager<T>::value_type& value)
  773. {
  774. using namespace __impl;
  775. auto ret = is_valid(handle);
  776. if (ret)
  777. {
  778. auto hd = make_handle_data(handle);
  779. value = _systems[hd.system_id][hd.entry_index].data();
  780. }
  781. return ret;
  782. }
  783. template<class T>
  784. inline typename utl::handle_manager<T>::value_type
  785. utl::handle_manager<T>::get(
  786. const utl::handle& handle)
  787. {
  788. value_type ret;
  789. if (!try_get(handle, ret))
  790. throw exception("invalid handle");
  791. return ret;
  792. }
  793. template<class T>
  794. inline bool
  795. utl::handle_manager<T>::update(
  796. const utl::handle& handle,
  797. typename utl::handle_manager<T>::value_type value)
  798. {
  799. using namespace __impl;
  800. if (is_valid(handle))
  801. {
  802. auto hd = make_handle_data(handle);
  803. _systems[hd.system_id][hd.entry_index].data(value);
  804. return true;
  805. }
  806. return false;
  807. }
  808. template<class T>
  809. inline bool
  810. utl::handle_manager<T>::set(
  811. const utl::handle& handle,
  812. typename utl::handle_manager<T>::value_type value)
  813. {
  814. using namespace __impl;
  815. if (!is_valid(handle))
  816. {
  817. auto hd = make_handle_data(handle);
  818. auto& system = _systems[hd.system_id];
  819. auto& entry = system[hd.entry_index];
  820. bool ret = entry.status() == entry_status::free;
  821. if (ret)
  822. {
  823. system.removeFree (hd.entry_index);
  824. system.pushBackUsed(hd.entry_index);
  825. entry.assign(value, hd.type_id, hd.counter);
  826. }
  827. return ret;
  828. }
  829. else
  830. {
  831. return update(handle, value);
  832. }
  833. }
  834. template<class T>
  835. inline utl::handle
  836. utl::handle_manager<T>::insert(
  837. const type_id_type& tId,
  838. const system_id_type& sId,
  839. typename utl::handle_manager<T>::value_type value)
  840. {
  841. using namespace __impl;
  842. auto& system = _systems[sId];
  843. auto index = system.popFrontFree();
  844. system.pushBackUsed(index);
  845. auto& entry = system[index];
  846. entry.assign(value, tId);
  847. handle_data hd;
  848. hd.entry_index = static_cast<uint32_t>(index);
  849. hd.counter = entry.counter();
  850. hd.type_id = tId,
  851. hd.system_id = sId;
  852. return make_handle(hd);
  853. }
  854. template<class T>
  855. inline bool
  856. utl::handle_manager<T>::remove(
  857. const utl::handle& handle)
  858. {
  859. using namespace __impl;
  860. if (!is_valid(handle))
  861. return false;
  862. auto hd = make_handle_data(handle);
  863. auto& system = _systems[hd.system_id];
  864. system.removeUsed(hd.entry_index);
  865. system.pushFrontFree(hd.entry_index);
  866. return true;
  867. }
  868. template<class T>
  869. inline typename utl::handle_manager<T>::value_type&
  870. utl::handle_manager<T>::operator[](
  871. const utl::handle& handle)
  872. {
  873. using namespace __impl;
  874. if (!is_valid(handle))
  875. throw exception("invalid handle");
  876. auto hd = make_handle_data(handle);
  877. auto& system = _systems[hd.system_id];
  878. auto& entry = system[hd.entry_index];
  879. return entry.data;
  880. }
  881. template<class T>
  882. inline void
  883. utl::handle_manager<T>::clear()
  884. { _systems.clear(); }