home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / threads.zip / iasyntfy.cpp < prev    next >
Text File  |  1995-11-11  |  10KB  |  273 lines

  1. /*******************************************************************************
  2. * FILE NAME: iasyntfy.cpp
  3. *
  4. * DESCRIPTION:
  5. *   Functions to implement the class(es):
  6. *     IAsyncNotifier
  7. *
  8. * COPYRIGHT:
  9. *   Licensed Materials - Property of IBM
  10. *   (C) Copyright IBM Corporation 1995
  11. *   All Rights Reserved
  12. *   US Government Users Restricted Rights - Use, duplication, or disclosure
  13. *   restricted by GSA ADP Schedule Contract with IBM Corp.
  14. *
  15. *******************************************************************************/
  16. #include <iasyntfy.hpp>
  17.  
  18. #ifndef _IASYNTHR_
  19.   #include <iasynthr.hpp>
  20. #endif
  21.  
  22. #ifndef _INOTIFEV_
  23.   #include <inotifev.hpp>
  24. #endif
  25.  
  26. #ifndef _ITHREAD_
  27.   #include <ithread.hpp>
  28. #endif
  29.  
  30. #ifndef _IEVNTSEM_
  31.   #include <ievntsem.hpp>
  32. #endif
  33.  
  34. #ifndef _IKEYSET_H
  35.   #include <ikeyset.h>
  36. #endif
  37.  
  38. // Define the functions and static data members to be exported.
  39. // Ordinals 200 through 249 are reserved for use by IAsyncNotifier.
  40. #pragma export(IAsyncNotifier::IAsyncNotifier(),, 200)
  41. #pragma export(IAsyncNotifier::IAsyncNotifier(const IAsyncNotifier&),, 201)
  42. #pragma export(IAsyncNotifier::~IAsyncNotifier(),, 202)
  43. #pragma export(IAsyncNotifier::deleteThis(),, 203)
  44. #pragma export(IAsyncNotifier::operator=(const IAsyncNotifier&),, 204)
  45. #pragma export(IAsyncNotifier::run(),, 205)
  46. #pragma export(IAsyncNotifier::notifyObservers(const INotificationEvent&),, 206)
  47. #pragma export(IAsyncNotifier::dispatchThread() const,, 207)
  48. #pragma export(IAsyncNotifier::notificationCleanUp(                    \
  49.                  const INotificationEvent&) const,, 208)
  50. #pragma export(IAsyncNotifier::notifyObservers(const INotificationId&),, 209)
  51. #pragma export(IAsyncNotifier::dispatchThreadId,, 210)
  52. // *********** TEMPORARY *************
  53. #pragma export(IAsyncNotifier::thisRefId,, 211)
  54.  
  55. // It's possible for the caller of the external entry points to have a
  56. // different C library environment.  Make sure the exception handler for
  57. // our library environment is registered on entry and deregistered on exit.
  58. #pragma handler(IAsyncNotifier::IAsyncNotifier())
  59. #pragma handler(IAsyncNotifier::IAsyncNotifier(const IAsyncNotifier&))
  60. #pragma handler(IAsyncNotifier::~IAsyncNotifier())
  61. #pragma handler(IAsyncNotifier::deleteThis())
  62. #pragma handler(IAsyncNotifier::operator=(const IAsyncNotifier&))
  63. #pragma handler(IAsyncNotifier::run())
  64. #pragma handler(IAsyncNotifier::notifyObservers(const INotificationEvent&))
  65. #pragma handler(IAsyncNotifier::dispatchThread() const)
  66. #pragma handler(IAsyncNotifier::notificationCleanUp(                   \
  67.                   const INotificationEvent&) const)
  68. #pragma handler(IAsyncNotifier::notifyObservers(const INotificationId&))
  69.  
  70. // Initialize class static members.
  71. IKeySet<IAsyncNotifierThread *, IThreadId> * IAsyncNotifier::threads
  72.                                = new IKeySet<IAsyncNotifierThread *, IThreadId>;
  73. IPrivateResource IAsyncNotifier::threadsKey;
  74. INotificationId const IAsyncNotifier::dispatchThreadId
  75.                                         = "IAsyncNotifier::dispatchThread";
  76. // *********** TEMPORARY *************
  77. INotificationId const IAsyncNotifier::thisRefId = "IAsyncNotifier::thisRef";
  78.  
  79.  
  80. /*------------------------------------------------------------------------------
  81. | Function Name: IAsyncNotifier :: IAsyncNotifier
  82. |
  83. | Implementation:
  84. |   Initialize the base class then find or create the dispatch thread.
  85. |-----------------------------------------------------------------------------*/
  86. IAsyncNotifier :: IAsyncNotifier ( ) :
  87.                    IStandardNotifier ( ),
  88.                    theDispatchThread ( NULL )
  89. {
  90.   findOrCreateDispatchThread();
  91. }
  92.  
  93. /*------------------------------------------------------------------------------
  94. | Function Name: IAsyncNotifier :: IAsyncNotifier
  95. |
  96. | Implementation:
  97. |   Initialize the base class then find or create the dispatch thread.
  98. |   Use the base class default constructor so notification will always be
  99. |   disabled for a new object.
  100. |-----------------------------------------------------------------------------*/
  101. IAsyncNotifier :: IAsyncNotifier ( const IAsyncNotifier & asyncNotifier ) :
  102.                    IStandardNotifier ( ),
  103.                    theDispatchThread ( NULL )
  104. {
  105.   findOrCreateDispatchThread();
  106. }
  107.  
  108. /*------------------------------------------------------------------------------
  109. | Function Name: IAsyncNotifier :: ~IAsyncNotifier
  110. |
  111. | Implementation:
  112. |   Delete all pending notifications for this object.
  113. |   Remove our reference to the thread.
  114. |   If the reference count is zero, remove the thread from the collection.
  115. |     If it is not running, delete it.  If it is running,
  116. |     IAsyncNotifier::run will delete it.
  117. |-----------------------------------------------------------------------------*/
  118. IAsyncNotifier :: ~IAsyncNotifier ( )
  119. {
  120.   theDispatchThread->deleteNotificationsFor ( *this );
  121.   if ( theDispatchThread->removeRef() == 0 )
  122.   {
  123.     threads->removeElementWithKey ( theDispatchThread->threadId() );
  124.  
  125.     if ( ! ( theDispatchThread->isRunning() ) )
  126.       delete theDispatchThread;
  127.   }
  128. }
  129.  
  130. /*------------------------------------------------------------------------------
  131. | Function Name: IAsyncNotifier :: deleteThis
  132. |
  133. | Implementation:
  134. |   Post our secret notification for async delete.
  135. |-----------------------------------------------------------------------------*/
  136. IAsyncNotifier & IAsyncNotifier :: deleteThis ( )
  137. {
  138.   theDispatchThread->enqueueNotification ( INotificationEvent (
  139.                                              IAsyncNotifierThread::deleteThisId,
  140.                                              *this ) );
  141.   return *this;
  142. }
  143.  
  144. /*------------------------------------------------------------------------------
  145. | Function Name: IAsyncNotifier :: operator =
  146. |
  147. | Implementation:
  148. |   Currently, there is nothing to do here.
  149. |   Do not change the dispatch thread.
  150. |   Do not call IStandardNotifier::operator=.  It kills notification.
  151. |-----------------------------------------------------------------------------*/
  152. IAsyncNotifier & IAsyncNotifier :: operator = ( const IAsyncNotifier & rhs )
  153. {
  154.   return *this;
  155. }
  156.  
  157. /*------------------------------------------------------------------------------
  158. | Function Name: IAsyncNotifier :: run
  159. |
  160. | Implementation:
  161. |   Find the current thread in the list of threads.
  162. |   If not found try to create one, but only for GUI.
  163. |   Call the thread's run function.
  164. |   Remove the thread from the collection and delete it.
  165. |-----------------------------------------------------------------------------*/
  166. void IAsyncNotifier :: run ( )
  167. {
  168.   IAsyncNotifierThread * anAsyncNotifierThread = NULL;
  169.   IThreadId threadId = IThread::currentId();
  170.  
  171.   {
  172.     IResourceLock threadsLock ( threadsKey );
  173.  
  174.     if ( threads->containsElementWithKey ( threadId ) )
  175.     {
  176.       anAsyncNotifierThread = threads->elementWithKey ( threadId );
  177.     }
  178.     else
  179.     {
  180.       anAsyncNotifierThread = IAsyncNotifierThread::make ( true );
  181.       threads->add ( anAsyncNotifierThread );
  182.     }
  183.   }
  184.  
  185.   anAsyncNotifierThread->processMsgs();
  186.  
  187.   threads->removeElementWithKey ( threadId );
  188.   delete anAsyncNotifierThread;
  189. }
  190.  
  191. /*------------------------------------------------------------------------------
  192. | Function Name: IAsyncNotifier :: notifyObservers
  193. |
  194. | Implementation:
  195. |   If enabled for notification, enqueue the event.
  196. |-----------------------------------------------------------------------------*/
  197. IAsyncNotifier & IAsyncNotifier :: notifyObservers (
  198.                                      const INotificationEvent & anEvent )
  199. {
  200.   if ( isEnabledForNotification() )
  201.     theDispatchThread->enqueueNotification ( anEvent );
  202.  
  203.   return *this;
  204. }
  205.  
  206. /*------------------------------------------------------------------------------
  207. | Function Name: IAsyncNotifier :: dispatchThread
  208. |
  209. | Implementation:
  210. |   Return the dispatch thread for this object.
  211. |-----------------------------------------------------------------------------*/
  212. const IThreadId & IAsyncNotifier :: dispatchThread ( ) const
  213. {
  214.   return ( theDispatchThread->threadId() );
  215. }
  216.  
  217. /*------------------------------------------------------------------------------
  218. | Function Name: IAsyncNotifier :: notificationCleanUp
  219. |
  220. | Implementation:
  221. |   This default implementation does nothing.
  222. |-----------------------------------------------------------------------------*/
  223. const IAsyncNotifier & IAsyncNotifier :: notificationCleanUp (
  224.                          const INotificationEvent & anEvent ) const
  225. {
  226.   return *this;
  227. }
  228.  
  229. /*------------------------------------------------------------------------------
  230. | Function Name: IAsyncNotifier :: notifyObservers
  231. |
  232. | Implementation:
  233. |   If enabled for notification, create an event and enqueue.
  234. |-----------------------------------------------------------------------------*/
  235. IAsyncNotifier & IAsyncNotifier :: notifyObservers (
  236.                                      const INotificationId & nId )
  237. {
  238.   if ( isEnabledForNotification() )
  239.   {
  240.     INotificationEvent anEvent ( nId, *this );
  241.     theDispatchThread->enqueueNotification ( anEvent );
  242.   }
  243.  
  244.   return *this;
  245. }
  246.  
  247. /*------------------------------------------------------------------------------
  248. | Function Name: IAsyncNotifier :: findOrCreateDispatchThread
  249. |
  250. | Implementation:
  251. |   Find or create the dispatch thread.
  252. |-----------------------------------------------------------------------------*/
  253. IAsyncNotifier & IAsyncNotifier :: findOrCreateDispatchThread ( )
  254. {
  255.   IThreadId threadId = IThread::currentId();
  256.  
  257.   IResourceLock threadsLock ( threadsKey );
  258.  
  259.   if ( threads->containsElementWithKey ( threadId ) )
  260.   {
  261.     theDispatchThread = threads->elementWithKey ( threadId );
  262.   }
  263.   else
  264.   {
  265.     theDispatchThread = IAsyncNotifierThread::make();
  266.     threads->add ( theDispatchThread );
  267.   }
  268.  
  269.   theDispatchThread->addRef();
  270.  
  271.   return *this;
  272. }
  273.