|
||||
Warning, file /include/root/TNotifyLink.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 // @(#)root/base:$Id$ 0002 // Author: Philippe Canal 2019 0003 0004 /************************************************************************* 0005 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. * 0006 * All rights reserved. * 0007 * * 0008 * For the licensing terms see $ROOTSYS/LICENSE. * 0009 * For the list of contributors see $ROOTSYS/README/CREDITS. * 0010 *************************************************************************/ 0011 0012 #ifndef ROOT_TNotifyLink 0013 #define ROOT_TNotifyLink 0014 0015 #include <TObject.h> 0016 #include <TError.h> // for R__ASSERT 0017 0018 /** \class TNotifyLink 0019 \ingroup Base 0020 0021 A node in a doubly linked list of subscribers to TChain notifications. 0022 0023 TObject has a virtual TObject::Notify() method that takes no parameters and returns a boolean. 0024 By default the method does nothing, and different objects in ROOT use this method for different purposes. 0025 0026 `TChain` uses `Notify` to implement a callback mechanism that notifies interested parties (subscribers) when 0027 the chain switches to a new sub-tree. 0028 In practice it calls the Notify() method of its fNotify data member from TChain::LoadTree(). 0029 However there could be several different objects interested in knowing that a given TChain switched to a new tree. 0030 TNotifyLink can be used to build a linked list of subscribers: calling TNotifyLink::Notify() on the head 0031 node of the list propagates the call to all subscribers in the list. 0032 0033 Example usage: 0034 ~~~{.cpp} 0035 TNotifyLink l(subscriber); // subscriber must implement `Notify()` 0036 l.PrependLink(chain); // prepends `l` to the list of notify links of the chain 0037 ~~~ 0038 0039 \note TChain does not explicitly enforce that its fNotify data member be the head node of a list of 0040 TNotifyLinks, but that is the case in practice at least when using TTreeReader or RDataFrame to process the chain. 0041 0042 \note TChain does not take ownership of the TNotifyLink and the TNotifyLink does not take ownership of the 0043 subscriber object. 0044 **/ 0045 0046 /// See TNotifyLink. 0047 class TNotifyLinkBase : public TObject { 0048 protected: 0049 /// Previous node in a TChain's list of subscribers to its notification. 0050 /// If null, this TNotifyLink is the head node of the list and the TChain::GetNotify() for the corresponding 0051 /// chain is expected to return `this`. 0052 TNotifyLinkBase *fPrevious = nullptr; 0053 /// Next node in a TChain's list of subscribers. 0054 /// For generality, it might be a generic TObject rather than another TNotifyLink: this makes it possible 0055 /// to call TChain::SetNotify() with a generic notifier exactly once before more TNotifyLinks are added. 0056 /// Null if this is the tail of the list. 0057 TObject *fNext = nullptr; 0058 0059 public: 0060 // TTree status bits 0061 enum EStatusBits { 0062 kLinked = BIT(11) // Used when the TNotifyLink is connected to a TTree. 0063 }; 0064 0065 void Clear(Option_t * /*option*/ ="") override 0066 { 0067 auto current = this; 0068 do { 0069 auto next = dynamic_cast<TNotifyLinkBase*>(fNext); 0070 current->ResetBit(kLinked); 0071 current->fPrevious = nullptr; 0072 current->fNext = nullptr; 0073 current = next; 0074 } while(current); 0075 } 0076 0077 /// Set this link as the head of the chain's list of notify subscribers. 0078 /// Templated only to remove an include dependency from TChain: it expects 0079 /// a TChain as input (in practice anything that implements SetNotify and 0080 /// GetNotify will work, but in ROOT that is only TTree and its sub-classes). 0081 template <class Chain> 0082 void PrependLink(Chain &chain) 0083 { 0084 SetBit(kLinked); 0085 0086 fNext = chain.GetNotify(); 0087 chain.SetNotify(this); 0088 if (auto next = dynamic_cast<TNotifyLinkBase *>(fNext)) 0089 next->fPrevious = this; 0090 } 0091 0092 /// Remove this link from a chain's list of notify subscribers. 0093 /// Templated only to remove an include dependency from TChain: it expects 0094 /// a TChain as input (in practice anything that implements SetNotify and 0095 /// GetNotify will work, but in ROOT that is only TTree and its sub-classes). 0096 /// \note No error is emitted if the TNotifyLink is not part of the linked list 0097 /// for the chain passed as argument. The TNotifyLink will still remove itself 0098 /// from the doubly linked list. 0099 template <class Chain> 0100 void RemoveLink(Chain &chain) 0101 { 0102 ResetBit(kLinked); 0103 0104 if (chain.GetNotify() == this) { // this notify link is the first in the list 0105 R__ASSERT(fPrevious == nullptr && "The TNotifyLink head node should not have a previous element."); 0106 chain.SetNotify(fNext); 0107 } else if (fPrevious) { 0108 fPrevious->fNext = fNext; 0109 } 0110 if (auto next = dynamic_cast<TNotifyLinkBase *>(fNext)) 0111 next->fPrevious = fPrevious; 0112 fPrevious = nullptr; 0113 fNext = nullptr; 0114 } 0115 0116 Bool_t IsLinked() 0117 { 0118 return TestBit(kLinked); 0119 } 0120 0121 TObject *GetNext() const { return fNext; } 0122 0123 ClassDefOverride(TNotifyLinkBase, 0); 0124 }; 0125 0126 template <class Type> 0127 class TNotifyLink : public TNotifyLinkBase { 0128 private: 0129 Type *fSubscriber; 0130 0131 public: 0132 TNotifyLink(Type *subscriber) : fSubscriber(subscriber) {} 0133 0134 /// Call Notify on our subscriber and propagate the call to the next link. 0135 Bool_t Notify() override 0136 { 0137 bool result = true; 0138 if (fSubscriber) 0139 result &= fSubscriber->Notify(); 0140 if (fNext) 0141 result &= fNext->Notify(); 0142 return result; 0143 } 0144 0145 ClassDefOverride(TNotifyLink, 0); 0146 }; 0147 0148 #endif // ROOT_TNotifyLink
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |