// @(#)root/base:$Id$ // Author: Philippe Canal 2019 /************************************************************************* * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ #ifndef ROOT_TNotifyLink #define ROOT_TNotifyLink #include #include // for R__ASSERT /** \class TNotifyLink \ingroup Base Links multiple listeners to be notified on TChain file changes. Neither TChain::SetNotify() nor this TNotifyLink take ownership of the object to be notified. eg. ``` auto notify = new TNotifyLink(object, fChain->GetNotify()); fChain->SetNotify(notify); ``` **/ class TNotifyLinkBase : public TObject { protected: TNotifyLinkBase *fPrevious = nullptr; TObject *fNext = nullptr; public: // TTree status bits enum EStatusBits { kLinked = BIT(11) // Used when the TNotifyLink is connected to a TTree. }; void Clear(Option_t * /*option*/ ="") { auto current = this; do { auto next = dynamic_cast(fNext); current->ResetBit(kLinked); current->fPrevious = nullptr; current->fNext = nullptr; current = next; } while(current); } template void PrependLink(Notifier ¬ifier) { SetBit(kLinked); fNext = notifier.GetNotify(); if (auto link = dynamic_cast(fNext)) { link->fPrevious = this; } notifier.SetNotify(this); } template void RemoveLink(Notifier ¬ifier) { ResetBit(kLinked); if (notifier.GetNotify() == this) { R__ASSERT(fPrevious == nullptr && "The TNotifyLink head node should not have a previous element."); notifier.SetNotify(fNext); } else if (fPrevious) { fPrevious->fNext = fNext; } if (auto link = dynamic_cast(fNext)) { link->fPrevious = fPrevious; } fPrevious = nullptr; fNext = nullptr; } Bool_t IsLinked() { return TestBit(kLinked); } ClassDef(TNotifyLinkBase, 0); }; template class TNotifyLink : public TNotifyLinkBase { private: Type *fCurrent; public: TNotifyLink(Type *current) : fCurrent(current) {} // Call Notify on the current and next object. Bool_t Notify() override { auto result = fCurrent ? fCurrent->Notify() : kTRUE; if (fNext) result &= fNext->Notify(); return result; } ClassDefOverride(TNotifyLink, 0); }; #endif // ROOT_TNotifyLink