home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / UI / IdleList.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  11.5 KB  |  440 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        IdleList.cpp
  3.  
  4.     Contains:    IdleList and IdleListIterator classes.
  5.  
  6.     Owned by:    Christopher Linn
  7.  
  8.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <2>     6/14/96    CSL        1257735: Can't register for idle time
  13.                                     during idle time
  14.          <7>     5/26/95    RR        #1251403: Multithreading naming support
  15.          <6>     5/25/95    jpa        List.h --> LinkList.h [1253324]
  16.          <5>      4/4/95    RR        #1220104 Use if IsEqual , # 1228161
  17.                                     RegisterIdle updates frequency if called
  18.                                     twice
  19.          <4>     1/31/95    RR        # 1206909 Rewrote AddIdle/RemoveIdle to
  20.                                     allow unregister while idling, and
  21.                                     immediate unregister/reregister
  22.          <3>     9/30/94    RR        #1167950 Allow unregistering while idling.
  23.                                     Unregistering simply flags items, and
  24.                                     RemoveUnregisteredIdlers removes them
  25.          <2>     9/20/94    RR        #1154046 Moved ref counting from Dispatcher
  26.                                     into IdleList methods so that an
  27.                                     unregistered part is not released.
  28.          <1>     5/13/94    RR        first checked in
  29.          <4>      2/7/94    NP        Tiger Team doings.
  30.          <3>    12/20/93    RR        interface takes part/frame pairs rather
  31.                                     than frames
  32.          <2>     12/3/93    TÇ        Stop including ODError.h, it is included
  33.                                     as ErrorDef.h inside Except.h
  34.          <1>    11/16/93    RR        first checked in
  35.  
  36.     To Do:
  37.     In Progress:
  38. */
  39.  
  40. #ifndef _IDLELIST_
  41. #include "IdleList.h"
  42. #endif
  43.  
  44. #ifndef _LINKLIST_
  45. #include <LinkList.h>
  46. #endif
  47.  
  48. #ifndef _FRAME_
  49. #include "Frame.xh"
  50. #endif
  51.  
  52. #ifndef _PART_
  53. #include "Part.xh"
  54. #endif
  55.  
  56. #ifndef _EXCEPT_
  57. #include "Except.h"
  58. #endif
  59.  
  60. #pragma segment IdleList
  61.  
  62. const ODSLong kMaxLong = 2147483647;
  63. const ODTicks kMaxIdleFrequency = kMaxLong;
  64.  
  65. inline long Max(long a, long b)
  66. {
  67.     return a > b ? a : b;
  68. }
  69.  
  70. inline long Min( long a, long b )
  71. {
  72.     return a < b ? a : b;
  73. }
  74.  
  75. //======================================================================================
  76. // Class IdleInfo
  77. //======================================================================================
  78.  
  79. IdleInfo::IdleInfo(ODPart* part, ODFrame* frame, ODIdleFrequency frequency)
  80. {
  81.     fPart = part;
  82.     fFrame = frame;
  83.     fIdleFrequency = frequency;
  84.     fLastIdle = 0;
  85.     fRemove = kODFalse;
  86. }
  87.  
  88. IdleInfo::~IdleInfo()
  89. {
  90. }
  91.  
  92. ODBoolean IdleInfo::NeedsIdle(ODTicks ticks)
  93. {
  94.     return ( !fRemove && ((ticks - fLastIdle) >= fIdleFrequency));
  95. }
  96.  
  97. ODTicks IdleInfo::NextIdle(ODTicks ticks)
  98. {
  99.     if (fLastIdle == 0)
  100.         return 0;
  101.     else
  102.         return Max(fLastIdle + fIdleFrequency - ticks, 0);
  103. }
  104.  
  105.  
  106. //======================================================================================
  107. // Class IdleList
  108. //======================================================================================
  109.  
  110. IdleList::IdleList()
  111.     : fIteratorCount( 0 ),
  112.       fMinIdleFrequency( kMaxIdleFrequency ),
  113.       fMinIdleIsInvalid( kODFalse )
  114. {
  115. }
  116.  
  117. IdleList::~IdleList()
  118. {
  119.     fImplementation.DeleteAllLinks();
  120.     fDeferredAddedIdlers.DeleteAllLinks();
  121. }
  122.  
  123. //-------------------------------------------------------------------------------------
  124. // IdleList::AddIdle                
  125. //
  126. // Description
  127. //-------------------------------------------------------------------------------------
  128.  
  129. void IdleList::AddIdle(Environment* ev, ODPart* part, ODFrame* frame, ODIdleFrequency frequency) 
  130. {
  131.     IdleInfo* idler = kODNULL;
  132.     
  133.     if ( this->FindIdler( ev, part, frame, &idler ))
  134.     {
  135.         // If it's already there, update the frequency in case it's different
  136.         this->SetIdleFrequency( ev, part, frame, frequency );
  137.     }
  138.     else
  139.     {
  140.         // Not found, make a new idler and add it to the list
  141.         idler = new IdleInfo(part, frame, frequency);        
  142.         if (idler)
  143.         {
  144.             if ( fIteratorCount > 0 )
  145.                 // Iterators are active, add it to the deferred list
  146.                 fDeferredAddedIdlers.AddLast(idler);
  147.             else
  148.                 // Safe to add to the active list
  149.                 fImplementation.AddLast(idler);
  150.  
  151.             // Aquire references to part & frame
  152.             // These get released in RemoveIdle()
  153.             part->Acquire(ev);
  154.             if (frame)
  155.                 frame->Acquire(ev);
  156.                 
  157.             fMinIdleFrequency = Min( fMinIdleFrequency, frequency );
  158.         }
  159.         else
  160.             THROW(kODErrOutOfMemory);    
  161.     }
  162. }
  163.     
  164. //-------------------------------------------------------------------------------------
  165. // IdleList::RemoveIdle                
  166. //
  167. // Description
  168. //-------------------------------------------------------------------------------------
  169.  
  170. void IdleList::RemoveIdle(Environment* ev, ODPart* part, ODFrame* frame)
  171. {
  172.     
  173.     IdleInfo* idler = kODNULL;
  174.     
  175.     if ( this->FindIdler( ev, part, frame, &idler ))
  176.     {
  177.         if ( fMinIdleFrequency == idler->GetIdleFrequency())
  178.             fMinIdleIsInvalid = kODTrue;
  179.  
  180.         if ( fIteratorCount > 0 )
  181.         {
  182.             // To allow removal while idling, we just flag
  183.             // "removed" items here.
  184.             // They are cleared by RemoveDeferredIdlers
  185.             idler->SetShouldRemove(kODTrue);
  186.         }
  187.         else
  188.         {
  189.             // No iterators are active, ok to delete
  190.             fImplementation.Remove( *idler );
  191.             delete idler;
  192.         }
  193.  
  194.         part->Release(ev);
  195.         if (frame)
  196.             frame->Release(ev);        
  197.     }
  198. }
  199.  
  200. //-------------------------------------------------------------------------------------
  201. // IdleList::RemoveDeferredIdlers                
  202. //
  203. // Description
  204. //-------------------------------------------------------------------------------------
  205.  
  206. void IdleList::RemoveDeferredIdlers()
  207. {
  208.     // Note that this method does not remove flagged idlers from
  209.     // the deferred added list.  Thus, you should call AddDeferredIdlers
  210.     // before calling this method in case there are any idlers on the
  211.     // deferred list that are also flagged for removal.  Unlikely, but
  212.     // certainly possible.
  213.     WASSERT( fIteratorCount == 0 );
  214.  
  215.     LinkedListIterator iter(&fImplementation);
  216.  
  217.     for (IdleInfo* link = (IdleInfo*) iter.First();iter.IsNotComplete(); link = (IdleInfo*) iter.Next())
  218.     {
  219.         if (link->ShouldRemove())
  220.         {
  221.             iter.RemoveCurrent();
  222.             delete link;
  223.         }
  224.     }
  225. }
  226.  
  227. //-------------------------------------------------------------------------------------
  228. // IdleList::SetIdleFrequency                
  229. //
  230. // Description
  231. //-------------------------------------------------------------------------------------
  232.  
  233. void IdleList::SetIdleFrequency(Environment* ev, ODPart* part, ODFrame* frame, ODIdleFrequency frequency) 
  234. {
  235.     IdleInfo* idler = kODNULL;
  236.     
  237.     if ( this->FindIdler( ev, part, frame, &idler ))
  238.     {
  239.         // Update the min idle frequency as needed
  240.         if ( fMinIdleFrequency == idler->GetIdleFrequency() && frequency > fMinIdleFrequency )
  241.             fMinIdleIsInvalid = kODTrue;
  242.         else
  243.             fMinIdleFrequency = Min( fMinIdleFrequency, frequency );
  244.  
  245.         // Save the idler's new frequency
  246.         idler->SetIdleFrequency(frequency);
  247.         idler->SetLastIdle(0);
  248.     }
  249. }
  250.  
  251.  
  252. //-------------------------------------------------------------------------------------
  253. // IdleList::IterationBegin                
  254. //
  255. // Description
  256. //-------------------------------------------------------------------------------------
  257.  
  258. void IdleList::IterationBegin()
  259. {
  260.     ++fIteratorCount;
  261. }
  262.  
  263. //-------------------------------------------------------------------------------------
  264. // IdleList::IterationEnd                
  265. //
  266. // Description
  267. //-------------------------------------------------------------------------------------
  268.  
  269. void IdleList::IterationEnd()
  270. {
  271.     WASSERT( fIteratorCount > 0 );
  272.  
  273.     if ( --fIteratorCount == 0 )
  274.     {
  275.         // No idlers are currently active, so it's now safe to
  276.         // add and delete idlers that were deferred.
  277.         this->AddDeferredIdlers();
  278.         this->RemoveDeferredIdlers();
  279.     }
  280. }
  281.  
  282.  
  283. //-------------------------------------------------------------------------------------
  284. // IdleList::FindIdler                
  285. //
  286. // Description
  287. //-------------------------------------------------------------------------------------
  288.  
  289. ODBoolean IdleList::FindIdler(Environment* ev, ODPart* part, ODFrame* frame, IdleInfo** idler)
  290. {
  291.     LinkedListIterator iter(&fImplementation);
  292.     ODBoolean wasFound = kODFalse;
  293.  
  294.     for (IdleInfo* link = (IdleInfo*) iter.First();iter.IsNotComplete(); link = (IdleInfo*) iter.Next())
  295.     {
  296.         // Skip links that are flagged for removal, because their references have been 
  297.         // Released, and there may not have been time to clear the flagged links,
  298.         // eg. during Revert
  299.         wasFound = !link->ShouldRemove() 
  300.                     && ODObjectsAreEqual(ev, link->GetFrame(), frame) 
  301.                     && ODObjectsAreEqual(ev, link->GetPart(), part);
  302.         if (wasFound)
  303.         {
  304.             *idler = link;
  305.             break;    
  306.         }
  307.     }
  308.     
  309.     if ( !wasFound )
  310.     {
  311.         // Continue searching, this time in the list of idlers that have been added during
  312.         // iteration.
  313.         LinkedListIterator iter(&fDeferredAddedIdlers);
  314.  
  315.         for (IdleInfo* link = (IdleInfo*) iter.First();iter.IsNotComplete(); link = (IdleInfo*) iter.Next())
  316.         {
  317.             // Skip links that are flagged for removal, because their references have been 
  318.             // Released, and there may not have been time to clear the flagged links,
  319.             // eg. during Revert
  320.             wasFound = !link->ShouldRemove() 
  321.                         && ODObjectsAreEqual(ev, link->GetFrame(), frame) 
  322.                         && ODObjectsAreEqual(ev, link->GetPart(), part);
  323.             if (wasFound)
  324.             {
  325.                 *idler = link;
  326.                 break;    
  327.             }
  328.         }
  329.     }    
  330.     
  331.     return wasFound;
  332. }
  333.  
  334. //-------------------------------------------------------------------------------------
  335. // IdleList::AddDeferredIdlers
  336. //
  337. // Description
  338. //-------------------------------------------------------------------------------------
  339.  
  340. void IdleList::AddDeferredIdlers()
  341. {
  342.     WASSERT( fIteratorCount == 0 );
  343.     
  344.     LinkedListIterator iter( &fDeferredAddedIdlers );
  345.     
  346.     for (IdleInfo* link = (IdleInfo*) iter.First();iter.IsNotComplete(); link = (IdleInfo*) iter.Next())
  347.     {
  348.         iter.RemoveCurrent();
  349.         fImplementation.AddLast( link );
  350.     }
  351. }
  352.  
  353.  
  354. //-------------------------------------------------------------------------------------
  355. // IdleList::GetMinIdleFrequency
  356. //
  357. // Description
  358. //-------------------------------------------------------------------------------------
  359.  
  360. ODIdleFrequency IdleList::GetMinIdleFrequency()
  361. {
  362.     if ( fMinIdleIsInvalid )
  363.     {
  364.         LinkedListIterator iter( &fImplementation );
  365.         
  366.         fMinIdleFrequency = kMaxIdleFrequency;
  367.         for (IdleInfo* link = (IdleInfo*) iter.First();iter.IsNotComplete(); link = (IdleInfo*) iter.Next())
  368.         {
  369.             if ( !link->ShouldRemove())
  370.                 fMinIdleFrequency = Min( fMinIdleFrequency, link->GetIdleFrequency());
  371.         }
  372.         fMinIdleIsInvalid = kODFalse;
  373.     }
  374.  
  375.     return fMinIdleFrequency;
  376. }
  377.  
  378.  
  379. //=====================================================================================
  380. // IdleListIterator Methods
  381. //=====================================================================================
  382.  
  383. //-------------------------------------------------------------------------------------
  384. // IdleListIterator::IdleListIterator                
  385. //
  386. // Description
  387. //-------------------------------------------------------------------------------------
  388.  
  389. IdleListIterator::IdleListIterator(IdleList* idleList)
  390.     : fIterator(&(idleList->fImplementation))
  391. {
  392.     fIdleList = idleList;
  393.     fIdleList->IterationBegin();
  394. }
  395.  
  396. //-------------------------------------------------------------------------------------
  397. // IdleListIterator::~IdleListIterator                
  398. //
  399. // Description
  400. //-------------------------------------------------------------------------------------
  401.  
  402. IdleListIterator::~IdleListIterator()
  403. {
  404.     fIdleList->IterationEnd();
  405. }
  406.  
  407. //-------------------------------------------------------------------------------------
  408. // IdleListIterator::First                
  409. //
  410. // Description
  411. //-------------------------------------------------------------------------------------
  412.     
  413. IdleInfo* IdleListIterator::First()
  414. {
  415.     return (IdleInfo*) fIterator.First();
  416. }
  417.  
  418. //-------------------------------------------------------------------------------------
  419. // IdleListIterator::Next                
  420. //
  421. // Description
  422. //-------------------------------------------------------------------------------------
  423.  
  424. IdleInfo* IdleListIterator::Next()
  425. {
  426.     return (IdleInfo*) fIterator.Next();
  427. }
  428.  
  429. //-------------------------------------------------------------------------------------
  430. // IdleListIterator::IsNotComplete                
  431. //
  432. // Description
  433. //-------------------------------------------------------------------------------------
  434.  
  435. ODBoolean IdleListIterator::IsNotComplete()
  436. {
  437.     return fIterator.IsNotComplete();
  438. }
  439.  
  440.