NonCachedCCWBase.h 1.8 KB

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