Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

85 lines
2.5 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: observer.h
  8. //
  9. //--------------------------------------------------------------------------
  10. #ifndef _OBSERVER_H_
  11. #define _OBSERVER_H_
  12. #include <vector>
  13. // Event source interface template
  14. // Defines event source class for specific observer class
  15. template <class Observer>
  16. class EventSource
  17. {
  18. public:
  19. STDMETHOD(Advise)(Observer* pObserver, LONG_PTR* pCookie) = 0;
  20. STDMETHOD(Unadvise)(LONG_PTR Cookie) = 0;
  21. };
  22. // Event source implementation template
  23. // Defines implementation of event source for a specific observer class
  24. // maintains a vector of the active observers of this event source
  25. template <class Observer>
  26. class ATL_NO_VTABLE EventSourceImpl : EventSource<Observer>
  27. {
  28. typedef std::list<Observer*> ObserverList;
  29. typedef std::list<Observer*>::iterator ObserverIter;
  30. public:
  31. STDMETHOD(Advise)(Observer* pObserver, LONG_PTR* plCookie);
  32. STDMETHOD(Unadvise)(LONG_PTR lCookie);
  33. protected:
  34. ~EventSourceImpl()
  35. {
  36. // verify there are no obervers when going away
  37. ASSERT(m_Observers.empty());
  38. }
  39. ObserverList m_Observers;
  40. };
  41. template <class Observer>
  42. STDMETHODIMP EventSourceImpl<Observer>::Advise(Observer* pObserver, LONG_PTR* plCookie)
  43. {
  44. ASSERT(pObserver != NULL);
  45. ASSERT(plCookie != NULL);
  46. ObserverIter iter = m_Observers.insert(m_Observers.end(), pObserver);
  47. // can't cast iterator to LONG_PTR so check size before cheating
  48. ASSERT(sizeof(ObserverIter) == sizeof(LONG_PTR));
  49. *(ObserverIter*)plCookie = iter;
  50. return S_OK;
  51. }
  52. template <class Observer>
  53. STDMETHODIMP EventSourceImpl<Observer>::Unadvise(LONG_PTR lCookie)
  54. {
  55. // Can't cast LONG_PTR to iterator, so have to cheat
  56. // see Advise method for size check
  57. ObserverIter iter;
  58. *(LONG_PTR*)&iter = lCookie;
  59. m_Observers.erase(iter);
  60. return S_OK;
  61. }
  62. // Observer enumerator helper
  63. // Provides for-loop header for iterating over observers of a specified observer class
  64. #define FOR_EACH_OBSERVER(ObserverClass, ObserverIter) \
  65. for ( \
  66. std::list<ObserverClass*>::iterator ObserverIter = EventSourceImpl<ObserverClass>::m_Observers.begin(); \
  67. ObserverIter != EventSourceImpl<ObserverClass>::m_Observers.end(); \
  68. ++ObserverIter \
  69. )
  70. #endif // _OBSERVER_H_