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  static void InsertProbe(const WeakProbePtr &probe);
295 
296  /// Remove a probe that was previously registered with \c InsertProbe.
297  /// \see TfNotice::Probe
298  static void RemoveProbe(const WeakProbePtr &probe);
299 
300  /// Register a listener as being interested in a \c TfNotice.
301  ///
302  /// Registration of interest in a notice class \c N automatically
303  /// registers interest in all classes derived from \c N. When a notice of
304  /// appropriate type is received, the listening object's member-function
305  /// \p method is called with the notice.
306  ///
307  /// Supports several forms of registration.
308  ///
309  /// - Listening for a notice from a particular sender.
310  ///
311  /// \code
312  /// // Listener does not receive sender.
313  /// void Listener::_HandleNotice(SomeNotice const &notice) [const];
314  /// Register(listenerPtr, &Listener::_HandleNotice, senderPtr);
315  ///
316  /// // Listener receives sender.
317  /// void Listener::_HandleNoticeSender(SomeNotice const &notice,
318  /// SenderPtr const &sender) [const];
319  /// Register(listenerPtr, &Listener::_HandleNoticeSender, senderPtr);
320  /// \endcode
321  ///
322  /// - Listening for a notice globally. Prefer listening to a notice from a
323  /// particular sender whenever possible (as above).
324  ///
325  /// \code
326  /// void Listener::_HandleGlobalNotice(SomeNotice const &notice) [const];
327  /// Register(listenerPtr, &Listener::_HandleGlobalNotice);
328  /// \endcode
329  ///
330  /// - Listening for a notice dynamically, with a type that is unknown at
331  /// compile-time. This facility is used for some internal mechanisms,
332  /// such as bridging notice delivery into Python, and is not meant for
333  /// public consumption.
334  ///
335  /// \code
336  /// void Listener::_HandleGenericNotice(TfNotice const &notice,
337  /// TfType const &noticeType,
338  /// TfWeakBase *sender,
339  /// void const *senderUniqueId,
340  /// std::type_info const &senderType)
341  /// [const];
342  /// Register(listenerPtr,
343  /// &Listener::_HandleGenericNotice, noticeType, senderPtr);
344  /// \endcode
345  ///
346  /// The listener being registered must be pointed to by a \c
347  /// TfWeakPtrFacade, like a TfWeakPtr or another TfWeakPtrFacade-based
348  /// Handle. The sender being registered for (if any) must also be pointed
349  /// to by a \c TfWeakPtrFacade.
350  ///
351  /// Note that the notification center only holds onto the listening object
352  /// via a \c TfWeakPtr. That is, it does not influence the lifetime of
353  /// that object.
354  ///
355  /// To reverse the registration, call \c Key::Revoke() on the \c Key
356  /// object returned by this call.
357  template <class LPtr, class MethodPtr>
358  static TfNotice::Key
359  Register(LPtr const &listener, MethodPtr method) {
360  return _Register(_MakeDeliverer(listener, method));
361  }
362 
363  template <class LPtr, class MethodPtr, class SenderPtr>
364  static TfNotice::Key
365  Register(LPtr const &listener, MethodPtr method, SenderPtr const &sender) {
366  return _Register(_MakeDeliverer(listener, method, sender));
367  }
368 
369  template <class LPtr, class MethodPtr>
370  static TfNotice::Key
371  Register(LPtr const &listener, MethodPtr method,
372  const TfType &noticeType, const TfAnyWeakPtr &sender) {
373  return _Register(_MakeDeliverer(noticeType, listener, method, sender));
374  }
375 
376  /// Revoke interest by a listener.
377  ///
378  /// This revokes interest by the listener for the particular notice type
379  /// and call-back method for which this key was created.
380  ///
381  /// \c Revoke will return a bool value indicating whether or not the key
382  /// was successfully revoked. Subsequent calls to \c Revoke with the same
383  /// key will return false.
384  TF_API
385  static bool Revoke(TfNotice::Key& key);
386 
387  /// Revoke interest by listeners.
388  ///
389  /// This revokes interest by the listeners for the particular
390  /// notice types and call-back methods for which the keys were
391  /// created. It then clears the keys container.
392  TF_API
393  static void Revoke(TfNotice::Keys* keys);
394 
395  /// Deliver the notice to interested listeners, returning the number
396  /// of interested listeners.
397  ///
398  /// For most clients it is recommended to use the Send(sender) version of
399  /// Send() rather than this one. Clients that use this form of Send
400  /// will prevent listeners from being able to register to receive notices
401  /// based on the sender of the notice.
402  ///
403  /// ONLY listeners that registered globally will get the notice.
404  ///
405  /// Listeners are invoked synchronously and in arbitrary order. The value
406  /// returned is the total number of times the notice was sent to listeners.
407  /// Note that a listener is called in the thread in which \c Send() is called
408  /// and \e not necessarily in the thread that \c Register() was called in.
409  TF_API
410  size_t Send() const;
411 
412  /// Deliver the notice to interested listeners, returning the number of
413  /// interested listeners.
414  ///
415  /// This is the recommended form of Send. It takes the sender as an
416  /// argument.
417  ///
418  /// Listeners that registered for the given sender AND listeners that
419  /// registered globally will get the notice.
420  ///
421  /// Listeners are invoked synchronously and in arbitrary order. The value
422  /// returned is the total number of times the notice was sent to
423  /// listeners. Note that a listener is called in the thread in which \c
424  /// Send() is called and \e not necessarily in the thread that \c
425  /// Register() was called in.
426  template <typename SenderPtr>
427  size_t Send(SenderPtr const &s) const;
428 
429  /// Variant of Send() that takes a specific sender in the form of a
430  /// TfWeakBase pointer and a typeid.
431  ///
432  /// This version is used by senders who don't have static knowledge of
433  /// sender's type, but have access to its weak base pointer and its
434  /// typeid.
435  TF_API
436  size_t SendWithWeakBase(const TfWeakBase *senderWeakBase,
437  const void *senderUniqueId,
438  const std::type_info &type) const;
439 
440  TF_API
441  virtual ~TfNotice();
442 
443  /// Blocks sending of all notices in current thread.
444  ///
445  /// \note This is intended to be temporary and should NOT be used.
446  ///
447  /// While one or more \c TfNotice::Block is instantiated, any call to \c
448  /// TfNotice::Send in the current thread will be silently ignored. This
449  /// will continue until all \c TfNotice::Block objects are destroyed.
450  /// Notices that are sent when blocking is active will *not* be resent.
451  class Block {
452  public:
453  TF_API Block();
454  TF_API ~Block();
455  };
456 
457 private:
458  // Abstract base class for calling listeners.
459  // A typed-version derives (via templating) off this class.
460  class _DelivererBase : public TfWeakBase {
461  public:
462  _DelivererBase()
463  : _list(0), _active(true), _markedForRemoval(false)
464  {
465  }
466 
467  TF_API
468  virtual ~_DelivererBase();
469 
470  TF_API
471  void _BeginDelivery(const TfNotice &notice,
472  const TfWeakBase *sender,
473  const std::type_info &senderType,
474  const TfWeakBase *listener,
475  const std::type_info &listenerType,
476  const std::vector<TfNotice::WeakProbePtr> &probes);
477 
478  TF_API
479  void _EndDelivery(const std::vector<TfNotice::WeakProbePtr> &probes);
480 
481  // The derived class converts n to the proper type and delivers it by
482  // calling the listener's method. The function returns \c true,
483  // unless the listener has expired or been marked in active (i.e. by
484  // TfNotice::Revoke()), in which case the method call is skipped and
485  // \c false is returned.
486  virtual bool
487  _SendToListener(const TfNotice &n,
488  const TfType &type,
489  const TfWeakBase *s,
490  const void *senderUniqueId,
491  const std::type_info &senderType,
492  const std::vector<TfNotice::WeakProbePtr> &probes) = 0;
493 
494  void _Deactivate() {
495  _active = false;
496  }
497 
498  bool _IsActive() const {
499  return _active;
500  }
501 
502  void _MarkForRemoval() {
503  _markedForRemoval = true;
504  }
505 
506  // True if the entry has been added to the _deadEntries list for
507  // removal. Used to avoid adding it more than once to the list.
508  bool _IsMarkedForRemoval() const {
509  return _markedForRemoval;
510  }
511 
512  virtual TfType GetNoticeType() const = 0;
513 
514  virtual bool Delivers(TfType const &noticeType,
515  const TfWeakBase *sender) const = 0;
516 
517  virtual TfWeakBase const *GetSenderWeakBase() const = 0;
518 
519  virtual _DelivererBase *Clone() const = 0;
520 
521  protected:
522 
523  template <class ToNoticeType, class FromNoticeType>
524  static inline ToNoticeType const *
525  _CastNotice(FromNoticeType const *from) {
526  // Dynamic casting in deliverers is significant overhead, so only
527  // do error checking in debug builds.
528  if (TF_DEV_BUILD) {
529  if (!dynamic_cast<ToNoticeType const *>(from)) {
530  ToNoticeType const *castNotice =
531  TfSafeDynamic_cast<ToNoticeType const *>(from);
532  // this will abort with a clear error message if
533  // castNotice is NULL
534  TfNotice::_VerifyFailedCast(typeid(ToNoticeType),
535  *from, castNotice);
536  }
537  }
538  return static_cast<ToNoticeType const *>(from);
539  }
540 
541  private:
542  // Linkage to the containing _DelivererList in the Tf_NoticeRegistry
543  _DelivererList *_list;
544  _DelivererList::iterator _listIter;
545 
546  bool _active;
547  bool _markedForRemoval;
548 
549  friend class Tf_NoticeRegistry;
550  };
551 
552  template <class Derived>
553  class _StandardDeliverer : public _DelivererBase {
554  public:
555  virtual ~_StandardDeliverer() {}
556 
557  virtual TfType GetNoticeType() const {
558  typedef typename Derived::NoticeType NoticeType;
559  TfType ret = TfType::Find<NoticeType>();
560  if (ret.IsUnknown())
561  TF_FATAL_ERROR("notice type " + ArchGetDemangled<NoticeType>() +
562  " undefined in the TfType system");
563  return ret;
564  }
565 
566  virtual bool Delivers(TfType const &noticeType,
567  TfWeakBase const *sender) const {
568  Derived const *derived = this->AsDerived();
569  return noticeType.IsA(GetNoticeType()) &&
570  !derived->_sender.IsInvalid() &&
571  sender && derived->_sender.GetWeakBase() == sender;
572  }
573 
574  virtual TfWeakBase const *GetSenderWeakBase() const {
575  Derived const *derived = this->AsDerived();
576  return derived->_sender ? derived->_sender.GetWeakBase() : 0;
577  }
578 
579  virtual _DelivererBase *Clone() const {
580  Derived const *derived = this->AsDerived();
581  return new Derived(derived->_listener,
582  derived->_method,
583  derived->_sender,
584  GetNoticeType());
585  }
586 
587  virtual bool
588  _SendToListener(const TfNotice &notice,
589  const TfType &noticeType,
590  const TfWeakBase *sender,
591  const void *senderUniqueId,
592  const std::type_info &senderType,
593  const std::vector<TfNotice::WeakProbePtr> &probes)
594  {
595  Derived *derived = this->AsDerived();
596  typedef typename Derived::ListenerType ListenerType;
597  typedef typename Derived::NoticeType NoticeType;
598  ListenerType *listener = get_pointer(derived->_listener);
599 
600  if (listener && !derived->_sender.IsInvalid()) {
601  if (ARCH_UNLIKELY(!probes.empty())) {
602  TfWeakBase const *senderWeakBase = GetSenderWeakBase(),
603  *listenerWeakBase = derived->_listener.GetWeakBase();
604  _BeginDelivery(notice, senderWeakBase,
605  senderWeakBase ?
606  senderType : typeid(void),
607  listenerWeakBase,
608  typeid(ListenerType), probes);
609  }
610 
611  derived->
612  _InvokeListenerMethod(listener,
613  *_CastNotice<NoticeType>(&notice),
614  noticeType, sender,
615  senderUniqueId, senderType);
616 
617  if (ARCH_UNLIKELY(!probes.empty()))
618  _EndDelivery(probes);
619 
620  return true;
621  }
622  return false;
623  }
624 
625  private:
626  Derived *AsDerived() {
627  return static_cast<Derived *>(this);
628  }
629 
630  Derived const *AsDerived() const {
631  return static_cast<Derived const *>(this);
632  }
633  };
634 
635 
636  template <typename LPtr, typename SPtr, typename Method, typename Notice>
637  class _Deliverer :
638  public _StandardDeliverer<_Deliverer<LPtr, SPtr, Method, Notice> >
639  {
640  public:
641  typedef Notice NoticeType;
642  typedef typename LPtr::DataType ListenerType;
643  typedef Method MethodPtr;
644 
645  _Deliverer(LPtr const &listener,
646  MethodPtr const &methodPtr,
647  SPtr const &sender = SPtr(),
648  TfType const &noticeType = TfType())
649  : _listener(listener)
650  , _sender(sender)
651  , _method(methodPtr)
652  {
653  }
654 
655  void _InvokeListenerMethod(ListenerType *listener,
656  const NoticeType &notice,
657  const TfType &noticeType,
658  const TfWeakBase *,
659  const void *,
660  const std::type_info &)
661  {
662  (listener->*_method)(notice);
663  }
664 
665  LPtr _listener;
666  SPtr _sender;
667  MethodPtr _method;
668  };
669 
670  template <class LPtr, class Method>
671  class _RawDeliverer :
672  public _StandardDeliverer<_RawDeliverer<LPtr, Method> >
673  {
674  public:
675  typedef TfNotice NoticeType;
676  typedef typename LPtr::DataType ListenerType;
677  typedef Method MethodPtr;
678 
679  _RawDeliverer(LPtr const &listener,
680  MethodPtr const &methodPtr,
681  TfAnyWeakPtr const &sender,
682  TfType const &noticeType)
683  : _noticeType(noticeType),
684  _listener(listener),
685  _method(methodPtr),
686  _sender(sender)
687  {
688  }
689 
690  virtual TfType GetNoticeType() const {
691  return _noticeType;
692  }
693 
694  void _InvokeListenerMethod(ListenerType *listener,
695  const NoticeType &notice,
696  const TfType &noticeType,
697  const TfWeakBase *sender,
698  const void *senderUniqueId,
699  const std::type_info &senderType)
700  {
701  (listener->*_method)(notice, noticeType,
702  const_cast<TfWeakBase *>(sender),
703  senderUniqueId, senderType);
704  }
705 
706  TfType _noticeType;
707  LPtr _listener;
708  MethodPtr _method;
709  TfAnyWeakPtr _sender;
710  };
711 
712  template <class LPtr, class SPtr, class Method, class Notice>
713  class _DelivererWithSender :
714  public _StandardDeliverer<
715  _DelivererWithSender<LPtr, SPtr, Method, Notice>
716  >
717  {
718  public:
719  typedef Notice NoticeType;
720  typedef Method MethodPtr;
721  typedef typename LPtr::DataType ListenerType;
722 
723  typedef typename SPtr::DataType SenderType;
724 
725  _DelivererWithSender(LPtr const &listener,
726  MethodPtr const &methodPtr,
727  SPtr const &sender,
728  TfType const &noticeType = TfType())
729  : _listener(listener),
730  _sender(sender),
731  _method(methodPtr)
732  {
733  }
734 
735  void _InvokeListenerMethod(ListenerType *listener,
736  const NoticeType &notice,
737  const TfType &noticeType,
738  const TfWeakBase *sender,
739  const void *,
740  const std::type_info &)
741  {
742  SenderType *deliveredSender =
743  static_cast<SenderType *>(const_cast<TfWeakBase *>(sender));
744  SPtr deliveredSPtr(deliveredSender);
745  (listener->*_method)(notice, deliveredSPtr);
746  }
747 
748  LPtr _listener;
749  SPtr _sender;
750  MethodPtr _method;
751  };
752 
753 private:
754  // Internal non-templated function to install listeners.
755  TF_API
756  static Key _Register(_DelivererBase*);
757 
758  TF_API
759  static void _VerifyFailedCast(const std::type_info& toType,
760  const TfNotice& notice,
761  const TfNotice* castNotice);
762 
763  TF_API
764  size_t _Send(const TfWeakBase* sender,
765  const void *senderUniqueId,
766  const std::type_info & senderType) const;
767  TF_API
768  size_t _SendWithType(const TfType & noticeType,
769  const TfWeakBase* sender,
770  const void *senderUniqueId,
771  const std::type_info & senderType) const;
772 
773  friend class Tf_NoticeRegistry;
774 
775  // Befriend the wrapping so it can access _SendWithType() directly
776  // in order to provide dynamic downcasting of Python notice types.
777  friend class Tf_PyNotice;
778 };
779 
780 template <typename SenderPtr>
781 size_t
782 TfNotice::Send(SenderPtr const &s) const
783 {
784  const TfWeakBase *senderWeakBase = s ? s.GetWeakBase() : NULL;
785  return _Send(senderWeakBase, senderWeakBase ? s.GetUniqueIdentifier() : 0,
786  senderWeakBase ?
787  typeid(typename SenderPtr::DataType) : typeid(void));
788 }
789 
791 
792 #endif // PXR_BASE_TF_NOTICE_H
GLdouble s
Definition: glew.h:1390
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
virtual TF_API ~TfNotice()
static TfNotice::Key Register(LPtr const &listener, MethodPtr method)
Definition: notice.h:359
friend class Tf_NoticeRegistry
Definition: notice.h:773
static void RemoveProbe(const WeakProbePtr &probe)
Y * get_pointer(TfWeakPtrFacade< X, Y > const &p)
Definition: weakPtrFacade.h:86
#define ARCH_UNLIKELY(x)
Definition: hints.h:47
virtual void EndSend()=0
TF_API size_t SendWithWeakBase(const TfWeakBase *senderWeakBase, const void *senderUniqueId, const std::type_info &type) const
static TF_API bool Revoke(TfNotice::Key &key)
void
Definition: png.h:1083
GLsizei n
Definition: glew.h:4040
#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:1274
virtual void EndDelivery()=0
static TfNotice::Key Register(LPtr const &listener, MethodPtr method, const TfType &noticeType, const TfAnyWeakPtr &sender)
Definition: notice.h:371
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1253
friend class Tf_PyNotice
Definition: notice.h:777
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:1346
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
static void InsertProbe(const WeakProbePtr &probe)
static TfNotice::Key Register(LPtr const &listener, MethodPtr method, SenderPtr const &sender)
Definition: notice.h:365
TF_API void const * GetUniqueIdentifier() const