7 #ifndef PXR_BASE_TF_NOTICE_H
8 #define PXR_BASE_TF_NOTICE_H
17 #include "pxr/base/tf/mallocTag.h"
31 class 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<
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();
265 _DelivererWeakPtr _deliverer;
346 template <
class LPtr,
class MethodPtr>
349 TfAutoMallocTag tag(
"Tf",
"Tf_NoticeRegistry::_Register");
350 return _Register(_MakeDeliverer(listener, method));
353 template <
class LPtr,
class MethodPtr,
class SenderPtr>
355 Register(LPtr
const &listener, MethodPtr method, SenderPtr
const &sender) {
356 TfAutoMallocTag tag(
"Tf",
"Tf_NoticeRegistry::_Register");
357 return _Register(_MakeDeliverer(listener, method, sender));
360 template <
class LPtr,
class MethodPtr>
364 TfAutoMallocTag tag(
"Tf",
"Tf_NoticeRegistry::_Register");
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);
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;
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 =
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;
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;
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;
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> >
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,
772 const_cast<TfWeakBase *>(sender),
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;
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;
850 template <
typename SenderPtr>
854 const TfWeakBase *senderWeakBase = s ? s.GetWeakBase() : NULL;
862 #endif // PXR_BASE_TF_NOTICE_H
virtual TF_API ~Probe()=0
virtual void BeginSend(const TfNotice ¬ice, const TfWeakBase *sender, const std::type_info &senderType)=0
virtual TF_API ~TfNotice()
#define PXR_NAMESPACE_OPEN_SCOPE
static TfNotice::Key Register(LPtr const &listener, MethodPtr method)
friend class Tf_NoticeRegistry
static TF_API void InsertProbe(const WeakProbePtr &probe)
**But if you need a result
Y * get_pointer(TfWeakPtrFacade< X, Y > const &p)
GLint GLint GLsizei GLint GLenum GLenum type
TF_API size_t SendWithWeakBase(const TfWeakBase *senderWeakBase, const void *senderUniqueId, const std::type_info &type) const
static TF_API void RemoveProbe(const WeakProbePtr &probe)
static TF_API bool Revoke(TfNotice::Key &key)
TfRefPtr< typename D::DataType > TfSafeDynamic_cast(const TfRefPtr< T > &ptr)
virtual void EndDelivery()=0
static TF_API bool RevokeAndWait(TfNotice::Key &key)
static TfNotice::Key Register(LPtr const &listener, MethodPtr method, const TfType ¬iceType, const TfAnyWeakPtr &sender)
FS_API bool cleanup(UT_StringArray &removed, UT_StringArray &error_files, exint &memory_freed, bool dry_run, const char *override_path=nullptr)
friend class Tf_NoticeRegistry
virtual void BeginDelivery(const TfNotice ¬ice, const TfWeakBase *sender, const std::type_info &senderType, const TfWeakBase *listener, const std::type_info &listenerType)=0
#define PXR_NAMESPACE_CLOSE_SCOPE
TF_API bool IsA(TfType queryType) const
TF_API size_t Send() const
TfWeakPtr< Probe > WeakProbePtr
static TfNotice::Key Register(LPtr const &listener, MethodPtr method, SenderPtr const &sender)
TF_API void const * GetUniqueIdentifier() const