NonCachedCCWBase.h 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #pragma once
  2. #include "gc/GCHandle.h"
  3. #include "vm/CCWBase.h"
  4. #include "vm/Exception.h"
  5. #include "utils/TemplateUtils.h"
  6. #include "utils/Memory.h"
  7. #include "Baselib.h"
  8. #include "Cpp/Atomic.h"
  9. namespace il2cpp
  10. {
  11. namespace vm
  12. {
  13. template<typename TDerived>
  14. struct NOVTABLE NonCachedCCWBase : CCWBase
  15. {
  16. private:
  17. baselib::atomic<uint32_t> m_RefCount;
  18. uint32_t m_GCHandle;
  19. public:
  20. inline NonCachedCCWBase(Il2CppObject* obj) :
  21. CCWBase(obj),
  22. m_RefCount(1) // We start with a ref count of 1
  23. {
  24. m_GCHandle = gc::GCHandle::New(GetManagedObjectInline(), false);
  25. IL2CPP_ASSERT(m_GCHandle != 0);
  26. Il2CppStaticAssert(utils::TemplateUtils::IsBaseOf<NonCachedCCWBase<TDerived>, TDerived>::value);
  27. }
  28. inline ~NonCachedCCWBase()
  29. {
  30. IL2CPP_ASSERT(m_GCHandle != 0);
  31. gc::GCHandle::Free(m_GCHandle);
  32. m_GCHandle = 0;
  33. }
  34. IL2CPP_FORCE_INLINE uint32_t AddRefImpl()
  35. {
  36. return ++m_RefCount;
  37. }
  38. IL2CPP_FORCE_INLINE uint32_t ReleaseImpl()
  39. {
  40. const uint32_t count = --m_RefCount;
  41. if (count == 0)
  42. Destroy();
  43. return count;
  44. }
  45. IL2CPP_FORCE_INLINE static TDerived* __CreateInstance(Il2CppObject* obj)
  46. {
  47. void* memory = utils::Memory::Malloc(sizeof(TDerived));
  48. if (memory == NULL)
  49. Exception::RaiseOutOfMemoryException();
  50. return new(memory) TDerived(obj);
  51. }
  52. virtual void STDCALL Destroy() IL2CPP_FINAL IL2CPP_OVERRIDE
  53. {
  54. IL2CPP_ASSERT(m_RefCount == 0);
  55. TDerived* instance = static_cast<TDerived*>(this);
  56. instance->~TDerived();
  57. utils::Memory::Free(instance);
  58. }
  59. };
  60. }
  61. }