7#ifndef PXR_BASE_TF_NOTICE_H
8#define PXR_BASE_TF_NOTICE_H
14#include "pxr/base/tf/api.h"
18#include "pxr/base/tf/scoped.h"
19#include "pxr/base/tf/type.h"
29PXR_NAMESPACE_OPEN_SCOPE
31class Tf_NoticeRegistry;
84 typedef std::list<_DelivererBase*> _DelivererList;
88 template <
class LPtr,
class L,
89 class Notice,
class SPtr,
class DeliveredSPtr>
90 static _DelivererBase *
91 _MakeDeliverer(LPtr
const &listener,
93 (
const Notice &, DeliveredSPtr
const &),
95 DeliveredSPtr weakSender(sender);
96 return new _DelivererWithSender<
98 void (L::*)(
const Notice &, DeliveredSPtr
const &),
100 >(listener, method, weakSender);
103 template <
class LPtr,
class L,
104 class Notice,
class SPtr,
class DeliveredSPtr>
105 static _DelivererBase *
106 _MakeDeliverer(LPtr
const &listener,
108 (
const Notice &, DeliveredSPtr
const &)
const,
109 SPtr
const &sender) {
110 DeliveredSPtr weakSender(sender);
111 return new _DelivererWithSender<
113 void (L::*)(
const Notice &, DeliveredSPtr
const &)
const,
115 >(listener, method, weakSender);
120 template <
class LPtr,
class L,
class SPtr,
class Notice>
121 static _DelivererBase *
122 _MakeDeliverer(LPtr
const &listener,
123 void (L::*method)(
const Notice &),
124 SPtr
const &sender) {
125 return new _Deliverer<
126 LPtr, SPtr, void (L::*)(
const Notice &), Notice
127 >(listener, method, sender);
130 template <
class LPtr,
class L,
class SPtr,
class Notice>
131 static _DelivererBase *
132 _MakeDeliverer(LPtr
const &listener,
133 void (L::*method)(
const Notice &)
const,
134 SPtr
const &sender) {
135 return new _Deliverer<
136 LPtr, SPtr, void (L::*)(
const Notice &)
const, Notice
137 >(listener, method, sender);
142 template <
class LPtr,
class L,
class Notice>
143 static _DelivererBase *
144 _MakeDeliverer(LPtr
const &listener,
145 void (L::*method)(
const Notice &)) {
146 return new _Deliverer<
151 template <
class LPtr,
class L,
class Notice>
152 static _DelivererBase *
153 _MakeDeliverer(LPtr
const &listener,
154 void (L::*method)(
const Notice &)
const) {
155 return new _Deliverer<
156 LPtr,
TfAnyWeakPtr, void (L::*)(
const Notice &)
const, Notice
162 template <
class LPtr,
class L>
163 static _DelivererBase *
164 _MakeDeliverer(
TfType const ¬iceType,
165 LPtr
const &listener,
169 const std::type_info&),
171 return new _RawDeliverer<LPtr,
174 const std::type_info &)>
175 (listener, method, sender, noticeType);
178 template <
class LPtr,
class L>
179 static _DelivererBase *
180 _MakeDeliverer(
TfType const ¬iceType,
181 LPtr
const &listener,
185 const std::type_info&)
const,
188 return new _RawDeliverer<LPtr,
191 const std::type_info &)
const>
192 (listener, method, sender, noticeType);
215 const std::type_info &senderType) = 0;
227 const std::type_info &senderType,
229 const std::type_info &listenerType) = 0;
252 return _deliverer && _deliverer->_IsActive();
258 operator bool()
const {
265 _DelivererWeakPtr _deliverer;
267 friend class Tf_NoticeRegistry;
346 template <
class LPtr,
class MethodPtr>
350 return _Register(_MakeDeliverer(listener, method));
353 template <
class LPtr,
class MethodPtr,
class SenderPtr>
355 Register(LPtr
const &listener, MethodPtr method, SenderPtr
const &sender) {
357 return _Register(_MakeDeliverer(listener, method, sender));
360 template <
class LPtr,
class MethodPtr>
362 Register(LPtr
const &listener, MethodPtr method,
365 return _Register(_MakeDeliverer(noticeType, listener, method, sender));
439 template <
typename SenderPtr>
440 size_t Send(SenderPtr
const &s)
const;
450 const void *senderUniqueId,
451 const std::type_info &type)
const;
476 : _list(0), _active(true), _markedForRemoval(false)
481 virtual ~_DelivererBase();
484 void _BeginDelivery(
const TfNotice ¬ice,
486 const std::type_info &senderType,
488 const std::type_info &listenerType,
489 const std::vector<TfNotice::WeakProbePtr> &probes);
492 void _EndDelivery(
const std::vector<TfNotice::WeakProbePtr> &probes);
500 _SendToListenerImpl(
const TfNotice &n,
503 const void *senderUniqueId,
504 const std::type_info &senderType,
505 const std::vector<TfNotice::WeakProbePtr> &) = 0;
511 bool _IsActive()
const {
515 void _MarkForRemoval() {
516 _markedForRemoval =
true;
521 bool _IsMarkedForRemoval()
const {
522 return _markedForRemoval;
525 virtual TfType GetNoticeType()
const = 0;
527 virtual bool Delivers(
TfType const ¬iceType,
530 virtual TfWeakBase const *GetSenderWeakBase()
const = 0;
532 virtual _DelivererBase *Clone()
const = 0;
535 bool _SendToListener(
const TfNotice &n,
538 const void *senderUniqueId,
539 const std::type_info &senderType,
540 const std::vector<TfNotice::WeakProbePtr> &probes)
543 if (_busy.fetch_add(1, std::memory_order_release) & _waitBit) {
551 _busy.fetch_add(-1, std::memory_order_release);
558 _busy.fetch_add(-1, std::memory_order_release);
562 _SendToListenerImpl(n, type,
563 s, senderUniqueId, senderType, probes);
569 void _WaitForSendsToFinish()
573 if (_busy.fetch_or(_waitBit, std::memory_order_release)) {
575 _WaitUntilNotSending();
581 template <
class ToNoticeType,
class FromNoticeType>
582 static inline ToNoticeType
const *
583 _CastNotice(FromNoticeType
const *from) {
587 if (!
dynamic_cast<ToNoticeType
const *
>(from)) {
588 ToNoticeType
const *castNotice =
589 TfSafeDynamic_cast<ToNoticeType const *>(from);
592 TfNotice::_VerifyFailedCast(
typeid(ToNoticeType),
596 return static_cast<ToNoticeType
const *
>(from);
601 void _WaitUntilNotSending();
605 _DelivererList *_list;
606 _DelivererList::iterator _listIter;
609 bool _markedForRemoval;
610 std::atomic<int> _busy{0};
612 static constexpr int _waitBit = 0x80000000;
614 friend class Tf_NoticeRegistry;
617 template <
class Derived>
618 class _StandardDeliverer :
public _DelivererBase {
620 virtual ~_StandardDeliverer() {}
622 virtual TfType GetNoticeType()
const {
623 typedef typename Derived::NoticeType NoticeType;
624 TfType ret = TfType::Find<NoticeType>();
627 " undefined in the TfType system");
631 virtual bool Delivers(
TfType const ¬iceType,
633 Derived
const *derived = this->AsDerived();
634 return noticeType.
IsA(GetNoticeType()) &&
635 !derived->_sender.IsInvalid() &&
636 sender && derived->_sender.GetWeakBase() == sender;
639 virtual TfWeakBase const *GetSenderWeakBase()
const {
640 Derived
const *derived = this->AsDerived();
641 return derived->_sender ? derived->_sender.GetWeakBase() : 0;
644 virtual _DelivererBase *Clone()
const {
645 Derived
const *derived = this->AsDerived();
646 return new Derived(derived->_listener,
653 _SendToListenerImpl(
const TfNotice ¬ice,
656 const void *senderUniqueId,
657 const std::type_info &senderType,
658 const std::vector<TfNotice::WeakProbePtr> &probes)
660 Derived *derived = this->AsDerived();
661 typedef typename Derived::ListenerType ListenerType;
662 typedef typename Derived::NoticeType NoticeType;
663 ListenerType *listener = get_pointer(derived->_listener);
665 if (listener && !derived->_sender.IsInvalid()) {
667 std::optional<TfScoped<>> endDeliveryScope;
668 if (ARCH_UNLIKELY(!probes.empty())) {
669 TfWeakBase const *senderWeakBase = GetSenderWeakBase(),
670 *listenerWeakBase = derived->_listener.GetWeakBase();
671 _BeginDelivery(notice, senderWeakBase,
673 senderType :
typeid(
void),
675 typeid(ListenerType), probes);
679 endDeliveryScope.emplace([
this, &probes]() {
680 _EndDelivery(probes);
685 _InvokeListenerMethod(listener,
686 *_CastNotice<NoticeType>(¬ice),
688 senderUniqueId, senderType);
696 Derived *AsDerived() {
697 return static_cast<Derived *
>(
this);
700 Derived
const *AsDerived()
const {
701 return static_cast<Derived
const *
>(
this);
706 template <
typename LPtr,
typename SPtr,
typename Method,
typename Notice>
708 public _StandardDeliverer<_Deliverer<LPtr, SPtr, Method, Notice> >
711 typedef Notice NoticeType;
712 typedef typename LPtr::DataType ListenerType;
713 typedef Method MethodPtr;
715 _Deliverer(LPtr
const &listener,
716 MethodPtr
const &methodPtr,
717 SPtr
const &sender = SPtr(),
719 : _listener(listener)
725 void _InvokeListenerMethod(ListenerType *listener,
726 const NoticeType ¬ice,
730 const std::type_info &)
732 (listener->*_method)(notice);
740 template <
class LPtr,
class Method>
741 class _RawDeliverer :
742 public _StandardDeliverer<_RawDeliverer<LPtr, Method> >
746 typedef typename LPtr::DataType ListenerType;
747 typedef Method MethodPtr;
749 _RawDeliverer(LPtr
const &listener,
750 MethodPtr
const &methodPtr,
753 : _noticeType(noticeType),
760 virtual TfType GetNoticeType()
const {
764 void _InvokeListenerMethod(ListenerType *listener,
765 const NoticeType ¬ice,
768 const void *senderUniqueId,
769 const std::type_info &senderType)
771 (listener->*_method)(notice, noticeType,
773 senderUniqueId, senderType);
782 template <
class LPtr,
class SPtr,
class Method,
class Notice>
783 class _DelivererWithSender :
784 public _StandardDeliverer<
785 _DelivererWithSender<LPtr, SPtr, Method, Notice>
789 typedef Notice NoticeType;
790 typedef Method MethodPtr;
791 typedef typename LPtr::DataType ListenerType;
793 typedef typename SPtr::DataType SenderType;
795 _DelivererWithSender(LPtr
const &listener,
796 MethodPtr
const &methodPtr,
799 : _listener(listener),
805 void _InvokeListenerMethod(ListenerType *listener,
806 const NoticeType ¬ice,
810 const std::type_info &)
812 SenderType *deliveredSender =
813 static_cast<SenderType *
>(
const_cast<TfWeakBase *
>(sender));
814 SPtr deliveredSPtr(deliveredSender);
815 (listener->*_method)(notice, deliveredSPtr);
826 static Key _Register(_DelivererBase*);
829 static void _VerifyFailedCast(
const std::type_info& toType,
835 const void *senderUniqueId,
836 const std::type_info & senderType)
const;
838 size_t _SendWithType(
const TfType & noticeType,
840 const void *senderUniqueId,
841 const std::type_info & senderType)
const;
843 friend class Tf_NoticeRegistry;
847 friend class Tf_PyNotice;
850template <
typename SenderPtr>
854 const TfWeakBase *senderWeakBase = s ? s.GetWeakBase() : NULL;
855 return _Send(senderWeakBase, senderWeakBase ? s.GetUniqueIdentifier() : 0,
857 typeid(
typename SenderPtr::DataType) :
typeid(
void));
860PXR_NAMESPACE_CLOSE_SCOPE
Type independent WeakPtr holder class.
Low-level utilities for informing users of various internal and external diagnostic conditions.
Provides the ability to hold an arbitrary TfWeakPtr in a non-type-specific manner in order to observe...
Blocks sending of all notices in current thread.
Handle-object returned by TfNotice::Register().
bool IsValid() const
Does this key refer to a valid notification?
Probe interface class which may be implemented and then registered via InsertProbe to introspect abou...
virtual void EndDelivery()=0
This method is called after the notice in the corresponding BeginDelivery call has finished being pro...
virtual void EndSend()=0
This method is called after the notice in the corresponding BeginSend call has been delivered to all ...
virtual void BeginDelivery(const TfNotice ¬ice, const TfWeakBase *sender, const std::type_info &senderType, const TfWeakBase *listener, const std::type_info &listenerType)=0
This method is called just before notice is delivered to a listener.
virtual void BeginSend(const TfNotice ¬ice, const TfWeakBase *sender, const std::type_info &senderType)=0
This method is called just before notice is sent to any listeners.
The base class for objects used to notify interested parties (listeners) when events have occurred.
TF_API size_t Send() const
Deliver the notice to interested listeners, returning the number of interested listeners.
static TF_API void RevokeAndWait(TfNotice::Keys *keys)
Revoke interest by listeners.
static TF_API void InsertProbe(const WeakProbePtr &probe)
Register a probe that will be invoked when notices are sent and delivered.
static TF_API void Revoke(TfNotice::Keys *keys)
Revoke interest by listeners.
static TfNotice::Key Register(LPtr const &listener, MethodPtr method)
Register a listener as being interested in a TfNotice.
static TF_API void RemoveProbe(const WeakProbePtr &probe)
Remove a probe that was previously registered with InsertProbe.
TF_API size_t SendWithWeakBase(const TfWeakBase *senderWeakBase, const void *senderUniqueId, const std::type_info &type) const
Variant of Send() that takes a specific sender in the form of a TfWeakBase pointer and a typeid.
static TF_API bool Revoke(TfNotice::Key &key)
Revoke interest by a listener.
static TF_API bool RevokeAndWait(TfNotice::Key &key)
Revoke interest by a listener.
std::vector< Key > Keys
A TfNotice::Key container.
Execute code on exiting scope.
TfType represents a dynamic runtime type.
TF_API bool IsA(TfType queryType) const
Return true if this type is the same as or derived from queryType.
bool IsUnknown() const
Return true if this is the unknown type, representing a type unknown to the TfType system.
Enable a concrete base class for use with TfWeakPtr.
Pointer storage with deletion detection.
Demangle C++ typenames generated by the typeid() facility.
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.
Pointer storage with deletion detection.