7#ifndef PXR_BASE_TF_NOTICE_H
8#define PXR_BASE_TF_NOTICE_H
14#include "pxr/base/tf/api.h"
17#include "pxr/base/tf/type.h"
26PXR_NAMESPACE_OPEN_SCOPE
28class Tf_NoticeRegistry;
81 typedef std::list<_DelivererBase*> _DelivererList;
85 template <
class LPtr,
class L,
86 class Notice,
class SPtr,
class DeliveredSPtr>
87 static _DelivererBase *
88 _MakeDeliverer(LPtr
const &listener,
90 (
const Notice &, DeliveredSPtr
const &),
92 DeliveredSPtr weakSender(sender);
93 return new _DelivererWithSender<
95 void (L::*)(
const Notice &, DeliveredSPtr
const &),
97 >(listener, method, weakSender);
100 template <
class LPtr,
class L,
101 class Notice,
class SPtr,
class DeliveredSPtr>
102 static _DelivererBase *
103 _MakeDeliverer(LPtr
const &listener,
105 (
const Notice &, DeliveredSPtr
const &)
const,
106 SPtr
const &sender) {
107 DeliveredSPtr weakSender(sender);
108 return new _DelivererWithSender<
110 void (L::*)(
const Notice &, DeliveredSPtr
const &)
const,
112 >(listener, method, weakSender);
117 template <
class LPtr,
class L,
class SPtr,
class Notice>
118 static _DelivererBase *
119 _MakeDeliverer(LPtr
const &listener,
120 void (L::*method)(
const Notice &),
121 SPtr
const &sender) {
122 return new _Deliverer<
123 LPtr, SPtr, void (L::*)(
const Notice &), Notice
124 >(listener, method, sender);
127 template <
class LPtr,
class L,
class SPtr,
class Notice>
128 static _DelivererBase *
129 _MakeDeliverer(LPtr
const &listener,
130 void (L::*method)(
const Notice &)
const,
131 SPtr
const &sender) {
132 return new _Deliverer<
133 LPtr, SPtr, void (L::*)(
const Notice &)
const, Notice
134 >(listener, method, sender);
139 template <
class LPtr,
class L,
class Notice>
140 static _DelivererBase *
141 _MakeDeliverer(LPtr
const &listener,
142 void (L::*method)(
const Notice &)) {
143 return new _Deliverer<
148 template <
class LPtr,
class L,
class Notice>
149 static _DelivererBase *
150 _MakeDeliverer(LPtr
const &listener,
151 void (L::*method)(
const Notice &)
const) {
152 return new _Deliverer<
153 LPtr,
TfAnyWeakPtr, void (L::*)(
const Notice &)
const, Notice
159 template <
class LPtr,
class L>
160 static _DelivererBase *
161 _MakeDeliverer(
TfType const ¬iceType,
162 LPtr
const &listener,
166 const std::type_info&),
168 return new _RawDeliverer<LPtr,
171 const std::type_info &)>
172 (listener, method, sender, noticeType);
175 template <
class LPtr,
class L>
176 static _DelivererBase *
177 _MakeDeliverer(
TfType const ¬iceType,
178 LPtr
const &listener,
182 const std::type_info&)
const,
185 return new _RawDeliverer<LPtr,
188 const std::type_info &)
const>
189 (listener, method, sender, noticeType);
212 const std::type_info &senderType) = 0;
224 const std::type_info &senderType,
226 const std::type_info &listenerType) = 0;
249 return _deliverer && _deliverer->_IsActive();
255 operator bool()
const {
262 _DelivererWeakPtr _deliverer;
264 friend class Tf_NoticeRegistry;
343 template <
class LPtr,
class MethodPtr>
346 return _Register(_MakeDeliverer(listener, method));
349 template <
class LPtr,
class MethodPtr,
class SenderPtr>
351 Register(LPtr
const &listener, MethodPtr method, SenderPtr
const &sender) {
352 return _Register(_MakeDeliverer(listener, method, sender));
355 template <
class LPtr,
class MethodPtr>
357 Register(LPtr
const &listener, MethodPtr method,
359 return _Register(_MakeDeliverer(noticeType, listener, method, sender));
433 template <
typename SenderPtr>
434 size_t Send(SenderPtr
const &s)
const;
444 const void *senderUniqueId,
445 const std::type_info &type)
const;
470 : _list(0), _active(true), _markedForRemoval(false)
475 virtual ~_DelivererBase();
478 void _BeginDelivery(
const TfNotice ¬ice,
480 const std::type_info &senderType,
482 const std::type_info &listenerType,
483 const std::vector<TfNotice::WeakProbePtr> &probes);
486 void _EndDelivery(
const std::vector<TfNotice::WeakProbePtr> &probes);
494 _SendToListenerImpl(
const TfNotice &n,
497 const void *senderUniqueId,
498 const std::type_info &senderType,
499 const std::vector<TfNotice::WeakProbePtr> &) = 0;
505 bool _IsActive()
const {
509 void _MarkForRemoval() {
510 _markedForRemoval =
true;
515 bool _IsMarkedForRemoval()
const {
516 return _markedForRemoval;
519 virtual TfType GetNoticeType()
const = 0;
521 virtual bool Delivers(
TfType const ¬iceType,
524 virtual TfWeakBase const *GetSenderWeakBase()
const = 0;
526 virtual _DelivererBase *Clone()
const = 0;
529 bool _SendToListener(
const TfNotice &n,
532 const void *senderUniqueId,
533 const std::type_info &senderType,
534 const std::vector<TfNotice::WeakProbePtr> &probes)
537 if (_busy.fetch_add(1, std::memory_order_release) & _waitBit) {
545 _busy.fetch_add(-1, std::memory_order_release);
549 _SendToListenerImpl(n, type,
550 s, senderUniqueId, senderType, probes);
551 _busy.fetch_add(-1, std::memory_order_release);
557 void _WaitForSendsToFinish()
561 if (_busy.fetch_or(_waitBit, std::memory_order_release)) {
563 _WaitUntilNotSending();
569 template <
class ToNoticeType,
class FromNoticeType>
570 static inline ToNoticeType
const *
571 _CastNotice(FromNoticeType
const *from) {
575 if (!
dynamic_cast<ToNoticeType
const *
>(from)) {
576 ToNoticeType
const *castNotice =
577 TfSafeDynamic_cast<ToNoticeType const *>(from);
580 TfNotice::_VerifyFailedCast(
typeid(ToNoticeType),
584 return static_cast<ToNoticeType
const *
>(from);
589 void _WaitUntilNotSending();
593 _DelivererList *_list;
594 _DelivererList::iterator _listIter;
597 bool _markedForRemoval;
598 std::atomic<int> _busy{0};
600 static constexpr int _waitBit = 0x80000000;
602 friend class Tf_NoticeRegistry;
605 template <
class Derived>
606 class _StandardDeliverer :
public _DelivererBase {
608 virtual ~_StandardDeliverer() {}
610 virtual TfType GetNoticeType()
const {
611 typedef typename Derived::NoticeType NoticeType;
612 TfType ret = TfType::Find<NoticeType>();
615 " undefined in the TfType system");
619 virtual bool Delivers(
TfType const ¬iceType,
621 Derived
const *derived = this->AsDerived();
622 return noticeType.
IsA(GetNoticeType()) &&
623 !derived->_sender.IsInvalid() &&
624 sender && derived->_sender.GetWeakBase() == sender;
627 virtual TfWeakBase const *GetSenderWeakBase()
const {
628 Derived
const *derived = this->AsDerived();
629 return derived->_sender ? derived->_sender.GetWeakBase() : 0;
632 virtual _DelivererBase *Clone()
const {
633 Derived
const *derived = this->AsDerived();
634 return new Derived(derived->_listener,
641 _SendToListenerImpl(
const TfNotice ¬ice,
644 const void *senderUniqueId,
645 const std::type_info &senderType,
646 const std::vector<TfNotice::WeakProbePtr> &probes)
648 Derived *derived = this->AsDerived();
649 typedef typename Derived::ListenerType ListenerType;
650 typedef typename Derived::NoticeType NoticeType;
651 ListenerType *listener = get_pointer(derived->_listener);
653 if (listener && !derived->_sender.IsInvalid()) {
654 if (ARCH_UNLIKELY(!probes.empty())) {
655 TfWeakBase const *senderWeakBase = GetSenderWeakBase(),
656 *listenerWeakBase = derived->_listener.GetWeakBase();
657 _BeginDelivery(notice, senderWeakBase,
659 senderType :
typeid(
void),
661 typeid(ListenerType), probes);
665 _InvokeListenerMethod(listener,
666 *_CastNotice<NoticeType>(¬ice),
668 senderUniqueId, senderType);
670 if (ARCH_UNLIKELY(!probes.empty()))
671 _EndDelivery(probes);
679 Derived *AsDerived() {
680 return static_cast<Derived *
>(
this);
683 Derived
const *AsDerived()
const {
684 return static_cast<Derived
const *
>(
this);
689 template <
typename LPtr,
typename SPtr,
typename Method,
typename Notice>
691 public _StandardDeliverer<_Deliverer<LPtr, SPtr, Method, Notice> >
694 typedef Notice NoticeType;
695 typedef typename LPtr::DataType ListenerType;
696 typedef Method MethodPtr;
698 _Deliverer(LPtr
const &listener,
699 MethodPtr
const &methodPtr,
700 SPtr
const &sender = SPtr(),
702 : _listener(listener)
708 void _InvokeListenerMethod(ListenerType *listener,
709 const NoticeType ¬ice,
713 const std::type_info &)
715 (listener->*_method)(notice);
723 template <
class LPtr,
class Method>
724 class _RawDeliverer :
725 public _StandardDeliverer<_RawDeliverer<LPtr, Method> >
729 typedef typename LPtr::DataType ListenerType;
730 typedef Method MethodPtr;
732 _RawDeliverer(LPtr
const &listener,
733 MethodPtr
const &methodPtr,
736 : _noticeType(noticeType),
743 virtual TfType GetNoticeType()
const {
747 void _InvokeListenerMethod(ListenerType *listener,
748 const NoticeType ¬ice,
751 const void *senderUniqueId,
752 const std::type_info &senderType)
754 (listener->*_method)(notice, noticeType,
756 senderUniqueId, senderType);
765 template <
class LPtr,
class SPtr,
class Method,
class Notice>
766 class _DelivererWithSender :
767 public _StandardDeliverer<
768 _DelivererWithSender<LPtr, SPtr, Method, Notice>
772 typedef Notice NoticeType;
773 typedef Method MethodPtr;
774 typedef typename LPtr::DataType ListenerType;
776 typedef typename SPtr::DataType SenderType;
778 _DelivererWithSender(LPtr
const &listener,
779 MethodPtr
const &methodPtr,
782 : _listener(listener),
788 void _InvokeListenerMethod(ListenerType *listener,
789 const NoticeType ¬ice,
793 const std::type_info &)
795 SenderType *deliveredSender =
796 static_cast<SenderType *
>(
const_cast<TfWeakBase *
>(sender));
797 SPtr deliveredSPtr(deliveredSender);
798 (listener->*_method)(notice, deliveredSPtr);
809 static Key _Register(_DelivererBase*);
812 static void _VerifyFailedCast(
const std::type_info& toType,
818 const void *senderUniqueId,
819 const std::type_info & senderType)
const;
821 size_t _SendWithType(
const TfType & noticeType,
823 const void *senderUniqueId,
824 const std::type_info & senderType)
const;
826 friend class Tf_NoticeRegistry;
830 friend class Tf_PyNotice;
833template <
typename SenderPtr>
837 const TfWeakBase *senderWeakBase = s ? s.GetWeakBase() : NULL;
838 return _Send(senderWeakBase, senderWeakBase ? s.GetUniqueIdentifier() : 0,
840 typeid(
typename SenderPtr::DataType) :
typeid(
void));
843PXR_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.
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.