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/type.h"
27PXR_NAMESPACE_OPEN_SCOPE
29class Tf_NoticeRegistry;
82 typedef std::list<_DelivererBase*> _DelivererList;
86 template <
class LPtr,
class L,
87 class Notice,
class SPtr,
class DeliveredSPtr>
88 static _DelivererBase *
89 _MakeDeliverer(LPtr
const &listener,
91 (
const Notice &, DeliveredSPtr
const &),
93 DeliveredSPtr weakSender(sender);
94 return new _DelivererWithSender<
96 void (L::*)(
const Notice &, DeliveredSPtr
const &),
98 >(listener, method, weakSender);
101 template <
class LPtr,
class L,
102 class Notice,
class SPtr,
class DeliveredSPtr>
103 static _DelivererBase *
104 _MakeDeliverer(LPtr
const &listener,
106 (
const Notice &, DeliveredSPtr
const &)
const,
107 SPtr
const &sender) {
108 DeliveredSPtr weakSender(sender);
109 return new _DelivererWithSender<
111 void (L::*)(
const Notice &, DeliveredSPtr
const &)
const,
113 >(listener, method, weakSender);
118 template <
class LPtr,
class L,
class SPtr,
class Notice>
119 static _DelivererBase *
120 _MakeDeliverer(LPtr
const &listener,
121 void (L::*method)(
const Notice &),
122 SPtr
const &sender) {
123 return new _Deliverer<
124 LPtr, SPtr, void (L::*)(
const Notice &), Notice
125 >(listener, method, sender);
128 template <
class LPtr,
class L,
class SPtr,
class Notice>
129 static _DelivererBase *
130 _MakeDeliverer(LPtr
const &listener,
131 void (L::*method)(
const Notice &)
const,
132 SPtr
const &sender) {
133 return new _Deliverer<
134 LPtr, SPtr, void (L::*)(
const Notice &)
const, Notice
135 >(listener, method, sender);
140 template <
class LPtr,
class L,
class Notice>
141 static _DelivererBase *
142 _MakeDeliverer(LPtr
const &listener,
143 void (L::*method)(
const Notice &)) {
144 return new _Deliverer<
149 template <
class LPtr,
class L,
class Notice>
150 static _DelivererBase *
151 _MakeDeliverer(LPtr
const &listener,
152 void (L::*method)(
const Notice &)
const) {
153 return new _Deliverer<
154 LPtr,
TfAnyWeakPtr, void (L::*)(
const Notice &)
const, Notice
160 template <
class LPtr,
class L>
161 static _DelivererBase *
162 _MakeDeliverer(
TfType const ¬iceType,
163 LPtr
const &listener,
167 const std::type_info&),
169 return new _RawDeliverer<LPtr,
172 const std::type_info &)>
173 (listener, method, sender, noticeType);
176 template <
class LPtr,
class L>
177 static _DelivererBase *
178 _MakeDeliverer(
TfType const ¬iceType,
179 LPtr
const &listener,
183 const std::type_info&)
const,
186 return new _RawDeliverer<LPtr,
189 const std::type_info &)
const>
190 (listener, method, sender, noticeType);
213 const std::type_info &senderType) = 0;
225 const std::type_info &senderType,
227 const std::type_info &listenerType) = 0;
250 return _deliverer && _deliverer->_IsActive();
256 operator bool()
const {
263 _DelivererWeakPtr _deliverer;
265 friend class Tf_NoticeRegistry;
344 template <
class LPtr,
class MethodPtr>
348 return _Register(_MakeDeliverer(listener, method));
351 template <
class LPtr,
class MethodPtr,
class SenderPtr>
353 Register(LPtr
const &listener, MethodPtr method, SenderPtr
const &sender) {
355 return _Register(_MakeDeliverer(listener, method, sender));
358 template <
class LPtr,
class MethodPtr>
360 Register(LPtr
const &listener, MethodPtr method,
363 return _Register(_MakeDeliverer(noticeType, listener, method, sender));
437 template <
typename SenderPtr>
438 size_t Send(SenderPtr
const &s)
const;
448 const void *senderUniqueId,
449 const std::type_info &type)
const;
474 : _list(0), _active(true), _markedForRemoval(false)
479 virtual ~_DelivererBase();
482 void _BeginDelivery(
const TfNotice ¬ice,
484 const std::type_info &senderType,
486 const std::type_info &listenerType,
487 const std::vector<TfNotice::WeakProbePtr> &probes);
490 void _EndDelivery(
const std::vector<TfNotice::WeakProbePtr> &probes);
498 _SendToListenerImpl(
const TfNotice &n,
501 const void *senderUniqueId,
502 const std::type_info &senderType,
503 const std::vector<TfNotice::WeakProbePtr> &) = 0;
509 bool _IsActive()
const {
513 void _MarkForRemoval() {
514 _markedForRemoval =
true;
519 bool _IsMarkedForRemoval()
const {
520 return _markedForRemoval;
523 virtual TfType GetNoticeType()
const = 0;
525 virtual bool Delivers(
TfType const ¬iceType,
528 virtual TfWeakBase const *GetSenderWeakBase()
const = 0;
530 virtual _DelivererBase *Clone()
const = 0;
533 bool _SendToListener(
const TfNotice &n,
536 const void *senderUniqueId,
537 const std::type_info &senderType,
538 const std::vector<TfNotice::WeakProbePtr> &probes)
541 if (_busy.fetch_add(1, std::memory_order_release) & _waitBit) {
549 _busy.fetch_add(-1, std::memory_order_release);
553 _SendToListenerImpl(n, type,
554 s, senderUniqueId, senderType, probes);
555 _busy.fetch_add(-1, std::memory_order_release);
561 void _WaitForSendsToFinish()
565 if (_busy.fetch_or(_waitBit, std::memory_order_release)) {
567 _WaitUntilNotSending();
573 template <
class ToNoticeType,
class FromNoticeType>
574 static inline ToNoticeType
const *
575 _CastNotice(FromNoticeType
const *from) {
579 if (!
dynamic_cast<ToNoticeType
const *
>(from)) {
580 ToNoticeType
const *castNotice =
581 TfSafeDynamic_cast<ToNoticeType const *>(from);
584 TfNotice::_VerifyFailedCast(
typeid(ToNoticeType),
588 return static_cast<ToNoticeType
const *
>(from);
593 void _WaitUntilNotSending();
597 _DelivererList *_list;
598 _DelivererList::iterator _listIter;
601 bool _markedForRemoval;
602 std::atomic<int> _busy{0};
604 static constexpr int _waitBit = 0x80000000;
606 friend class Tf_NoticeRegistry;
609 template <
class Derived>
610 class _StandardDeliverer :
public _DelivererBase {
612 virtual ~_StandardDeliverer() {}
614 virtual TfType GetNoticeType()
const {
615 typedef typename Derived::NoticeType NoticeType;
616 TfType ret = TfType::Find<NoticeType>();
619 " undefined in the TfType system");
623 virtual bool Delivers(
TfType const ¬iceType,
625 Derived
const *derived = this->AsDerived();
626 return noticeType.
IsA(GetNoticeType()) &&
627 !derived->_sender.IsInvalid() &&
628 sender && derived->_sender.GetWeakBase() == sender;
631 virtual TfWeakBase const *GetSenderWeakBase()
const {
632 Derived
const *derived = this->AsDerived();
633 return derived->_sender ? derived->_sender.GetWeakBase() : 0;
636 virtual _DelivererBase *Clone()
const {
637 Derived
const *derived = this->AsDerived();
638 return new Derived(derived->_listener,
645 _SendToListenerImpl(
const TfNotice ¬ice,
648 const void *senderUniqueId,
649 const std::type_info &senderType,
650 const std::vector<TfNotice::WeakProbePtr> &probes)
652 Derived *derived = this->AsDerived();
653 typedef typename Derived::ListenerType ListenerType;
654 typedef typename Derived::NoticeType NoticeType;
655 ListenerType *listener = get_pointer(derived->_listener);
657 if (listener && !derived->_sender.IsInvalid()) {
658 if (ARCH_UNLIKELY(!probes.empty())) {
659 TfWeakBase const *senderWeakBase = GetSenderWeakBase(),
660 *listenerWeakBase = derived->_listener.GetWeakBase();
661 _BeginDelivery(notice, senderWeakBase,
663 senderType :
typeid(
void),
665 typeid(ListenerType), probes);
669 _InvokeListenerMethod(listener,
670 *_CastNotice<NoticeType>(¬ice),
672 senderUniqueId, senderType);
674 if (ARCH_UNLIKELY(!probes.empty()))
675 _EndDelivery(probes);
683 Derived *AsDerived() {
684 return static_cast<Derived *
>(
this);
687 Derived
const *AsDerived()
const {
688 return static_cast<Derived
const *
>(
this);
693 template <
typename LPtr,
typename SPtr,
typename Method,
typename Notice>
695 public _StandardDeliverer<_Deliverer<LPtr, SPtr, Method, Notice> >
698 typedef Notice NoticeType;
699 typedef typename LPtr::DataType ListenerType;
700 typedef Method MethodPtr;
702 _Deliverer(LPtr
const &listener,
703 MethodPtr
const &methodPtr,
704 SPtr
const &sender = SPtr(),
706 : _listener(listener)
712 void _InvokeListenerMethod(ListenerType *listener,
713 const NoticeType ¬ice,
717 const std::type_info &)
719 (listener->*_method)(notice);
727 template <
class LPtr,
class Method>
728 class _RawDeliverer :
729 public _StandardDeliverer<_RawDeliverer<LPtr, Method> >
733 typedef typename LPtr::DataType ListenerType;
734 typedef Method MethodPtr;
736 _RawDeliverer(LPtr
const &listener,
737 MethodPtr
const &methodPtr,
740 : _noticeType(noticeType),
747 virtual TfType GetNoticeType()
const {
751 void _InvokeListenerMethod(ListenerType *listener,
752 const NoticeType ¬ice,
755 const void *senderUniqueId,
756 const std::type_info &senderType)
758 (listener->*_method)(notice, noticeType,
760 senderUniqueId, senderType);
769 template <
class LPtr,
class SPtr,
class Method,
class Notice>
770 class _DelivererWithSender :
771 public _StandardDeliverer<
772 _DelivererWithSender<LPtr, SPtr, Method, Notice>
776 typedef Notice NoticeType;
777 typedef Method MethodPtr;
778 typedef typename LPtr::DataType ListenerType;
780 typedef typename SPtr::DataType SenderType;
782 _DelivererWithSender(LPtr
const &listener,
783 MethodPtr
const &methodPtr,
786 : _listener(listener),
792 void _InvokeListenerMethod(ListenerType *listener,
793 const NoticeType ¬ice,
797 const std::type_info &)
799 SenderType *deliveredSender =
800 static_cast<SenderType *
>(
const_cast<TfWeakBase *
>(sender));
801 SPtr deliveredSPtr(deliveredSender);
802 (listener->*_method)(notice, deliveredSPtr);
813 static Key _Register(_DelivererBase*);
816 static void _VerifyFailedCast(
const std::type_info& toType,
822 const void *senderUniqueId,
823 const std::type_info & senderType)
const;
825 size_t _SendWithType(
const TfType & noticeType,
827 const void *senderUniqueId,
828 const std::type_info & senderType)
const;
830 friend class Tf_NoticeRegistry;
834 friend class Tf_PyNotice;
837template <
typename SenderPtr>
841 const TfWeakBase *senderWeakBase = s ? s.GetWeakBase() : NULL;
842 return _Send(senderWeakBase, senderWeakBase ? s.GetUniqueIdentifier() : 0,
844 typeid(
typename SenderPtr::DataType) :
typeid(
void));
847PXR_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.