AppendOnlyGCHashMap.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #pragma once
  2. #include "utils/Il2CppHashMap.h"
  3. #include "utils/NonCopyable.h"
  4. #include "GarbageCollector.h"
  5. namespace il2cpp
  6. {
  7. namespace gc
  8. {
  9. template<class Key, class T,
  10. class HashFcn,
  11. class EqualKey = std::equal_to<Key> >
  12. class AppendOnlyGCHashMap : public il2cpp::utils::NonCopyable
  13. {
  14. typedef Il2CppHashMap<Key, size_t, HashFcn, EqualKey> hash_map_type;
  15. typedef typename Il2CppHashMap<Key, size_t, HashFcn, EqualKey>::const_iterator ConstIterator;
  16. public:
  17. typedef typename hash_map_type::key_type key_type;
  18. typedef T data_type;
  19. typedef typename hash_map_type::size_type size_type;
  20. typedef typename hash_map_type::hasher hasher;
  21. typedef typename hash_map_type::key_equal key_equal;
  22. AppendOnlyGCHashMap() :
  23. m_Data(NULL),
  24. m_Size(0)
  25. {
  26. }
  27. ~AppendOnlyGCHashMap()
  28. {
  29. if (m_Data)
  30. il2cpp::gc::GarbageCollector::FreeFixed(m_Data);
  31. }
  32. bool Contains(const Key& k)
  33. {
  34. return m_Map.find(k) != m_Map.end();
  35. }
  36. // Returns true if value was added. False if it already existed
  37. bool Add(const Key& k, T value)
  38. {
  39. if (m_Map.find(k) != m_Map.end())
  40. return false;
  41. if (m_Size == 0)
  42. {
  43. m_Size = 8;
  44. m_Data = (T*)il2cpp::gc::GarbageCollector::AllocateFixed(m_Size * sizeof(T), NULL);
  45. assert(m_Data);
  46. }
  47. else if (m_Map.size() == m_Size)
  48. {
  49. size_t newSize = 2 * m_Size;
  50. T* newData = (T*)il2cpp::gc::GarbageCollector::AllocateFixed(newSize * sizeof(T), NULL);
  51. MemCpyData memCpyData = { newData, m_Data, m_Size * sizeof(T) };
  52. // perform memcpy with GC lock held so GC doesn't see torn pointer values.I think this is less of an issue with Boehm than other GCs, but being safe.
  53. il2cpp::gc::GarbageCollector::CallWithAllocLockHeld(&CopyValues, &memCpyData);
  54. il2cpp::gc::GarbageCollector::FreeFixed(m_Data);
  55. m_Size = newSize;
  56. m_Data = newData;
  57. assert(m_Data);
  58. }
  59. size_t index = m_Map.size();
  60. m_Map.insert(std::make_pair(k, index));
  61. m_Data[index] = value;
  62. assert(m_Map.size() <= m_Size);
  63. return true;
  64. }
  65. bool TryGetValue(const Key& k, T* value)
  66. {
  67. ConstIterator iter = m_Map.find(k);
  68. if (iter == m_Map.end())
  69. return false;
  70. size_t index = iter->second;
  71. assert(index <= m_Map.size());
  72. *value = m_Data[index];
  73. return true;
  74. }
  75. private:
  76. struct MemCpyData
  77. {
  78. void* dst;
  79. const void* src;
  80. size_t size;
  81. };
  82. static void* CopyValues(void* arg)
  83. {
  84. MemCpyData* thisPtr = (MemCpyData*)arg;
  85. memcpy(thisPtr->dst, thisPtr->src, thisPtr->size);
  86. return NULL;
  87. }
  88. Il2CppHashMap<Key, size_t, HashFcn, EqualKey> m_Map;
  89. T* m_Data;
  90. size_t m_Size;
  91. };
  92. }
  93. }