LockingPtr.hpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. * ZeroTier One - Network Virtualization Everywhere
  3. * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #ifndef ZT_LOCKINGPTR_HPP
  19. #define ZT_LOCKINGPTR_HPP
  20. #include "Mutex.hpp"
  21. namespace ZeroTier {
  22. /**
  23. * A simple pointer that locks and holds a mutex until destroyed
  24. *
  25. * Care must be taken when using this. It's not very sophisticated and does
  26. * not handle being copied except for the simple return use case. When it is
  27. * copied it hands off the mutex to the copy and clears it in the original,
  28. * meaning that the mutex is unlocked when the last LockingPtr<> in a chain
  29. * of such handoffs is destroyed. If this chain of handoffs "forks" (more than
  30. * one copy is made) then non-determinism may ensue.
  31. *
  32. * This does not delete or do anything else with the pointer. It also does not
  33. * take care of locking the lock. That must be done beforehand.
  34. */
  35. template<typename T>
  36. class LockingPtr
  37. {
  38. public:
  39. LockingPtr() :
  40. _ptr((T *)0),
  41. _lock((Mutex *)0)
  42. {
  43. }
  44. LockingPtr(T *obj,Mutex *lock) :
  45. _ptr(obj),
  46. _lock(lock)
  47. {
  48. }
  49. LockingPtr(const LockingPtr &p) :
  50. _ptr(p._ptr),
  51. _lock(p._lock)
  52. {
  53. const_cast<LockingPtr *>(&p)->_lock = (Mutex *)0;
  54. }
  55. ~LockingPtr()
  56. {
  57. if (_lock)
  58. _lock->unlock();
  59. }
  60. inline LockingPtr &operator=(const LockingPtr &p)
  61. {
  62. _ptr = p._ptr;
  63. _lock = p._lock;
  64. const_cast<LockingPtr *>(&p)->_lock = (Mutex *)0;
  65. return *this;
  66. }
  67. inline operator bool() const throw() { return (_ptr != (T *)0); }
  68. inline T &operator*() const throw() { return *_ptr; }
  69. inline T *operator->() const throw() { return _ptr; }
  70. /**
  71. * @return Raw pointer to held object
  72. */
  73. inline T *ptr() const throw() { return _ptr; }
  74. inline bool operator==(const LockingPtr &sp) const throw() { return (_ptr == sp._ptr); }
  75. inline bool operator!=(const LockingPtr &sp) const throw() { return (_ptr != sp._ptr); }
  76. inline bool operator>(const LockingPtr &sp) const throw() { return (_ptr > sp._ptr); }
  77. inline bool operator<(const LockingPtr &sp) const throw() { return (_ptr < sp._ptr); }
  78. inline bool operator>=(const LockingPtr &sp) const throw() { return (_ptr >= sp._ptr); }
  79. inline bool operator<=(const LockingPtr &sp) const throw() { return (_ptr <= sp._ptr); }
  80. private:
  81. T *_ptr;
  82. Mutex *_lock;
  83. };
  84. } // namespace ZeroTier
  85. #endif