HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 
27 /// \file tf/notice.h
28 /// \ingroup group_tf_Notification
29 
30 #include "pxr/pxr.h"
31 #include "pxr/base/tf/api.h"
32 #include "pxr/base/tf/anyWeakPtr.h"
33 #include "pxr/base/tf/diagnostic.h"
34 #include "pxr/base/tf/type.h"
35 #include "pxr/base/tf/weakPtr.h"
36 #include "pxr/base/arch/demangle.h"
37 #include "pxr/base/arch/hints.h"
38 
39 #include <list>
40 #include <typeinfo>
41 
43 
44 class Tf_NoticeRegistry;
45 
46 /// \class TfNotice
47 /// \ingroup group_tf_Notification
48 ///
49 /// The base class for objects used to notify interested parties (listeners)
50 /// when events have occurred. The TfNotice class also serves as a container
51 /// for various dispatching routines such as Register() and Send().
52 ///
53 /// See \ref page_tf_Notification in the C++ API reference for a detailed
54 /// description of the notification system.
55 ///
56 /// \section pycode_TfNotice Python Example: Registering For and Sending
57 /// Notices The following code provides examples of how to set up a Notice
58 /// listener connection (represented in Python by the Listener class),
59 /// including creating and sending notices, registering to receive notices,
60 /// and breaking a listener connection.
61 /// \code{.py}
62 /// # To create a new notice type:
63 /// class APythonClass(Tf.Notice):
64 /// '''TfNotice sent when APythonClass does something of interest.'''
65 /// pass
66 /// Tf.Type.Define(APythonClass)
67 ///
68 /// # An interested listener can register to receive notices from all
69 /// # senders, or from a particular type of sender.
70 ///
71 /// # To send a notice to all registered listeners:;
72 /// APythonClass().SendGlobally()
73 ///
74 /// # To send a notice to listeners who register with a specific sender:
75 /// APythonClass().Send(self)
76 ///
77 /// # To register for the notice from any sender:
78 /// my_listener = Tf.Notice.RegisterGlobally(APythonClass, self._HandleNotice)
79 ///
80 /// # To register for the notice from a specific sender
81 /// my_listener = Tf.Notice.Register(APythonClass, self._HandleNotice, sender)
82 ///
83 /// def _HandleNotice(self, notice, sender):
84 /// '''callback function for handling a notice'''
85 /// # do something when the notice arrives
86 ///
87 /// # To revoke interest in a notice
88 /// my_listener.Revoke()
89 /// \endcode
90 ///
91 /// For more on using notices in Python, see the Editor With Notices tutorial.
92 ///
93 class TfNotice {
94 private:
95  class _DelivererBase;
97  typedef std::list<_DelivererBase*> _DelivererList;
98 
99  ////////////////////////////////////////////////////////////////////////
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 
131  ////////////////////////////////////////////////////////////////////////
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 
153  ////////////////////////////////////////////////////////////////////////
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 
173  ////////////////////////////////////////////////////////////////////////
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 
210 public:
211 
212  class Probe;
214 
215  /// Probe interface class which may be implemented and then registered via
216  /// \c InsertProbe to introspect about notices as they are sent and
217  /// delivered.
218  class Probe : public TfWeakBase {
219  public:
220  TF_API
221  virtual ~Probe() = 0;
222 
223  /// This method is called just before \p notice is sent to any
224  /// listeners. \p sender is NULL if \p notice is sent globally. In
225  /// this case, \p senderType will be typeid(void).
226  virtual void BeginSend(const TfNotice &notice,
227  const TfWeakBase *sender,
228  const std::type_info &senderType) = 0;
229 
230  /// This method is called after the notice in the corresponding \c
231  /// BeginSend call has been delivered to all listeners.
232  virtual void EndSend() = 0;
233 
234  /// This method is called just before \p notice is
235  /// delivered to a listener. \p sender is NULL if \p notice is
236  /// sent globally or the listener is global. In this case, \p
237  /// senderType will be typeid(void).
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 
244  /// This method is called after the notice in the
245  /// corresponding \c BeginDelivery call has finished being
246  /// processed by its listener.
247  virtual void EndDelivery() = 0;
248  };
249 
250  /// Handle-object returned by \c TfNotice::Register().
251  ///
252  /// When a listener is registered by \c TfNotice::Register(), an object of
253  /// type \c TfNotice::Key is returned; this key object can be given to \c
254  /// Revoke() to subsequently unregister the listener with respect to that
255  /// particular notice type and callback method.
256  class Key {
257  public:
258  Key() {}
259 
260  /// Does this key refer to a valid notification?
261  ///
262  /// \c IsValid will return true if this key refers to a currently
263  /// active notification. Revoking the key will make it invalid again.
264  bool IsValid() const {
265  return _deliverer && _deliverer->_IsActive();
266  }
267 
268  /// Does this key refer to a valid notification?
269  ///
270  /// The boolean operator is identical to \c IsValid() above.
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 
284  /// A \c TfNotice::Key container.
285  ///
286  /// Many listeners listen for several notices and must revoke interest for
287  /// those several notices at once. These listeners can put all of the
288  /// keys into a \c TfNotice::Keys then call \c Revoke() on it.
289  typedef std::vector<Key> Keys;
290 
291  /// Register a probe that will be invoked when notices are sent and
292  /// delivered.
293  /// \see TfNotice::Probe
294  TF_API
295  static void InsertProbe(const WeakProbePtr &probe);
296 
297  /// Remove a probe that was previously registered with \c InsertProbe.
298  /// \see TfNotice::Probe
299  TF_API
300  static void RemoveProbe(const WeakProbePtr &probe);
301 
302  /// Register a listener as being interested in a \c TfNotice.
303  ///
304  /// Registration of interest in a notice class \c N automatically
305  /// registers interest in all classes derived from \c N. When a notice of
306  /// appropriate type is received, the listening object's member-function
307  /// \p method is called with the notice.
308  ///
309  /// Supports several forms of registration.
310  ///
311  /// - Listening for a notice from a particular sender.
312  ///
313  /// \code
314  /// // Listener does not receive sender.
315  /// void Listener::_HandleNotice(SomeNotice const &notice) [const];
316  /// Register(listenerPtr, &Listener::_HandleNotice, senderPtr);
317  ///
318  /// // Listener receives sender.
319  /// void Listener::_HandleNoticeSender(SomeNotice const &notice,
320  /// SenderPtr const &sender) [const];
321  /// Register(listenerPtr, &Listener::_HandleNoticeSender, senderPtr);
322  /// \endcode
323  ///
324  /// - Listening for a notice globally. Prefer listening to a notice from a
325  /// particular sender whenever possible (as above).
326  ///
327  /// \code
328  /// void Listener::_HandleGlobalNotice(SomeNotice const &notice) [const];
329  /// Register(listenerPtr, &Listener::_HandleGlobalNotice);
330  /// \endcode
331  ///
332  /// - Listening for a notice dynamically, with a type that is unknown at
333  /// compile-time. This facility is used for some internal mechanisms,
334  /// such as bridging notice delivery into Python, and is not meant for
335  /// public consumption.
336  ///
337  /// \code
338  /// void Listener::_HandleGenericNotice(TfNotice const &notice,
339  /// TfType const &noticeType,
340  /// TfWeakBase *sender,
341  /// void const *senderUniqueId,
342  /// std::type_info const &senderType)
343  /// [const];
344  /// Register(listenerPtr,
345  /// &Listener::_HandleGenericNotice, noticeType, senderPtr);
346  /// \endcode
347  ///
348  /// The listener being registered must be pointed to by a \c
349  /// TfWeakPtrFacade, like a TfWeakPtr or another TfWeakPtrFacade-based
350  /// Handle. The sender being registered for (if any) must also be pointed
351  /// to by a \c TfWeakPtrFacade.
352  ///
353  /// Note that the notification center only holds onto the listening object
354  /// via a \c TfWeakPtr. That is, it does not influence the lifetime of
355  /// that object.
356  ///
357  /// To reverse the registration, call \c Key::Revoke() on the \c Key
358  /// object returned by this call.
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 
378  /// Revoke interest by a listener.
379  ///
380  /// This revokes interest by the listener for the particular notice type
381  /// and call-back method for which this key was created.
382  ///
383  /// \c Revoke will return a bool value indicating whether or not the key
384  /// was successfully revoked. Subsequent calls to \c Revoke with the same
385  /// key will return false.
386  TF_API
387  static bool Revoke(TfNotice::Key& key);
388 
389  /// Revoke interest by listeners.
390  ///
391  /// This revokes interest by the listeners for the particular
392  /// notice types and call-back methods for which the keys were
393  /// created. It then clears the keys container.
394  TF_API
395  static void Revoke(TfNotice::Keys* keys);
396 
397  /// Deliver the notice to interested listeners, returning the number
398  /// of interested listeners.
399  ///
400  /// For most clients it is recommended to use the Send(sender) version of
401  /// Send() rather than this one. Clients that use this form of Send
402  /// will prevent listeners from being able to register to receive notices
403  /// based on the sender of the notice.
404  ///
405  /// ONLY listeners that registered globally will get the notice.
406  ///
407  /// Listeners are invoked synchronously and in arbitrary order. The value
408  /// returned is the total number of times the notice was sent to listeners.
409  /// Note that a listener is called in the thread in which \c Send() is called
410  /// and \e not necessarily in the thread that \c Register() was called in.
411  TF_API
412  size_t Send() const;
413 
414  /// Deliver the notice to interested listeners, returning the number of
415  /// interested listeners.
416  ///
417  /// This is the recommended form of Send. It takes the sender as an
418  /// argument.
419  ///
420  /// Listeners that registered for the given sender AND listeners that
421  /// registered globally will get the notice.
422  ///
423  /// Listeners are invoked synchronously and in arbitrary order. The value
424  /// returned is the total number of times the notice was sent to
425  /// listeners. Note that a listener is called in the thread in which \c
426  /// Send() is called and \e not necessarily in the thread that \c
427  /// Register() was called in.
428  template <typename SenderPtr>
429  size_t Send(SenderPtr const &s) const;
430 
431  /// Variant of Send() that takes a specific sender in the form of a
432  /// TfWeakBase pointer and a typeid.
433  ///
434  /// This version is used by senders who don't have static knowledge of
435  /// sender's type, but have access to its weak base pointer and its
436  /// typeid.
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 
445  /// Blocks sending of all notices in current thread.
446  ///
447  /// \note This is intended to be temporary and should NOT be used.
448  ///
449  /// While one or more \c TfNotice::Block is instantiated, any call to \c
450  /// TfNotice::Send in the current thread will be silently ignored. This
451  /// will continue until all \c TfNotice::Block objects are destroyed.
452  /// Notices that are sent when blocking is active will *not* be resent.
453  class Block {
454  public:
455  TF_API Block();
456  TF_API ~Block();
457  };
458 
459 private:
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 
755 private:
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 
782 template <typename SenderPtr>
783 size_t
784 TfNotice::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 
793 
794 #endif // PXR_BASE_TF_NOTICE_H
virtual TF_API ~Probe()=0
virtual void BeginSend(const TfNotice &notice, const TfWeakBase *sender, const std::type_info &senderType)=0
bool IsUnknown() const
Definition: type.h:388
#define TF_API
Definition: api.h:40
void
Definition: png.h:1083
virtual TF_API ~TfNotice()
static TfNotice::Key Register(LPtr const &listener, MethodPtr method)
Definition: notice.h:361
friend class Tf_NoticeRegistry
Definition: notice.h:775
static TF_API void InsertProbe(const WeakProbePtr &probe)
GLdouble s
Definition: glad.h:3009
Y * get_pointer(TfWeakPtrFacade< X, Y > const &p)
Definition: weakPtrFacade.h:83
#define ARCH_UNLIKELY(x)
Definition: hints.h:47
GLdouble n
Definition: glcorearb.h:2008
virtual void EndSend()=0
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)
#define TF_FATAL_ERROR
std::vector< Key > Keys
Definition: notice.h:289
TfRefPtr< typename D::DataType > TfSafeDynamic_cast(const TfRefPtr< T > &ptr)
Definition: refPtr.h:1249
virtual void EndDelivery()=0
static TfNotice::Key Register(LPtr const &listener, MethodPtr method, const TfType &noticeType, const TfAnyWeakPtr &sender)
Definition: notice.h:373
friend class Tf_PyNotice
Definition: notice.h:779
friend class Tf_NoticeRegistry
Definition: notice.h:280
virtual void BeginDelivery(const TfNotice &notice, const TfWeakBase *sender, const std::type_info &senderType, const TfWeakBase *listener, const std::type_info &listenerType)=0
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1432
bool IsValid() const
Definition: notice.h:264
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
Definition: type.h:64
TF_API bool IsA(TfType queryType) const
TF_API size_t Send() const
TfWeakPtr< Probe > WeakProbePtr
Definition: notice.h:212
type
Definition: core.h:1059
static TfNotice::Key Register(LPtr const &listener, MethodPtr method, SenderPtr const &sender)
Definition: notice.h:367
TF_API void const * GetUniqueIdentifier() const