No Description
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.

AppendOnlyGCHashMap.h 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #pragma once
  2. #include "utils/Il2CppHashMap.h"
  3. #include "utils/NonCopyable.h"
  4. #include "GarbageCollector.h"
  5. #include "os/FastReaderReaderWriterLock.h"
  6. namespace il2cpp
  7. {
  8. namespace gc
  9. {
  10. template<class Key, class T,
  11. class HashFcn,
  12. class EqualKey = std::equal_to<Key> >
  13. class AppendOnlyGCHashMap : public il2cpp::utils::NonCopyable
  14. {
  15. typedef Il2CppHashMap<Key, size_t, HashFcn, EqualKey> hash_map_type;
  16. typedef typename Il2CppHashMap<Key, size_t, HashFcn, EqualKey>::const_iterator ConstIterator;
  17. public:
  18. typedef typename hash_map_type::key_type key_type;
  19. typedef T data_type;
  20. typedef typename hash_map_type::size_type size_type;
  21. typedef typename hash_map_type::hasher hasher;
  22. typedef typename hash_map_type::key_equal key_equal;
  23. AppendOnlyGCHashMap() :
  24. m_Data(NULL),
  25. m_Size(0)
  26. {
  27. }
  28. ~AppendOnlyGCHashMap()
  29. {
  30. if (m_Data)
  31. il2cpp::gc::GarbageCollector::FreeFixed(m_Data);
  32. }
  33. bool Contains(const Key& k)
  34. {
  35. os::FastReaderReaderWriterAutoSharedLock readLock(&lock);
  36. return m_Map.find(k) != m_Map.end();
  37. }
  38. // Returns the existing value if the it was already added or inserts and returns value
  39. T GetOrAdd(const Key& k, T value)
  40. {
  41. os::FastReaderReaderWriterAutoExclusiveLock writeLock(&lock);
  42. ConstIterator iter = m_Map.find(k);
  43. if (iter != m_Map.end())
  44. {
  45. size_t index = iter->second;
  46. IL2CPP_ASSERT(index <= m_Map.size());
  47. return m_Data[index];
  48. }
  49. if (m_Size == 0)
  50. {
  51. m_Size = 8;
  52. m_Data = (T*)il2cpp::gc::GarbageCollector::AllocateFixed(m_Size * sizeof(T), NULL);
  53. IL2CPP_ASSERT(m_Data);
  54. }
  55. else if (m_Map.size() == m_Size)
  56. {
  57. size_t newSize = 2 * m_Size;
  58. T* newData = (T*)il2cpp::gc::GarbageCollector::AllocateFixed(newSize * sizeof(T), NULL);
  59. MemCpyData memCpyData = { newData, m_Data, m_Size * sizeof(T) };
  60. // 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.
  61. il2cpp::gc::GarbageCollector::CallWithAllocLockHeld(&CopyValues, &memCpyData);
  62. il2cpp::gc::GarbageCollector::FreeFixed(m_Data);
  63. GarbageCollector::SetWriteBarrier((void**)newData, m_Size * sizeof(T));
  64. m_Size = newSize;
  65. m_Data = newData;
  66. IL2CPP_ASSERT(m_Data);
  67. }
  68. size_t index = m_Map.size();
  69. m_Map.insert(std::make_pair(k, index));
  70. m_Data[index] = value;
  71. GarbageCollector::SetWriteBarrier((void**)(m_Data + index));
  72. IL2CPP_ASSERT(m_Map.size() <= m_Size);
  73. return value;
  74. }
  75. bool TryGetValue(const Key& k, T* value)
  76. {
  77. os::FastReaderReaderWriterAutoSharedLock readLock(&lock);
  78. ConstIterator iter = m_Map.find(k);
  79. if (iter == m_Map.end())
  80. return false;
  81. size_t index = iter->second;
  82. IL2CPP_ASSERT(index <= m_Map.size());
  83. *value = m_Data[index];
  84. return true;
  85. }
  86. private:
  87. struct MemCpyData
  88. {
  89. void* dst;
  90. const void* src;
  91. size_t size;
  92. };
  93. static void* CopyValues(void* arg)
  94. {
  95. MemCpyData* thisPtr = (MemCpyData*)arg;
  96. memcpy(thisPtr->dst, thisPtr->src, thisPtr->size);
  97. return NULL;
  98. }
  99. Il2CppHashMap<Key, size_t, HashFcn, EqualKey> m_Map;
  100. T* m_Data;
  101. size_t m_Size;
  102. os::FastReaderReaderWriterLock lock;
  103. };
  104. }
  105. }