ROOT  6.06/09
Reference Guide
TCoopPtr.h
Go to the documentation of this file.
1 /// \file TCoopPtr
2 /// \ingroup Base ROOT7
3 /// \author Axel Naumann <axel@cern.ch>
4 /// \date 2015-07-31
5 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
6 
7 /*************************************************************************
8  * Copyright (C) 1995-2015, Rene Brun and Fons Rademakers. *
9  * All rights reserved. *
10  * *
11  * For the licensing terms see $ROOTSYS/LICENSE. *
12  * For the list of contributors see $ROOTSYS/README/CREDITS. *
13  *************************************************************************/
14 
15 #ifndef ROOT7_TCoopPtr
16 #define ROOT7_TCoopPtr
17 
18 #include <memory>
19 #include <type_traits>
20 
21 namespace ROOT {
22 
23 /**
24  \class TCoopPtr
25  \brief Several pointers point to the same object, any of them can delete
26  the object, setting all of them to `nullptr`. Once all TCoopPtr-s have been
27  destructed, the pointed-to object is also destructed.
28 
29  Internally, this is modelled as a `shared_ptr<unique_ptr<T>>`: all
30  shared_ptr-s point to the same pointer (unique_ptr, actually), and a change to
31  that pointer value is visible to all of them.
32 
33  This is a PAW-style ownership management, useful if deletion needs to be an
34  explicit action (unlike `shared_ptr`), but shared resource handling is
35  required (like `unique_ptr`).
36 
37  Example:
38  TCoopPtr<TH1D> pHist(new TH1D({{10, 0., 1.}}));
39  TCoopPtr<TCanvas> pad = gROOT.Create<TCanvas>();
40  pad->Draw(pHist); // histogram is drawn; the pad co-owns the histogram
41  pHist.Delete(); // histogram vanishes from pad.
42  // Or the histogram could have been deleted on the pad, interactively.
43 **/
44 
45 template <class POINTEE>
46 class TCoopPtr {
47 public:
48  /// The type pointed to
49  using Pointee_t = std::remove_reference_t<POINTEE>;
50  /// The primitive pointer type
51  using Pointer_t = std::add_pointer_t<Pointee_t>;
52  /// The underlying std::shared_ptr
53  using SharedPtr_t = std::shared_ptr<void*>;
54 
55  TCoopPtr() = default;
56  /// Creates a synchronized TCoopPtr: once any of them call Delete(), all others
57  /// will "contain" a `nullptr`. The last synchronized TCoopPtr to be destructed
58  /// will delete the object they pointed to.
59  TCoopPtr(const TCoopPtr& other) = default;
60  TCoopPtr(TCoopPtr&& other) = default;
61 
62  /// Initialize from a raw pointer.
64  fPtrBuf(std::make_shared<void*>(ptr)) {}
65 
66  /// Create a TCoopPtr from an object. Tries to invoke POINTEE's move
67  /// constructor. Is only available if POINTEE is move constructable.
68  template <class SELF = TCoopPtr,
69  typename std::enable_if<
71  >::type* = nullptr>
72  TCoopPtr(POINTEE&& obj):
73  fPtrBuf(std::make_shared<void*>(new POINTEE(std::move(obj))))
74  {}
75 
76  /// Initialize from a unique_ptr; takes ownership.
77  ///
78  /// Call as `TCoopPtr p(std::move(uniquePtr));`
79  TCoopPtr(std::unique_ptr<POINTEE>&& ptr):
80  TCoopPtr(ptr.release()) {}
81 
82  /// Conversion from a pointer to derived to a pointer to base.
83  template <class DERIVED,
84  typename std::enable_if<std::is_base_of<POINTEE, DERIVED>{}>::type* = nullptr>
85  TCoopPtr(const TCoopPtr<DERIVED>& derived) {
86  fPtrBuf = std::static_pointer_cast<void*>(derived.GetShared());
87  }
88 
89  /// Get the raw pointer.
90  Pointer_t Get() const {
91  return fPtrBuf.get() ? static_cast<Pointer_t>(*fPtrBuf.get())
92  : nullptr;
93  }
94  const SharedPtr_t& GetShared() const { return fPtrBuf; }
95 
96  /// Delete the object pointed to. Safe to be called mutiple times.
97  /// All other synchronized TCoopPtr will be notified.
98  POINTEE* Delete() const {
99  delete fPtrBuf.get();
100  fPtrBuf.get() = nullptr;
101  }
102 
103  /// Access the object pointed to.
104  Pointer_t operator->() const { return Get(); }
105  /// Dereference the object pointed to.
106  POINTEE& operator*() const { return *Get(); }
107  /// Returns `true` if the pointer is non-null.
108  operator bool() const { return fPtrBuf.get(); }
109 
110 private:
112 };
113 
114 
115 /// Create an object of type `POINTEE` on the heap, and build a `TCoopPtr` for
116 /// it.
117 ///
118 /// \param args Arguments forwarded to the constructor of `POINTEE`.
119 template <class POINTEE, class... ARGS>
121  return TCoopPtr<POINTEE>(new POINTEE(std::forward<ARGS>(args)...));
122 };
123 
124 
125 /// Move an object into a TCoopPtr. Rather efficient if there is a move
126 /// constructor for `POINTEE`.
127 ///
128 /// \param obj - object to be moved into the TCoopPtr.
129 template <class POINTEE>
131  return TCoopPtr<POINTEE>(std::move(obj));
132 };
133 
134 
135 namespace Internal {
136 /**
137  \class TCoopPtrTypeErasedBase
138  To handle polymorphic `TCoopPtr<POINTEE>`s, convert them to
139  `TCoopPtrTypeErased<POINTEE>`s and access them through their common base
140  `TCoopPtrTypeErasedBase`. Example:
141 
142  auto pH1D = MakeCoOwnedHist<1, double>({{{10, 0., 1.}}});
143  auto pH2I = MakeCoOwnedHist<2, int>({{{2, 0., 1.}, {2., 0., 1.}}});
144  std::vector<Internal::TCoopPtrTypeErased<TDrawable>>
145  coOwnedDrawables {pH1D, pH2I};
146 
147  The contained objects will be destructed once all TCoopPtrTypeErased and all
148  other synchronized `TCoopPtr` are destructed.
149  */
152 };
153 
154 
155 /**
156  \class TCoopPtrTypeErased
157  Type-specific derived implementation of a `TCoopPtrTypeErasedBase`, to invoke
158  the destructor of the `TCoopPtr<POINTEE>` upon destruction of the
159  `TCoopPtrTypeErased`. "Translates" from the abstract interface
160  (`TCoopPtrTypeErasedBase`) to the specific implementation `TCoopPtr<POINTEE>`.
161  */
162 template<class POINTEE>
163 class TCoopPtrTypeErased: public TCoopPtr<POINTEE>, public TCoopPtrTypeErasedBase {
164 public:
165  TCoopPtrTypeErased(const TCoopPtr<POINTEE>& ptr): TCoopPtr<POINTEE>(ptr) {}
166  ~TCoopPtrTypeErased() final = default;
167 };
168 } // namespace Internal
169 }
170 
171 #endif
TCoopPtrTypeErased(const TCoopPtr< POINTEE > &ptr)
Definition: TCoopPtr.h:165
POINTEE * Delete() const
Delete the object pointed to.
Definition: TCoopPtr.h:98
#define ARGS(alist)
Definition: gifencode.c:10
Namespace for new ROOT classes and functions.
Definition: ROOT.py:1
TCoopPtr(POINTEE &&obj)
Create a TCoopPtr from an object.
Definition: TCoopPtr.h:72
TCoopPtr< POINTEE > MakeCoop(ARGS &&...args)
Create an object of type POINTEE on the heap, and build a TCoopPtr for it.
Definition: TCoopPtr.h:120
STL namespace.
TCoopPtr(const TCoopPtr< DERIVED > &derived)
Conversion from a pointer to derived to a pointer to base.
Definition: TCoopPtr.h:85
TCoopPtr()=default
Pointer_t operator->() const
Access the object pointed to.
Definition: TCoopPtr.h:104
std::shared_ptr< void * > SharedPtr_t
The underlying std::shared_ptr.
Definition: TCoopPtr.h:53
const SharedPtr_t & GetShared() const
Definition: TCoopPtr.h:94
SharedPtr_t fPtrBuf
Definition: TCoopPtr.h:111
std::add_pointer_t< Pointee_t > Pointer_t
The primitive pointer type.
Definition: TCoopPtr.h:51
Type-specific derived implementation of a TCoopPtrTypeErasedBase, to invoke the destructor of the TCo...
Definition: TCoopPtr.h:163
TCoopPtr(Pointer_t ptr)
Initialize from a raw pointer.
Definition: TCoopPtr.h:63
int type
Definition: TGX11.cxx:120
To handle polymorphic TCoopPtrs, convert them to TCoopPtrTypeEraseds and access the...
Definition: TCoopPtr.h:150
POINTEE & operator*() const
Dereference the object pointed to.
Definition: TCoopPtr.h:106
typedef void((*Func_t)())
TObject * obj
Pointer_t Get() const
Get the raw pointer.
Definition: TCoopPtr.h:90
float value
Definition: math.cpp:443
std::remove_reference_t< ROOT::THist< DIMENSION, PRECISION > > Pointee_t
The type pointed to.
Definition: TCoopPtr.h:49
TCoopPtr(std::unique_ptr< POINTEE > &&ptr)
Initialize from a unique_ptr; takes ownership.
Definition: TCoopPtr.h:79
Several pointers point to the same object, any of them can delete the object, setting all of them to ...
Definition: TCoopPtr.h:46