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

  1. /*******************************************************************************
  2. * FILE NAME: iasynbkg.cpp
  3. *
  4. * DESCRIPTION:
  5. *   Functions to implement the class(es):
  6. *     IAsyncNotifierBackgroundThread
  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 <iasynbkg.hpp>
  17.  
  18. #ifndef _IASYNTFY_
  19.   #include <iasyntfy.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 _IEXCEPT_
  35.   #include <iexcept.hpp>
  36. #endif
  37.  
  38. #ifndef _ISEQ_H
  39.   #include <iseq.h>
  40. #endif
  41.  
  42.  
  43. /*------------------------------------------------------------------------------
  44. | Function Name: removeFor
  45. |
  46. | Implementation:
  47. |   Used by IAsyncNotifierBackgroundThread::deleteNotificationsFor as a
  48. |   parameter to ISequence<INotificationEvent>::removeAll.
  49. |-----------------------------------------------------------------------------*/
  50. IBoolean removeFor ( const INotificationEvent & anEvent, void * asyncNotifier )
  51. {
  52.   IBoolean remove = false;
  53.  
  54.   if ( (&(anEvent.notifier())) == ((INotifier *)asyncNotifier) )
  55.   {
  56.     remove = true;
  57.     ((const IAsyncNotifier *)asyncNotifier)->notificationCleanUp ( anEvent );
  58.   }
  59.  
  60.   return remove;
  61. }
  62.  
  63. /*------------------------------------------------------------------------------
  64. | Function Name: IAsyncNotifierBackgroundThread :: IAsyncNotifierBackgroundThread
  65. |
  66. | Implementation:
  67. |   Initialize the base class and create our queue.
  68. |-----------------------------------------------------------------------------*/
  69. IAsyncNotifierBackgroundThread :: IAsyncNotifierBackgroundThread ( ) :
  70.                    IAsyncNotifierThread ( ),
  71.                    queue ( new ISequence<INotificationEvent> ),
  72.                    queueKey ( ),
  73.                    queueEventSem ( )
  74. {
  75. }
  76.  
  77. /*------------------------------------------------------------------------------
  78. | Function Name: IAsyncNotifierBackgroundThread :: ~IAsyncNotifierBackgroundThread
  79. |
  80. | Implementation:
  81. |   Delete the queue.
  82. |-----------------------------------------------------------------------------*/
  83. IAsyncNotifierBackgroundThread :: ~IAsyncNotifierBackgroundThread ( )
  84. {
  85.   delete queue;
  86. }
  87.  
  88. /*------------------------------------------------------------------------------
  89. | Function Name: IAsyncNotifierBackgroundThread :: removeRef
  90. |
  91. | Implementation:
  92. |   If the count is now zero and the queue is empty let processMsgs know it
  93. |     is time to exit.
  94. |-----------------------------------------------------------------------------*/
  95. unsigned long IAsyncNotifierBackgroundThread :: removeRef ( )
  96. {
  97.   IResourceLock queueLock ( queueKey );
  98.  
  99.   unsigned long count = IAsyncNotifierThread::removeRef();
  100.   if ( ( count == 0 ) && ( queue->isEmpty() ) )
  101.     queueEventSem.post();
  102.  
  103.   return count;
  104. }
  105.  
  106. /*------------------------------------------------------------------------------
  107. | Function Name: IAsyncNotifierBackgroundThread :: enqueueNotification
  108. |
  109. | Implementation:
  110. |   Enqueue the notification.  The queue will make a copy of the event.
  111. |   If the dispatch thread may be waiting, post the semaphore.
  112. |-----------------------------------------------------------------------------*/
  113. IAsyncNotifierBackgroundThread & IAsyncNotifierBackgroundThread
  114.                                    :: enqueueNotification (
  115.                                         const INotificationEvent & anEvent )
  116. {
  117.   IResourceLock queueLock ( queueKey );
  118.  
  119.   queue->addAsLast ( anEvent );
  120.  
  121.   if ( queue->numberOfElements() == 1 )
  122.     queueEventSem.post();
  123.  
  124.   return *this;
  125. }
  126.  
  127. /*------------------------------------------------------------------------------
  128. | Function Name: IAsyncNotifierBackgroundThread :: processMsgs
  129. |
  130. | Implementation:
  131. |   Lock the queue
  132. |   While there are async notifiers on this thread:
  133. |     If queue is empty:
  134. |       Reset event sem
  135. |       Unlock the queue
  136. |       Wait on the event sem
  137. |       Lock the queue
  138. |     If the queue is not empty
  139. |       Dequeue the next event
  140. |       Unlock the queue
  141. |       Check for deleteThisId and notify observers
  142. |       Lock the queue
  143. |   Unlock the queue
  144. |-----------------------------------------------------------------------------*/
  145. IAsyncNotifierBackgroundThread & IAsyncNotifierBackgroundThread
  146.                                    :: processMsgs ( )
  147. {
  148.   IASSERTSTATE ( threadId() == IThread::currentId() );
  149.  
  150.   setIsRunning ( true );
  151.  
  152.   // Lock the queue
  153.   queueKey.lock();
  154.   IBoolean lockedHere = true;
  155.  
  156.   try
  157.   {
  158.     // While there are async notifiers on this thread:
  159.     while ( refCount() != 0 )
  160.     {
  161.       // If queue is empty:
  162.       if ( queue->isEmpty() )
  163.       {
  164.         // Reset event sem
  165.         queueEventSem.reset();
  166.  
  167.         // Unlock the queue
  168.         queueKey.unlock();
  169.         lockedHere = false;
  170.  
  171.         // Wait on the event sem
  172.         queueEventSem.wait();
  173.  
  174.         // Lock the queue
  175.         queueKey.lock();
  176.         lockedHere = true;
  177.       }
  178.  
  179.       // If the queue is not empty
  180.       if ( ! (queue->isEmpty()) )
  181.       {
  182.         // Dequeue the next event
  183.         INotificationEvent nextEvent ( queue->firstElement() );
  184.         queue->removeFirst();
  185.  
  186.         // Unlock the queue
  187.         queueKey.unlock();
  188.         lockedHere = false;
  189.  
  190.         // Check for deleteThisId and notify observers
  191.         IAsyncNotifier * theNotifier
  192.                            = (IAsyncNotifier *)(&(nextEvent.notifier()));
  193.         if ( nextEvent.notificationId() == deleteThisId )
  194.         {
  195.           delete theNotifier;
  196.         }
  197.         else
  198.         {
  199.           if ( theNotifier->isEnabledForNotification() )
  200.             theNotifier->IStandardNotifier::notifyObservers ( nextEvent );
  201.           theNotifier->notificationCleanUp ( nextEvent );
  202.         }
  203.  
  204.         // Lock the queue
  205.         queueKey.lock();
  206.         lockedHere = true;
  207.       }
  208.     }
  209.   }
  210.   catch ( IException & exc )
  211.   {
  212.     // Unlock the queue and rethrow.
  213.     if ( lockedHere )
  214.       queueKey.unlock();
  215.     throw;
  216.   }
  217.  
  218.   // Unlock the queue
  219.   queueKey.unlock();
  220.  
  221.   setIsRunning ( false );
  222.  
  223.   return *this;
  224. }
  225.  
  226. /*------------------------------------------------------------------------------
  227. | Function Name: IAsyncNotifierBackgroundThread :: deleteNotificationsFor
  228. |
  229. | Implementation:
  230. |   Remove all pending notifications for the passed async notifier.
  231. |-----------------------------------------------------------------------------*/
  232. IAsyncNotifierBackgroundThread & IAsyncNotifierBackgroundThread
  233.                                    :: deleteNotificationsFor (
  234.                                         const IAsyncNotifier & asyncNotifier )
  235. {
  236.   IASSERTSTATE ( threadId() == IThread::currentId() );
  237.  
  238.   IResourceLock queueLock ( queueKey );
  239.  
  240.   queue->removeAll ( removeFor, (void *)(&asyncNotifier) );
  241.  
  242.   return *this;
  243. }
  244.