access_byid.cpp
上传用户:kx_jwh
上传日期:2021-09-03
资源大小:76k
文件大小:4k
源码类别:

STL

开发平台:

Visual C++

  1. /* vim: set tabstop=4 : */
  2. #include "access_byid.h"
  3. #include <algorithm>
  4. #include <sstream>
  5. #include <stdexcept>
  6. namespace febird {
  7. id_generator::id_generator(long maxID)
  8. : id_list(maxID+1)
  9. {
  10. chain(0);
  11. m_nUsed = 0;
  12. }
  13. id_generator::~id_generator()
  14. {
  15. }
  16. void id_generator::chain(long newHead)
  17. {
  18. for (long i = newHead; i != id_list.size()-1; ++i)
  19. id_list[i] = i + 1; // id_list[i] link to id_list[i+1]
  20. id_list.back() = 0; // set 0 as tail
  21. }
  22. long id_generator::alloc_id()
  23. {
  24. if (0 == id_list[0]) // out of space, enlarge id_list
  25. {
  26. long newHead = id_list[0] = id_list.size();
  27. id_list.resize(id_list.size()*2);
  28. chain(newHead);
  29. }
  30. ++m_nUsed;
  31. long retid = id_list[0];
  32. id_list[0] = id_list[retid];
  33. return retid;
  34. }
  35. void id_generator::free_id(long id)
  36. {
  37. assert(id >= 1);
  38. assert(id <= long(id_list.size()));
  39. if (long(id_list.size()) < id || id <= 0)
  40. {
  41. throw std::invalid_argument("void id_generator::free_id(long id)");
  42. }
  43. id_list[id] = id_list[0];
  44. id_list[0] = id;
  45. --m_nUsed;
  46. }
  47. long id_generator::add_val(uintptr_t val)
  48. {
  49. long id = alloc_id();
  50. id_list[id] = val;
  51. return id;
  52. }
  53. void id_generator::get_used_id(std::vector<uintptr_t>& used_id) const
  54. {
  55. used_id.resize(0);
  56. used_id.reserve(id_list.size());
  57. std::vector<long> free_subscript;
  58. free_subscript.reserve(id_list.size());
  59. free_subscript.push_back(0);
  60. for (uintptr_t h = id_list[0]; h != 0; h = id_list[h])
  61. free_subscript.push_back(h);
  62. std::sort(free_subscript.begin(), free_subscript.end());
  63. free_subscript.push_back(id_list.size());
  64. for (long i = 0; i != free_subscript.size()-1; ++i)
  65. {
  66. long d1 = free_subscript[i+0]+1;
  67. long d2 = free_subscript[i+1];
  68. for (long j = d1; j < d2; ++j)
  69. used_id.push_back(j);
  70. }
  71. }
  72. void* access_byid<void*>::get_ptr_imp(long id, const char* func) const
  73. {
  74. if (this->is_valid(id))
  75. {
  76. assert(this->get_val(id) > 1024);
  77. return (void*)(this->get_val(id));
  78. }
  79. std::ostringstream oss;
  80. oss << func << ": id too large";
  81. throw std::invalid_argument(oss.str());
  82. }
  83. void access_byid<void*>::on_destroy(void* vp)
  84. {
  85. ::free(vp);
  86. }
  87. void access_byid<void*>::destroy()
  88. {
  89. std::vector<uintptr_t> used_id;
  90. get_used_id(used_id);
  91. for (long i = 0; i != used_id.size(); ++i)
  92. {
  93. void* x = (void*)this->get_val(used_id[i]);
  94. on_destroy(x);
  95. }
  96. this->clear();
  97. }
  98. long AccessByNameID<void*>::add_ptr(void* x, const std::string& name, void** existed)
  99. {
  100. assert(0 != x);
  101. void*& y = m_byname[name];
  102. if (y)
  103. {
  104. *existed = y;
  105. return 0;
  106. }
  107. else
  108. {
  109. *existed = 0;
  110. y = x;
  111. long id = m_byid.add_ptr(x);
  112. return id;
  113. }
  114. }
  115. void* AccessByNameID<void*>::get_byname(const std::string& name) const
  116. {
  117. std::map<std::string, void*>::const_iterator iter = m_byname.find(name);
  118. if (m_byname.end() != iter)
  119. {
  120. return iter->second;
  121. }
  122. return 0;
  123. }
  124. void AccessByNameID<void*>::on_destroy(void* vp)
  125. {
  126. ::free(vp);
  127. }
  128. //! delete all object in list, and clear self
  129. void AccessByNameID<void*>::destroy()
  130. {
  131. std::vector<uintptr_t> used_id;
  132. m_byid.get_used_id(used_id);
  133. std::vector<uintptr_t> bynamep(m_byname.size());
  134. std::map<std::string, void*>::iterator iter = m_byname.begin();
  135. for (long i = 0; iter != m_byname.end(); ++iter)
  136. bynamep[i++] = (uintptr_t)iter->second;
  137. for (long i = 0; i != used_id.size(); ++i)
  138. used_id[i] = m_byid.get_val(used_id[i]);
  139. std::sort(used_id.begin(), used_id.end());
  140. std::sort(bynamep.begin(), bynamep.end());
  141. long n = std::set_union(used_id.begin(), used_id.end(), bynamep.begin(), bynamep.end(), used_id.begin()) - used_id.begin();
  142. assert(used_id.size() == n);
  143. for (long i = 0; i != used_id.size(); ++i)
  144. {
  145. on_destroy((void*)used_id[i]);
  146. }
  147. m_byid.clear();
  148. m_byname.clear();
  149. }
  150. void AccessByNameID<void*>::remove(long id, const std::string& name)
  151. {
  152. void* p = m_byid.get_ptr(id);
  153. m_byid.free_id(id);
  154. m_byname.erase(name);
  155. on_destroy(p);
  156. }
  157. void AccessByNameID<void*>::remove(long id)
  158. {
  159. void* p = m_byid.get_ptr(id);
  160. m_byid.free_id(id);
  161. on_destroy(p);
  162. }
  163. bool AccessByNameID<void*>::check_id(long id, const char* szClassName, std::string& err) const
  164. {
  165. if (0 == id)
  166. {
  167. assert(0);
  168. }
  169. if (!this->is_valid(id))
  170. {
  171. std::ostringstream oss;
  172. oss << "can not find " << szClassName << " object[id=" << id << "]"
  173. ;
  174. err = oss.str();
  175. return false;
  176. }
  177. return true;
  178. }
  179. } // namespace febird