Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TNotifyLink.h
Go to the documentation of this file.
1 // @(#)root/base:$Id$
2 // Author: Philippe Canal 2019
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #ifndef ROOT_TNotifyLink
13 #define ROOT_TNotifyLink
14 
15 #include <TObject.h>
16 #include <TError.h> // for R__ASSERT
17 
18 /** \class TNotifyLink
19 \ingroup Base
20 
21 Links multiple listeners to be notified on TChain file changes.
22 
23 Neither TChain::SetNotify() nor this TNotifyLink take ownership of the object to be notified.
24 
25 eg.
26 ```
27 auto notify = new TNotifyLink(object, fChain->GetNotify());
28 fChain->SetNotify(notify);
29 ```
30 **/
31 
32 class TNotifyLinkBase : public TObject {
33 protected:
34  TNotifyLinkBase *fPrevious = nullptr;
35  TObject *fNext = nullptr;
36 
37 public:
38  // TTree status bits
39  enum EStatusBits {
40  kLinked = BIT(11) // Used when the TNotifyLink is connected to a TTree.
41  };
42 
43  void Clear(Option_t * /*option*/ ="") {
44  auto current = this;
45  do {
46  auto next = dynamic_cast<TNotifyLinkBase*>(fNext);
47  current->ResetBit(kLinked);
48  current->fPrevious = nullptr;
49  current->fNext = nullptr;
50  current = next;
51  } while(current);
52  }
53 
54  template <class Notifier>
55  void PrependLink(Notifier &notifier) {
56  SetBit(kLinked);
57 
58  fNext = notifier.GetNotify();
59  if (auto link = dynamic_cast<TNotifyLinkBase*>(fNext)) {
60  link->fPrevious = this;
61  }
62  notifier.SetNotify(this);
63  }
64 
65  template <class Notifier>
66  void RemoveLink(Notifier &notifier) {
67  ResetBit(kLinked);
68 
69  if (notifier.GetNotify() == this) {
70  R__ASSERT(fPrevious == nullptr && "The TNotifyLink head node should not have a previous element.");
71  notifier.SetNotify(fNext);
72  } else if (fPrevious) {
73  fPrevious->fNext = fNext;
74  }
75  if (auto link = dynamic_cast<TNotifyLinkBase*>(fNext)) {
76  link->fPrevious = fPrevious;
77  }
78  fPrevious = nullptr;
79  fNext = nullptr;
80  }
81 
82  Bool_t IsLinked() {
83  return TestBit(kLinked);
84  }
85 
86  ClassDef(TNotifyLinkBase, 0);
87 };
88 
89 template <class Type>
90 class TNotifyLink : public TNotifyLinkBase {
91 private:
92  Type *fCurrent;
93 
94 public:
95  TNotifyLink(Type *current) : fCurrent(current) {}
96 
97  // Call Notify on the current and next object.
98  Bool_t Notify() override
99  {
100  auto result = fCurrent ? fCurrent->Notify() : kTRUE;
101  if (fNext) result &= fNext->Notify();
102  return result;
103  }
104 
105  ClassDefOverride(TNotifyLink, 0);
106 };
107 
108 #endif // ROOT_TNotifyLink