All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
notice.h
Go to the documentation of this file.
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_BASE_TF_NOTICE_H
8#define PXR_BASE_TF_NOTICE_H
9
12
13#include "pxr/pxr.h"
14#include "pxr/base/tf/api.h"
17#include "pxr/base/tf/type.h"
18#include "pxr/base/tf/weakPtr.h"
20#include "pxr/base/arch/hints.h"
21
22#include <list>
23#include <typeinfo>
24
25PXR_NAMESPACE_OPEN_SCOPE
26
27class Tf_NoticeRegistry;
28
76class TfNotice {
77private:
78 class _DelivererBase;
80 typedef std::list<_DelivererBase*> _DelivererList;
81
83 // Per-sender delivery, listener gets sender.
84 template <class LPtr, class L,
85 class Notice, class SPtr, class DeliveredSPtr>
86 static _DelivererBase *
87 _MakeDeliverer(LPtr const &listener,
88 void (L::*method)
89 (const Notice &, DeliveredSPtr const &),
90 SPtr const &sender) {
91 DeliveredSPtr weakSender(sender);
92 return new _DelivererWithSender<
93 LPtr, DeliveredSPtr,
94 void (L::*)(const Notice &, DeliveredSPtr const &),
95 Notice
96 >(listener, method, weakSender);
97 }
98
99 template <class LPtr, class L,
100 class Notice, class SPtr, class DeliveredSPtr>
101 static _DelivererBase *
102 _MakeDeliverer(LPtr const &listener,
103 void (L::*method)
104 (const Notice &, DeliveredSPtr const &) const,
105 SPtr const &sender) {
106 DeliveredSPtr weakSender(sender);
107 return new _DelivererWithSender<
108 LPtr, DeliveredSPtr,
109 void (L::*)(const Notice &, DeliveredSPtr const &) const,
110 Notice
111 >(listener, method, weakSender);
112 }
113
115 // Per-sender delivery, listener does not get sender.
116 template <class LPtr, class L, class SPtr, class Notice>
117 static _DelivererBase *
118 _MakeDeliverer(LPtr const &listener,
119 void (L::*method)(const Notice &),
120 SPtr const &sender) {
121 return new _Deliverer<
122 LPtr, SPtr, void (L::*)(const Notice &), Notice
123 >(listener, method, sender);
124 }
125
126 template <class LPtr, class L, class SPtr, class Notice>
127 static _DelivererBase *
128 _MakeDeliverer(LPtr const &listener,
129 void (L::*method)(const Notice &) const,
130 SPtr const &sender) {
131 return new _Deliverer<
132 LPtr, SPtr, void (L::*)(const Notice &) const, Notice
133 >(listener, method, sender);
134 }
135
137 // Global delivery.
138 template <class LPtr, class L, class Notice>
139 static _DelivererBase *
140 _MakeDeliverer(LPtr const &listener,
141 void (L::*method)(const Notice &)) {
142 return new _Deliverer<
143 LPtr, TfAnyWeakPtr, void (L::*)(const Notice &), Notice
144 >(listener, method);
145 }
146
147 template <class LPtr, class L, class Notice>
148 static _DelivererBase *
149 _MakeDeliverer(LPtr const &listener,
150 void (L::*method)(const Notice &) const) {
151 return new _Deliverer<
152 LPtr, TfAnyWeakPtr, void (L::*)(const Notice &) const, Notice
153 >(listener, method);
154 }
155
157 // Generic (raw) delivery.
158 template <class LPtr, class L>
159 static _DelivererBase *
160 _MakeDeliverer(TfType const &noticeType,
161 LPtr const &listener,
162 void (L::*method)(const TfNotice &,
163 const TfType &,
164 TfWeakBase*, const void *,
165 const std::type_info&),
166 TfAnyWeakPtr const &sender) {
167 return new _RawDeliverer<LPtr,
168 void (L::*)(const TfNotice &, const TfType &,
169 TfWeakBase *, const void *,
170 const std::type_info &)>
171 (listener, method, sender, noticeType);
172 }
173
174 template <class LPtr, class L>
175 static _DelivererBase *
176 _MakeDeliverer(TfType const &noticeType,
177 LPtr const &listener,
178 void (L::*method)(const TfNotice &,
179 const TfType &,
180 TfWeakBase*, const void *,
181 const std::type_info&) const,
182 TfAnyWeakPtr const &sender)
183 {
184 return new _RawDeliverer<LPtr,
185 void (L::*)(const TfNotice &, const TfType &,
186 TfWeakBase *, const void *,
187 const std::type_info &) const>
188 (listener, method, sender, noticeType);
189 }
190
191
192
193public:
194
195 class Probe;
197
201 class Probe : public TfWeakBase {
202 public:
203 TF_API
204 virtual ~Probe() = 0;
205
209 virtual void BeginSend(const TfNotice &notice,
210 const TfWeakBase *sender,
211 const std::type_info &senderType) = 0;
212
215 virtual void EndSend() = 0;
216
221 virtual void BeginDelivery(const TfNotice &notice,
222 const TfWeakBase *sender,
223 const std::type_info &senderType,
224 const TfWeakBase *listener,
225 const std::type_info &listenerType) = 0;
226
230 virtual void EndDelivery() = 0;
231 };
232
239 class Key {
240 public:
241 Key() {}
242
247 bool IsValid() const {
248 return _deliverer && _deliverer->_IsActive();
249 }
250
254 operator bool() const {
255 return IsValid();
256 }
257
258 private:
259 Key(const _DelivererWeakPtr & d) : _deliverer(d) {}
260
261 _DelivererWeakPtr _deliverer;
262
263 friend class Tf_NoticeRegistry;
264 friend class TfNotice;
265 };
266
272 typedef std::vector<Key> Keys;
273
277 TF_API
278 static void InsertProbe(const WeakProbePtr &probe);
279
282 TF_API
283 static void RemoveProbe(const WeakProbePtr &probe);
284
342 template <class LPtr, class MethodPtr>
343 static TfNotice::Key
344 Register(LPtr const &listener, MethodPtr method) {
345 return _Register(_MakeDeliverer(listener, method));
346 }
347
348 template <class LPtr, class MethodPtr, class SenderPtr>
349 static TfNotice::Key
350 Register(LPtr const &listener, MethodPtr method, SenderPtr const &sender) {
351 return _Register(_MakeDeliverer(listener, method, sender));
352 }
353
354 template <class LPtr, class MethodPtr>
355 static TfNotice::Key
356 Register(LPtr const &listener, MethodPtr method,
357 const TfType &noticeType, const TfAnyWeakPtr &sender) {
358 return _Register(_MakeDeliverer(noticeType, listener, method, sender));
359 }
360
369 TF_API
370 static bool Revoke(TfNotice::Key& key);
371
377 TF_API
378 static void Revoke(TfNotice::Keys* keys);
379
394 TF_API
395 size_t Send() const;
396
411 template <typename SenderPtr>
412 size_t Send(SenderPtr const &s) const;
413
420 TF_API
421 size_t SendWithWeakBase(const TfWeakBase *senderWeakBase,
422 const void *senderUniqueId,
423 const std::type_info &type) const;
424
425 TF_API
426 virtual ~TfNotice();
427
436 class Block {
437 public:
438 TF_API Block();
439 TF_API ~Block();
440 };
441
442private:
443 // Abstract base class for calling listeners.
444 // A typed-version derives (via templating) off this class.
445 class _DelivererBase : public TfWeakBase {
446 public:
447 _DelivererBase()
448 : _list(0), _active(true), _markedForRemoval(false)
449 {
450 }
451
452 TF_API
453 virtual ~_DelivererBase();
454
455 TF_API
456 void _BeginDelivery(const TfNotice &notice,
457 const TfWeakBase *sender,
458 const std::type_info &senderType,
459 const TfWeakBase *listener,
460 const std::type_info &listenerType,
461 const std::vector<TfNotice::WeakProbePtr> &probes);
462
463 TF_API
464 void _EndDelivery(const std::vector<TfNotice::WeakProbePtr> &probes);
465
466 // The derived class converts n to the proper type and delivers it by
467 // calling the listener's method. The function returns \c true,
468 // unless the listener has expired or been marked in active (i.e. by
469 // TfNotice::Revoke()), in which case the method call is skipped and
470 // \c false is returned.
471 virtual bool
472 _SendToListener(const TfNotice &n,
473 const TfType &type,
474 const TfWeakBase *s,
475 const void *senderUniqueId,
476 const std::type_info &senderType,
477 const std::vector<TfNotice::WeakProbePtr> &probes) = 0;
478
479 void _Deactivate() {
480 _active = false;
481 }
482
483 bool _IsActive() const {
484 return _active;
485 }
486
487 void _MarkForRemoval() {
488 _markedForRemoval = true;
489 }
490
491 // True if the entry has been added to the _deadEntries list for
492 // removal. Used to avoid adding it more than once to the list.
493 bool _IsMarkedForRemoval() const {
494 return _markedForRemoval;
495 }
496
497 virtual TfType GetNoticeType() const = 0;
498
499 virtual bool Delivers(TfType const &noticeType,
500 const TfWeakBase *sender) const = 0;
501
502 virtual TfWeakBase const *GetSenderWeakBase() const = 0;
503
504 virtual _DelivererBase *Clone() const = 0;
505
506 protected:
507
508 template <class ToNoticeType, class FromNoticeType>
509 static inline ToNoticeType const *
510 _CastNotice(FromNoticeType const *from) {
511 // Dynamic casting in deliverers is significant overhead, so only
512 // do error checking in debug builds.
513 if (TF_DEV_BUILD) {
514 if (!dynamic_cast<ToNoticeType const *>(from)) {
515 ToNoticeType const *castNotice =
516 TfSafeDynamic_cast<ToNoticeType const *>(from);
517 // this will abort with a clear error message if
518 // castNotice is NULL
519 TfNotice::_VerifyFailedCast(typeid(ToNoticeType),
520 *from, castNotice);
521 }
522 }
523 return static_cast<ToNoticeType const *>(from);
524 }
525
526 private:
527 // Linkage to the containing _DelivererList in the Tf_NoticeRegistry
528 _DelivererList *_list;
529 _DelivererList::iterator _listIter;
530
531 bool _active;
532 bool _markedForRemoval;
533
534 friend class Tf_NoticeRegistry;
535 };
536
537 template <class Derived>
538 class _StandardDeliverer : public _DelivererBase {
539 public:
540 virtual ~_StandardDeliverer() {}
541
542 virtual TfType GetNoticeType() const {
543 typedef typename Derived::NoticeType NoticeType;
544 TfType ret = TfType::Find<NoticeType>();
545 if (ret.IsUnknown())
546 TF_FATAL_ERROR("notice type " + ArchGetDemangled<NoticeType>() +
547 " undefined in the TfType system");
548 return ret;
549 }
550
551 virtual bool Delivers(TfType const &noticeType,
552 TfWeakBase const *sender) const {
553 Derived const *derived = this->AsDerived();
554 return noticeType.IsA(GetNoticeType()) &&
555 !derived->_sender.IsInvalid() &&
556 sender && derived->_sender.GetWeakBase() == sender;
557 }
558
559 virtual TfWeakBase const *GetSenderWeakBase() const {
560 Derived const *derived = this->AsDerived();
561 return derived->_sender ? derived->_sender.GetWeakBase() : 0;
562 }
563
564 virtual _DelivererBase *Clone() const {
565 Derived const *derived = this->AsDerived();
566 return new Derived(derived->_listener,
567 derived->_method,
568 derived->_sender,
569 GetNoticeType());
570 }
571
572 virtual bool
573 _SendToListener(const TfNotice &notice,
574 const TfType &noticeType,
575 const TfWeakBase *sender,
576 const void *senderUniqueId,
577 const std::type_info &senderType,
578 const std::vector<TfNotice::WeakProbePtr> &probes)
579 {
580 Derived *derived = this->AsDerived();
581 typedef typename Derived::ListenerType ListenerType;
582 typedef typename Derived::NoticeType NoticeType;
583 ListenerType *listener = get_pointer(derived->_listener);
584
585 if (listener && !derived->_sender.IsInvalid()) {
586 if (ARCH_UNLIKELY(!probes.empty())) {
587 TfWeakBase const *senderWeakBase = GetSenderWeakBase(),
588 *listenerWeakBase = derived->_listener.GetWeakBase();
589 _BeginDelivery(notice, senderWeakBase,
590 senderWeakBase ?
591 senderType : typeid(void),
592 listenerWeakBase,
593 typeid(ListenerType), probes);
594 }
595
596 derived->
597 _InvokeListenerMethod(listener,
598 *_CastNotice<NoticeType>(&notice),
599 noticeType, sender,
600 senderUniqueId, senderType);
601
602 if (ARCH_UNLIKELY(!probes.empty()))
603 _EndDelivery(probes);
604
605 return true;
606 }
607 return false;
608 }
609
610 private:
611 Derived *AsDerived() {
612 return static_cast<Derived *>(this);
613 }
614
615 Derived const *AsDerived() const {
616 return static_cast<Derived const *>(this);
617 }
618 };
619
620
621 template <typename LPtr, typename SPtr, typename Method, typename Notice>
622 class _Deliverer :
623 public _StandardDeliverer<_Deliverer<LPtr, SPtr, Method, Notice> >
624 {
625 public:
626 typedef Notice NoticeType;
627 typedef typename LPtr::DataType ListenerType;
628 typedef Method MethodPtr;
629
630 _Deliverer(LPtr const &listener,
631 MethodPtr const &methodPtr,
632 SPtr const &sender = SPtr(),
633 TfType const &noticeType = TfType())
634 : _listener(listener)
635 , _sender(sender)
636 , _method(methodPtr)
637 {
638 }
639
640 void _InvokeListenerMethod(ListenerType *listener,
641 const NoticeType &notice,
642 const TfType &noticeType,
643 const TfWeakBase *,
644 const void *,
645 const std::type_info &)
646 {
647 (listener->*_method)(notice);
648 }
649
650 LPtr _listener;
651 SPtr _sender;
652 MethodPtr _method;
653 };
654
655 template <class LPtr, class Method>
656 class _RawDeliverer :
657 public _StandardDeliverer<_RawDeliverer<LPtr, Method> >
658 {
659 public:
660 typedef TfNotice NoticeType;
661 typedef typename LPtr::DataType ListenerType;
662 typedef Method MethodPtr;
663
664 _RawDeliverer(LPtr const &listener,
665 MethodPtr const &methodPtr,
666 TfAnyWeakPtr const &sender,
667 TfType const &noticeType)
668 : _noticeType(noticeType),
669 _listener(listener),
670 _method(methodPtr),
671 _sender(sender)
672 {
673 }
674
675 virtual TfType GetNoticeType() const {
676 return _noticeType;
677 }
678
679 void _InvokeListenerMethod(ListenerType *listener,
680 const NoticeType &notice,
681 const TfType &noticeType,
682 const TfWeakBase *sender,
683 const void *senderUniqueId,
684 const std::type_info &senderType)
685 {
686 (listener->*_method)(notice, noticeType,
687 const_cast<TfWeakBase *>(sender),
688 senderUniqueId, senderType);
689 }
690
691 TfType _noticeType;
692 LPtr _listener;
693 MethodPtr _method;
694 TfAnyWeakPtr _sender;
695 };
696
697 template <class LPtr, class SPtr, class Method, class Notice>
698 class _DelivererWithSender :
699 public _StandardDeliverer<
700 _DelivererWithSender<LPtr, SPtr, Method, Notice>
701 >
702 {
703 public:
704 typedef Notice NoticeType;
705 typedef Method MethodPtr;
706 typedef typename LPtr::DataType ListenerType;
707
708 typedef typename SPtr::DataType SenderType;
709
710 _DelivererWithSender(LPtr const &listener,
711 MethodPtr const &methodPtr,
712 SPtr const &sender,
713 TfType const &noticeType = TfType())
714 : _listener(listener),
715 _sender(sender),
716 _method(methodPtr)
717 {
718 }
719
720 void _InvokeListenerMethod(ListenerType *listener,
721 const NoticeType &notice,
722 const TfType &noticeType,
723 const TfWeakBase *sender,
724 const void *,
725 const std::type_info &)
726 {
727 SenderType *deliveredSender =
728 static_cast<SenderType *>(const_cast<TfWeakBase *>(sender));
729 SPtr deliveredSPtr(deliveredSender);
730 (listener->*_method)(notice, deliveredSPtr);
731 }
732
733 LPtr _listener;
734 SPtr _sender;
735 MethodPtr _method;
736 };
737
738private:
739 // Internal non-templated function to install listeners.
740 TF_API
741 static Key _Register(_DelivererBase*);
742
743 TF_API
744 static void _VerifyFailedCast(const std::type_info& toType,
745 const TfNotice& notice,
746 const TfNotice* castNotice);
747
748 TF_API
749 size_t _Send(const TfWeakBase* sender,
750 const void *senderUniqueId,
751 const std::type_info & senderType) const;
752 TF_API
753 size_t _SendWithType(const TfType & noticeType,
754 const TfWeakBase* sender,
755 const void *senderUniqueId,
756 const std::type_info & senderType) const;
757
758 friend class Tf_NoticeRegistry;
759
760 // Befriend the wrapping so it can access _SendWithType() directly
761 // in order to provide dynamic downcasting of Python notice types.
762 friend class Tf_PyNotice;
763};
764
765template <typename SenderPtr>
766size_t
767TfNotice::Send(SenderPtr const &s) const
768{
769 const TfWeakBase *senderWeakBase = s ? s.GetWeakBase() : NULL;
770 return _Send(senderWeakBase, senderWeakBase ? s.GetUniqueIdentifier() : 0,
771 senderWeakBase ?
772 typeid(typename SenderPtr::DataType) : typeid(void));
773}
774
775PXR_NAMESPACE_CLOSE_SCOPE
776
777#endif // PXR_BASE_TF_NOTICE_H
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...
Definition: anyWeakPtr.h:37
Blocks sending of all notices in current thread.
Definition: notice.h:436
Handle-object returned by TfNotice::Register().
Definition: notice.h:239
bool IsValid() const
Does this key refer to a valid notification?
Definition: notice.h:247
Probe interface class which may be implemented and then registered via InsertProbe to introspect abou...
Definition: notice.h:201
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 &notice, 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 &notice, 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.
Definition: notice.h:76
TF_API size_t Send() const
Deliver the notice to interested listeners, returning the number of interested 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.
Definition: notice.h:344
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.
std::vector< Key > Keys
A TfNotice::Key container.
Definition: notice.h:272
TfType represents a dynamic runtime type.
Definition: type.h:48
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.
Definition: type.h:374
Enable a concrete base class for use with TfWeakPtr.
Definition: weakBase.h:124
Pointer storage with deletion detection.
Definition: weakPtr.h:128
Demangle C++ typenames generated by the typeid() facility.
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.
Definition: diagnostic.h:91
Compiler hints.
Pointer storage with deletion detection.