CmLockedPtr.h 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. #pragma once
  2. #include "CmPrerequisitesUtil.h"
  3. #if CM_DEBUG_MODE
  4. #include "CmException.h"
  5. #endif
  6. namespace CamelotEngine
  7. {
  8. /**
  9. * @brief A pointer that once locked will not allow its value to be accessed.
  10. *
  11. * @note This is useful with multithreading where you need to pass along some value to a different
  12. * thread, but want to ensure that no other thread can modify the value (without actually creating a copy
  13. * of all the data).
  14. *
  15. * LockedPtr MUST be the exclusive owner of the data it is pointing to.
  16. */
  17. template <class T>
  18. class LockedPtr
  19. {
  20. public:
  21. explicit LockedPtr(T* data)
  22. :mLocked(false)
  23. {
  24. mData = new std::shared_ptr<T>(data);
  25. }
  26. T* operator->() const
  27. {
  28. throwIfLocked();
  29. return !mLocked ? mData.get() : nullptr;
  30. }
  31. void lock() { mLocked = true; }
  32. template<class _Ty>
  33. struct CM_Bool_struct
  34. {
  35. int _Member;
  36. };
  37. // Conversion to bool
  38. // (Why not just directly convert to bool? Because then we can assign pointer to bool and that's weird)
  39. operator int CM_Bool_struct<T>::*() const
  40. {
  41. return ((mData.get() != 0) ? &CM_Bool_struct<T>::_Member : 0);
  42. }
  43. private:
  44. std::shared_ptr<T> mData;
  45. bool mLocked;
  46. #if CM_DEBUG_MODE
  47. void throwIfLocked() const
  48. {
  49. if(mLocked)
  50. {
  51. CM_EXCEPT(InternalErrorException, "Attempting to access locked data!");
  52. }
  53. }
  54. };
  55. #endif
  56. }