Loading...
Searching...
No Matches
notice.h
Go to the documentation of this file.
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the Apache License, Version 2.0 (the "Apache License")
5// with the following modification; you may not use this file except in
6// compliance with the Apache License and the following modification to it:
7// Section 6. Trademarks. is deleted and replaced with:
8//
9// 6. Trademarks. This License does not grant permission to use the trade
10// names, trademarks, service marks, or product names of the Licensor
11// and its affiliates, except as required to comply with Section 4(c) of
12// the License and to reproduce the content of the NOTICE file.
13//
14// You may obtain a copy of the Apache License at
15//
16// http://www.apache.org/licenses/LICENSE-2.0
17//
18// Unless required by applicable law or agreed to in writing, software
19// distributed under the Apache License with the above modification is
20// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21// KIND, either express or implied. See the Apache License for the specific
22// language governing permissions and limitations under the Apache License.
23//
24#ifndef PXR_BASE_TF_NOTICE_H
25#define PXR_BASE_TF_NOTICE_H
26
29
30#include "pxr/pxr.h"
31#include "pxr/base/tf/api.h"
34#include "pxr/base/tf/type.h"
35#include "pxr/base/tf/weakPtr.h"
37#include "pxr/base/arch/hints.h"
38
39#include <list>
40#include <typeinfo>
41
42PXR_NAMESPACE_OPEN_SCOPE
43
44class Tf_NoticeRegistry;
45
93class TfNotice {
94private:
95 class _DelivererBase;
97 typedef std::list<_DelivererBase*> _DelivererList;
98
100 // Per-sender delivery, listener gets sender.
101 template <class LPtr, class L,
102 class Notice, class SPtr, class DeliveredSPtr>
103 static _DelivererBase *
104 _MakeDeliverer(LPtr const &listener,
105 void (L::*method)
106 (const Notice &, DeliveredSPtr const &),
107 SPtr const &sender) {
108 DeliveredSPtr weakSender(sender);
109 return new _DelivererWithSender<
110 LPtr, DeliveredSPtr,
111 void (L::*)(const Notice &, DeliveredSPtr const &),
112 Notice
113 >(listener, method, weakSender);
114 }
115
116 template <class LPtr, class L,
117 class Notice, class SPtr, class DeliveredSPtr>
118 static _DelivererBase *
119 _MakeDeliverer(LPtr const &listener,
120 void (L::*method)
121 (const Notice &, DeliveredSPtr const &) const,
122 SPtr const &sender) {
123 DeliveredSPtr weakSender(sender);
124 return new _DelivererWithSender<
125 LPtr, DeliveredSPtr,
126 void (L::*)(const Notice &, DeliveredSPtr const &) const,
127 Notice
128 >(listener, method, weakSender);
129 }
130
132 // Per-sender delivery, listener does not get sender.
133 template <class LPtr, class L, class SPtr, class Notice>
134 static _DelivererBase *
135 _MakeDeliverer(LPtr const &listener,
136 void (L::*method)(const Notice &),
137 SPtr const &sender) {
138 return new _Deliverer<
139 LPtr, SPtr, void (L::*)(const Notice &), Notice
140 >(listener, method, sender);
141 }
142
143 template <class LPtr, class L, class SPtr, class Notice>
144 static _DelivererBase *
145 _MakeDeliverer(LPtr const &listener,
146 void (L::*method)(const Notice &) const,
147 SPtr const &sender) {
148 return new _Deliverer<
149 LPtr, SPtr, void (L::*)(const Notice &) const, Notice
150 >(listener, method, sender);
151 }
152
154 // Global delivery.
155 template <class LPtr, class L, class Notice>
156 static _DelivererBase *
157 _MakeDeliverer(LPtr const &listener,
158 void (L::*method)(const Notice &)) {
159 return new _Deliverer<
160 LPtr, TfAnyWeakPtr, void (L::*)(const Notice &), Notice
161 >(listener, method);
162 }
163
164 template <class LPtr, class L, class Notice>
165 static _DelivererBase *
166 _MakeDeliverer(LPtr const &listener,
167 void (L::*method)(const Notice &) const) {
168 return new _Deliverer<
169 LPtr, TfAnyWeakPtr, void (L::*)(const Notice &) const, Notice
170 >(listener, method);
171 }
172
174 // Generic (raw) delivery.
175 template <class LPtr, class L>
176 static _DelivererBase *
177 _MakeDeliverer(TfType const &noticeType,
178 LPtr const &listener,
179 void (L::*method)(const TfNotice &,
180 const TfType &,
181 TfWeakBase*, const void *,
182 const std::type_info&),
183 TfAnyWeakPtr const &sender) {
184 return new _RawDeliverer<LPtr,
185 void (L::*)(const TfNotice &, const TfType &,
186 TfWeakBase *, const void *,
187 const std::type_info &)>
188 (listener, method, sender, noticeType);
189 }
190
191 template <class LPtr, class L>
192 static _DelivererBase *
193 _MakeDeliverer(TfType const &noticeType,
194 LPtr const &listener,
195 void (L::*method)(const TfNotice &,
196 const TfType &,
197 TfWeakBase*, const void *,
198 const std::type_info&) const,
199 TfAnyWeakPtr const &sender)
200 {
201 return new _RawDeliverer<LPtr,
202 void (L::*)(const TfNotice &, const TfType &,
203 TfWeakBase *, const void *,
204 const std::type_info &) const>
205 (listener, method, sender, noticeType);
206 }
207
208
209
210public:
211
212 class Probe;
214
218 class Probe : public TfWeakBase {
219 public:
220 TF_API
221 virtual ~Probe() = 0;
222
226 virtual void BeginSend(const TfNotice &notice,
227 const TfWeakBase *sender,
228 const std::type_info &senderType) = 0;
229
232 virtual void EndSend() = 0;
233
238 virtual void BeginDelivery(const TfNotice &notice,
239 const TfWeakBase *sender,
240 const std::type_info &senderType,
241 const TfWeakBase *listener,
242 const std::type_info &listenerType) = 0;
243
247 virtual void EndDelivery() = 0;
248 };
249
256 class Key {
257 public:
258 Key() {}
259
264 bool IsValid() const {
265 return _deliverer && _deliverer->_IsActive();
266 }
267
271 operator bool() const {
272 return IsValid();
273 }
274
275 private:
276 Key(const _DelivererWeakPtr & d) : _deliverer(d) {}
277
278 _DelivererWeakPtr _deliverer;
279
280 friend class Tf_NoticeRegistry;
281 friend class TfNotice;
282 };
283
289 typedef std::vector<Key> Keys;
290
294 TF_API
295 static void InsertProbe(const WeakProbePtr &probe);
296
299 TF_API
300 static void RemoveProbe(const WeakProbePtr &probe);
301
359 template <class LPtr, class MethodPtr>
360 static TfNotice::Key
361 Register(LPtr const &listener, MethodPtr method) {
362 return _Register(_MakeDeliverer(listener, method));
363 }
364
365 template <class LPtr, class MethodPtr, class SenderPtr>
366 static TfNotice::Key
367 Register(LPtr const &listener, MethodPtr method, SenderPtr const &sender) {
368 return _Register(_MakeDeliverer(listener, method, sender));
369 }
370
371 template <class LPtr, class MethodPtr>
372 static TfNotice::Key
373 Register(LPtr const &listener, MethodPtr method,
374 const TfType &noticeType, const TfAnyWeakPtr &sender) {
375 return _Register(_MakeDeliverer(noticeType, listener, method, sender));
376 }
377
386 TF_API
387 static bool Revoke(TfNotice::Key& key);
388
394 TF_API
395 static void Revoke(TfNotice::Keys* keys);
396
411 TF_API
412 size_t Send() const;
413
428 template <typename SenderPtr>
429 size_t Send(SenderPtr const &s) const;
430
437 TF_API
438 size_t SendWithWeakBase(const TfWeakBase *senderWeakBase,
439 const void *senderUniqueId,
440 const std::type_info &type) const;
441
442 TF_API
443 virtual ~TfNotice();
444
453 class Block {
454 public:
455 TF_API Block();
456 TF_API ~Block();
457 };
458
459private:
460 // Abstract base class for calling listeners.
461 // A typed-version derives (via templating) off this class.
462 class _DelivererBase : public TfWeakBase {
463 public:
464 _DelivererBase()
465 : _list(0), _active(true), _markedForRemoval(false)
466 {
467 }
468
469 TF_API
470 virtual ~_DelivererBase();
471
472 TF_API
473 void _BeginDelivery(const TfNotice &notice,
474 const TfWeakBase *sender,
475 const std::type_info &senderType,
476 const TfWeakBase *listener,
477 const std::type_info &listenerType,
478 const std::vector<TfNotice::WeakProbePtr> &probes);
479
480 TF_API
481 void _EndDelivery(const std::vector<TfNotice::WeakProbePtr> &probes);
482
483 // The derived class converts n to the proper type and delivers it by
484 // calling the listener's method. The function returns \c true,
485 // unless the listener has expired or been marked in active (i.e. by
486 // TfNotice::Revoke()), in which case the method call is skipped and
487 // \c false is returned.
488 virtual bool
489 _SendToListener(const TfNotice &n,
490 const TfType &type,
491 const TfWeakBase *s,
492 const void *senderUniqueId,
493 const std::type_info &senderType,
494 const std::vector<TfNotice::WeakProbePtr> &probes) = 0;
495
496 void _Deactivate() {
497 _active = false;
498 }
499
500 bool _IsActive() const {
501 return _active;
502 }
503
504 void _MarkForRemoval() {
505 _markedForRemoval = true;
506 }
507
508 // True if the entry has been added to the _deadEntries list for
509 // removal. Used to avoid adding it more than once to the list.
510 bool _IsMarkedForRemoval() const {
511 return _markedForRemoval;
512 }
513
514 virtual TfType GetNoticeType() const = 0;
515
516 virtual bool Delivers(TfType const &noticeType,
517 const TfWeakBase *sender) const = 0;
518
519 virtual TfWeakBase const *GetSenderWeakBase() const = 0;
520
521 virtual _DelivererBase *Clone() const = 0;
522
523 protected:
524
525 template <class ToNoticeType, class FromNoticeType>
526 static inline ToNoticeType const *
527 _CastNotice(FromNoticeType const *from) {
528 // Dynamic casting in deliverers is significant overhead, so only
529 // do error checking in debug builds.
530 if (TF_DEV_BUILD) {
531 if (!dynamic_cast<ToNoticeType const *>(from)) {
532 ToNoticeType const *castNotice =
533 TfSafeDynamic_cast<ToNoticeType const *>(from);
534 // this will abort with a clear error message if
535 // castNotice is NULL
536 TfNotice::_VerifyFailedCast(typeid(ToNoticeType),
537 *from, castNotice);
538 }
539 }
540 return static_cast<ToNoticeType const *>(from);
541 }
542
543 private:
544 // Linkage to the containing _DelivererList in the Tf_NoticeRegistry
545 _DelivererList *_list;
546 _DelivererList::iterator _listIter;
547
548 bool _active;
549 bool _markedForRemoval;
550
551 friend class Tf_NoticeRegistry;
552 };
553
554 template <class Derived>
555 class _StandardDeliverer : public _DelivererBase {
556 public:
557 virtual ~_StandardDeliverer() {}
558
559 virtual TfType GetNoticeType() const {
560 typedef typename Derived::NoticeType NoticeType;
561 TfType ret = TfType::Find<NoticeType>();
562 if (ret.IsUnknown())
563 TF_FATAL_ERROR("notice type " + ArchGetDemangled<NoticeType>() +
564 " undefined in the TfType system");
565 return ret;
566 }
567
568 virtual bool Delivers(TfType const &noticeType,
569 TfWeakBase const *sender) const {
570 Derived const *derived = this->AsDerived();
571 return noticeType.IsA(GetNoticeType()) &&
572 !derived->_sender.IsInvalid() &&
573 sender && derived->_sender.GetWeakBase() == sender;
574 }
575
576 virtual TfWeakBase const *GetSenderWeakBase() const {
577 Derived const *derived = this->AsDerived();
578 return derived->_sender ? derived->_sender.GetWeakBase() : 0;
579 }
580
581 virtual _DelivererBase *Clone() const {
582 Derived const *derived = this->AsDerived();
583 return new Derived(derived->_listener,
584 derived->_method,
585 derived->_sender,
586 GetNoticeType());
587 }
588
589 virtual bool
590 _SendToListener(const TfNotice &notice,
591 const TfType &noticeType,
592 const TfWeakBase *sender,
593 const void *senderUniqueId,
594 const std::type_info &senderType,
595 const std::vector<TfNotice::WeakProbePtr> &probes)
596 {
597 Derived *derived = this->AsDerived();
598 typedef typename Derived::ListenerType ListenerType;
599 typedef typename Derived::NoticeType NoticeType;
600 ListenerType *listener = get_pointer(derived->_listener);
601
602 if (listener && !derived->_sender.IsInvalid()) {
603 if (ARCH_UNLIKELY(!probes.empty())) {
604 TfWeakBase const *senderWeakBase = GetSenderWeakBase(),
605 *listenerWeakBase = derived->_listener.GetWeakBase();
606 _BeginDelivery(notice, senderWeakBase,
607 senderWeakBase ?
608 senderType : typeid(void),
609 listenerWeakBase,
610 typeid(ListenerType), probes);
611 }
612
613 derived->
614 _InvokeListenerMethod(listener,
615 *_CastNotice<NoticeType>(&notice),
616 noticeType, sender,
617 senderUniqueId, senderType);
618
619 if (ARCH_UNLIKELY(!probes.empty()))
620 _EndDelivery(probes);
621
622 return true;
623 }
624 return false;
625 }
626
627 private:
628 Derived *AsDerived() {
629 return static_cast<Derived *>(this);
630 }
631
632 Derived const *AsDerived() const {
633 return static_cast<Derived const *>(this);
634 }
635 };
636
637
638 template <typename LPtr, typename SPtr, typename Method, typename Notice>
639 class _Deliverer :
640 public _StandardDeliverer<_Deliverer<LPtr, SPtr, Method, Notice> >
641 {
642 public:
643 typedef Notice NoticeType;
644 typedef typename LPtr::DataType ListenerType;
645 typedef Method MethodPtr;
646
647 _Deliverer(LPtr const &listener,
648 MethodPtr const &methodPtr,
649 SPtr const &sender = SPtr(),
650 TfType const &noticeType = TfType())
651 : _listener(listener)
652 , _sender(sender)
653 , _method(methodPtr)
654 {
655 }
656
657 void _InvokeListenerMethod(ListenerType *listener,
658 const NoticeType &notice,
659 const TfType &noticeType,
660 const TfWeakBase *,
661 const void *,
662 const std::type_info &)
663 {
664 (listener->*_method)(notice);
665 }
666
667 LPtr _listener;
668 SPtr _sender;
669 MethodPtr _method;
670 };
671
672 template <class LPtr, class Method>
673 class _RawDeliverer :
674 public _StandardDeliverer<_RawDeliverer<LPtr, Method> >
675 {
676 public:
677 typedef TfNotice NoticeType;
678 typedef typename LPtr::DataType ListenerType;
679 typedef Method MethodPtr;
680
681 _RawDeliverer(LPtr const &listener,
682 MethodPtr const &methodPtr,
683 TfAnyWeakPtr const &sender,
684 TfType const &noticeType)
685 : _noticeType(noticeType),
686 _listener(listener),
687 _method(methodPtr),
688 _sender(sender)
689 {
690 }
691
692 virtual TfType GetNoticeType() const {
693 return _noticeType;
694 }
695
696 void _InvokeListenerMethod(ListenerType *listener,
697 const NoticeType &notice,
698 const TfType &noticeType,
699 const TfWeakBase *sender,
700 const void *senderUniqueId,
701 const std::type_info &senderType)
702 {
703 (listener->*_method)(notice, noticeType,
704 const_cast<TfWeakBase *>(sender),
705 senderUniqueId, senderType);
706 }
707
708 TfType _noticeType;
709 LPtr _listener;
710 MethodPtr _method;
711 TfAnyWeakPtr _sender;
712 };
713
714 template <class LPtr, class SPtr, class Method, class Notice>
715 class _DelivererWithSender :
716 public _StandardDeliverer<
717 _DelivererWithSender<LPtr, SPtr, Method, Notice>
718 >
719 {
720 public:
721 typedef Notice NoticeType;
722 typedef Method MethodPtr;
723 typedef typename LPtr::DataType ListenerType;
724
725 typedef typename SPtr::DataType SenderType;
726
727 _DelivererWithSender(LPtr const &listener,
728 MethodPtr const &methodPtr,
729 SPtr const &sender,
730 TfType const &noticeType = TfType())
731 : _listener(listener),
732 _sender(sender),
733 _method(methodPtr)
734 {
735 }
736
737 void _InvokeListenerMethod(ListenerType *listener,
738 const NoticeType &notice,
739 const TfType &noticeType,
740 const TfWeakBase *sender,
741 const void *,
742 const std::type_info &)
743 {
744 SenderType *deliveredSender =
745 static_cast<SenderType *>(const_cast<TfWeakBase *>(sender));
746 SPtr deliveredSPtr(deliveredSender);
747 (listener->*_method)(notice, deliveredSPtr);
748 }
749
750 LPtr _listener;
751 SPtr _sender;
752 MethodPtr _method;
753 };
754
755private:
756 // Internal non-templated function to install listeners.
757 TF_API
758 static Key _Register(_DelivererBase*);
759
760 TF_API
761 static void _VerifyFailedCast(const std::type_info& toType,
762 const TfNotice& notice,
763 const TfNotice* castNotice);
764
765 TF_API
766 size_t _Send(const TfWeakBase* sender,
767 const void *senderUniqueId,
768 const std::type_info & senderType) const;
769 TF_API
770 size_t _SendWithType(const TfType & noticeType,
771 const TfWeakBase* sender,
772 const void *senderUniqueId,
773 const std::type_info & senderType) const;
774
775 friend class Tf_NoticeRegistry;
776
777 // Befriend the wrapping so it can access _SendWithType() directly
778 // in order to provide dynamic downcasting of Python notice types.
779 friend class Tf_PyNotice;
780};
781
782template <typename SenderPtr>
783size_t
784TfNotice::Send(SenderPtr const &s) const
785{
786 const TfWeakBase *senderWeakBase = s ? s.GetWeakBase() : NULL;
787 return _Send(senderWeakBase, senderWeakBase ? s.GetUniqueIdentifier() : 0,
788 senderWeakBase ?
789 typeid(typename SenderPtr::DataType) : typeid(void));
790}
791
792PXR_NAMESPACE_CLOSE_SCOPE
793
794#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:54
Blocks sending of all notices in current thread.
Definition: notice.h:453
Handle-object returned by TfNotice::Register().
Definition: notice.h:256
bool IsValid() const
Does this key refer to a valid notification?
Definition: notice.h:264
Probe interface class which may be implemented and then registered via InsertProbe to introspect abou...
Definition: notice.h:218
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:93
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:361
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:289
TfType represents a dynamic runtime type.
Definition: type.h:65
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:388
Enable a concrete base class for use with TfWeakPtr.
Definition: weakBase.h:141
Pointer storage with deletion detection.
Definition: weakPtr.h:145
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:108
Compiler hints.
Pointer storage with deletion detection.