home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / Found / FWExcLib / Sources / FWNewHel.cpp < prev    next >
Encoding:
Text File  |  1995-11-08  |  11.7 KB  |  371 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWNewHel.cpp
  4. //    Release Version:    $ 1.0d11 $
  5. //
  6. //    Copyright:    (c) 1993, 1995 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFound.hpp"
  11.  
  12. #ifndef FWNEWHEL_H
  13. #include "FWNewHel.h"
  14. #endif
  15.  
  16. #ifndef FWEXCDEF_H
  17. #include "FWExcDef.h"
  18. #endif
  19.  
  20. #ifndef   FWPRIMEM_H
  21. #include "FWPriMem.h"
  22. #endif
  23.  
  24. #ifdef FW_USE_NEW_HELPER
  25.  
  26. #if FW_LIB_EXPORT_PRAGMAS
  27. #pragma lib_export on
  28. #endif
  29.  
  30. #ifdef FW_BUILD_MAC
  31. #pragma segment BEL
  32. #endif
  33.  
  34. //========================================================================================
  35. //    CLASS FW_CPrivSubHelper
  36. //========================================================================================
  37.  
  38. void FW_CPrivSubHelper::InitializeStorageArray(FW_SPrivExceptionGlobals& globals,
  39.                                                 FW_CPrivSubHelper*array, int size)
  40. {
  41.     for (int i=0; i<size-1; i++)
  42.     {
  43.         array[i].fSiblings = array+i+1;
  44. #ifdef FW_DEBUG
  45.         array[i].fSubObject = 0;
  46.         array[i].fSubObjectSize = 0;
  47.         array[i].fSubObjectVTable = 0;
  48. #endif
  49.     }
  50.     array[size-1].fSiblings = NULL;
  51.     globals.gSubHelperFreeListHead = array;
  52. }
  53.  
  54. //----------------------------------------------------------------------------------------
  55. //    FW_CPrivSubHelper::operator new
  56. //----------------------------------------------------------------------------------------
  57.  
  58. void* FW_CPrivSubHelper::operator new(size_t size)
  59. {
  60. FW_UNUSED(size);
  61.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  62.     FW_CPrivSubHelper* head = globals.gSubHelperFreeListHead;
  63.     FW_PRIV_ASSERT(head != NULL);
  64.     globals.gSubHelperFreeListHead = head->fSiblings;
  65.     return (void*) head;
  66. }
  67.  
  68. //----------------------------------------------------------------------------------------
  69. //    FW_CPrivSubHelper::operator delete
  70. //----------------------------------------------------------------------------------------
  71.  
  72. void  FW_CPrivSubHelper::operator delete(void* object)
  73. {
  74.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  75.     FW_CPrivSubHelper* subHelper = (FW_CPrivSubHelper*) object;
  76.     FW_CPrivSubHelper* head = globals.gSubHelperFreeListHead;
  77.     subHelper->fSiblings = head;
  78. #ifdef FW_DEBUG
  79.     subHelper->fSubObject = 0;
  80.     subHelper->fSubObjectSize = 0;
  81.     subHelper->fSubObjectVTable = 0;
  82. #endif
  83.     globals.gSubHelperFreeListHead = subHelper;
  84. }
  85.  
  86. //----------------------------------------------------------------------------------------
  87. //    FW_CPrivSubHelper::FW_CPrivSubHelper
  88. //----------------------------------------------------------------------------------------
  89.  
  90. FW_CPrivSubHelper::FW_CPrivSubHelper(_FW_CAutoDestructObject *subObject, 
  91.                                        size_t subObjectSize,
  92.                                        FW_CPrivSubHelper *nextSubHelper)
  93. {
  94.     fSubObject = subObject;
  95.     fSubObjectSize = subObjectSize;
  96.     fSubObjectVTable = *(void**)subObject;
  97.     fSiblings = nextSubHelper;
  98. }
  99.  
  100. //----------------------------------------------------------------------------------------
  101. //    FW_CPrivSubHelper::~FW_CPrivSubHelper
  102. //----------------------------------------------------------------------------------------
  103.  
  104. FW_CPrivSubHelper::~FW_CPrivSubHelper()
  105. {
  106. }
  107.  
  108. //========================================================================================
  109. //    CLASS FW_CPrivNewHelper
  110. //========================================================================================
  111.  
  112. //----------------------------------------------------------------------------------------
  113. //    FW_CPrivNewHelper::Initialize
  114. //----------------------------------------------------------------------------------------
  115.  
  116. void FW_CPrivNewHelper::Initialize(FW_SPrivExceptionGlobals& globals)
  117. {
  118.     globals.gNewHelperStackBottom = (FW_CPrivNewHelper **) 
  119.                             ::FW_PrimitiveAllocateBlock(kNewHelperStackSize);
  120.  
  121.     globals.gNewHelperStackTop = globals.gNewHelperStackBottom;
  122.     
  123.     globals.gSubHelperStorageArray = (FW_CPrivSubHelper *) 
  124.                             ::FW_PrimitiveAllocateBlock(kSubHelperArrayByteSize);
  125.  
  126.     FW_CPrivSubHelper::InitializeStorageArray(globals,
  127.                             globals.gSubHelperStorageArray,
  128.                             kSubHelperArraySize);
  129. }
  130.     
  131. //----------------------------------------------------------------------------------------
  132. //    FW_CPrivNewHelper::Terminate
  133. //----------------------------------------------------------------------------------------
  134.  
  135. void FW_CPrivNewHelper::Terminate()
  136. {
  137.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  138.     ::FW_PrimitiveFreeBlock(globals.gSubHelperStorageArray);
  139.     ::FW_PrimitiveFreeBlock(globals.gNewHelperStackBottom);
  140. }
  141.  
  142. //----------------------------------------------------------------------------------------
  143. //    FW_CPrivNewHelper::FW_CPrivNewHelper
  144. //----------------------------------------------------------------------------------------
  145.  
  146. FW_CPrivNewHelper::FW_CPrivNewHelper(__FW_OperatorNewHandler newHandler,
  147.                                       __FW_OperatorDeleteHandler deleteHandler) :
  148.     fWatchedObject(0),
  149.     fObjectVTable(0),
  150.     fWatchedSize(0),
  151.     fSubHelperList(0),
  152.     fNewHandler(newHandler),
  153.     fDeleteHandler(deleteHandler)
  154. {
  155.     PushNewHelper();
  156.     FW_END_CONSTRUCTOR
  157. }
  158.  
  159. //----------------------------------------------------------------------------------------
  160. //    FW_CPrivNewHelper::~FW_CPrivNewHelper
  161. //----------------------------------------------------------------------------------------
  162.  
  163. FW_CPrivNewHelper::~FW_CPrivNewHelper()
  164. {
  165.     FW_START_DESTRUCTOR
  166.     if (fWatchedObject != 0)
  167.     {
  168.         DeleteWatchedObject();
  169.         FW_CPrivNewHelper *temp = FW_CPrivNewHelper::PopNewHelper();
  170.         FW_PRIV_ASSERT(temp == this);
  171.     }
  172.     else
  173.     {
  174.         FW_PRIV_ASSERT(fSubHelperList == 0);
  175.     }
  176. }
  177.  
  178. //----------------------------------------------------------------------------------------
  179. //    FW_CPrivNewHelper::DeleteWatchedObject
  180. //----------------------------------------------------------------------------------------
  181.  
  182. void FW_CPrivNewHelper::DeleteWatchedObject()
  183. {
  184.     FW_CPrivSubHelper    *next = fSubHelperList;
  185.     while (next != NULL)
  186.     {
  187.         _FW_CAutoDestructObject *subObject = next->fSubObject;
  188.         *(void**)subObject = next->fSubObjectVTable;
  189.         subObject->__Delete();
  190.  
  191.         // Save next->fSiblings before deleting next! (see operator delete)
  192.         FW_CPrivSubHelper    *temp = next;
  193.         next = next->fSiblings;
  194.         delete temp;
  195.     }
  196.     if (fObjectVTable != 0)
  197.     {
  198.         *(void**)fWatchedObject = fObjectVTable;
  199.         fWatchedObject->__Delete();
  200.     }
  201.     _FW_CAutoDestructObject::operator delete((void*) fWatchedObject);
  202. }
  203.  
  204. //----------------------------------------------------------------------------------------
  205. //    FW_CPrivNewHelper::WatchObject
  206. //
  207. //        This method is not really const, 
  208. //        but it reduces unnecessary warnings to declare it so.
  209. //----------------------------------------------------------------------------------------
  210.  
  211. _FW_CAutoDestructObject * FW_CPrivNewHelper::WatchObject(
  212.                                 _FW_CAutoDestructObject *watchedObject,
  213.                                 size_t watchedSize) const
  214. {
  215.     FW_CPrivNewHelper *self = (FW_CPrivNewHelper *) this;
  216.     _FW_CAutoDestructObject *previous = fWatchedObject;
  217.     self->fWatchedObject = watchedObject;
  218.     self->fWatchedSize = watchedSize;
  219.     return previous;
  220. }
  221.  
  222. //----------------------------------------------------------------------------------------
  223. //    FW_CPrivNewHelper::ForgetObject
  224. //
  225. //        This method is not really const, 
  226. //        but it reduces unnecessary warnings to declare it so.
  227. //----------------------------------------------------------------------------------------
  228.  
  229. _FW_CAutoDestructObject * FW_CPrivNewHelper::ForgetObject() const
  230. {
  231.     FW_CPrivNewHelper *self = (FW_CPrivNewHelper *) this;
  232.     _FW_CAutoDestructObject *previous = fWatchedObject;
  233.     self->fWatchedObject = 0;
  234.     FW_PRIV_ASSERT(fSubHelperList == 0);
  235.     return previous;
  236. }
  237.  
  238. //----------------------------------------------------------------------------------------
  239. //    FW_CPrivNewHelper::PopNewHelper
  240. //----------------------------------------------------------------------------------------
  241.  
  242. FW_CPrivNewHelper* FW_CPrivNewHelper::PopNewHelper()
  243. {
  244.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  245.     FW_CPrivNewHelper** top = globals.gNewHelperStackTop;
  246. #ifdef FW_DEBUG
  247.     FW_CPrivNewHelper** bottom = globals.gNewHelperStackBottom;
  248.     FW_PRIV_ASSERT(top > bottom);
  249. #endif
  250.     FW_CPrivNewHelper*    helper = *--top;
  251.     globals.gNewHelperStackTop = top;
  252.     return helper;
  253. }
  254.  
  255. //----------------------------------------------------------------------------------------
  256. //    FW_CPrivNewHelper::TopNewHelper
  257. //----------------------------------------------------------------------------------------
  258.  
  259. FW_CPrivNewHelper* FW_CPrivNewHelper::TopNewHelper()
  260. {
  261.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  262.     FW_CPrivNewHelper** top = globals.gNewHelperStackTop;
  263.     FW_CPrivNewHelper** bottom = globals.gNewHelperStackBottom;
  264.     FW_CPrivNewHelper*    helper = 0;
  265.     if (top > bottom)
  266.         helper = top[-1];
  267.     return helper;
  268. }
  269.  
  270. //----------------------------------------------------------------------------------------
  271. //    FW_CPrivNewHelper::PushNewHelper
  272. //----------------------------------------------------------------------------------------
  273.  
  274. void FW_CPrivNewHelper::PushNewHelper()
  275. {
  276.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  277.     FW_CPrivNewHelper** top = globals.gNewHelperStackTop;
  278. #ifdef FW_DEBUG
  279.     FW_CPrivNewHelper** bottom = globals.gNewHelperStackBottom;
  280.     FW_PRIV_ASSERT(top < bottom + kMaxNewHelperStackItems);
  281. #endif
  282.     *top++ = this;
  283.     globals.gNewHelperStackTop = top;
  284. }
  285.  
  286. //----------------------------------------------------------------------------------------
  287. //    FW_CPrivSubHelper::InList
  288. //----------------------------------------------------------------------------------------
  289.  
  290. FW_CPrivSubHelper* FW_CPrivNewHelper::InList(_FW_CAutoDestructObject *subObject)
  291. {
  292.     FW_CPrivSubHelper *next = fSubHelperList;
  293.     while (next != NULL)
  294.     {
  295.         if (next->fSubObject == subObject)
  296.             break;
  297.         next = next->fSiblings;
  298.     }
  299.     return next;
  300. }
  301.  
  302. //----------------------------------------------------------------------------------------
  303. //    FW_CPrivNewHelper::UpdateForEndConstructor
  304. //----------------------------------------------------------------------------------------
  305.  
  306. void FW_CPrivNewHelper::UpdateForEndConstructor(_FW_CAutoDestructObject *object, size_t size)
  307. {
  308.     if (object == fWatchedObject)
  309.     {
  310.         // Object is the object that was FW_NEWed.
  311.         // Update the helper's copy of the vtbl pointer.
  312.         fObjectVTable = *(void**)fWatchedObject;
  313.         FW_PRIV_ASSERT(fObjectVTable != 0);
  314.     }
  315.     else
  316.     {
  317.         // Object must be a subobject of the object that was FW_NEWed.
  318.         FW_PRIV_ASSERT(IsSubObject(object, fWatchedObject, fWatchedSize));
  319.         
  320.         // Is this subobject already attached, partially constructed?
  321.         FW_CPrivSubHelper* subHelper = InList(object);
  322.         if (subHelper==NULL)
  323.         {
  324.             // No, create a new helper to track this subobject
  325.             fSubHelperList = new FW_CPrivSubHelper(object, size, fSubHelperList);
  326.         }
  327.         else
  328.         {
  329.             // Yes, update its vtable
  330.             subHelper->fSubObjectVTable = *(void**)object;
  331.             FW_PRIV_ASSERT(subHelper->fSubObjectVTable != 0);
  332.         }
  333.     }
  334.         
  335.     // Now, release any nested subobjects of this object
  336.     // First, remove from head of list, updating fSubHelperList
  337.     while (fSubHelperList != NULL && IsSubObject(fSubHelperList->fSubObject, object, size))
  338.     {
  339.         // Save fSubHelperList->fSiblings before deleting fSubHelperList!
  340.         FW_CPrivSubHelper *temp = fSubHelperList;
  341.         fSubHelperList = fSubHelperList->fSiblings;
  342.         delete temp;
  343.     }
  344.     
  345.     // Second, remove from internal to list, with fSubHelperList frozen
  346.     if (fSubHelperList != NULL)
  347.     {
  348.         FW_PRIV_ASSERT(!IsSubObject(fSubHelperList->fSubObject, object, size));
  349.         FW_CPrivSubHelper* prev = fSubHelperList;
  350.         FW_CPrivSubHelper* next = prev->fSiblings;
  351.         while (next!=NULL)
  352.         {
  353.             if (IsSubObject(next->fSubObject, object, size))
  354.             {
  355.                 // unlink & delete next.
  356.                 prev->fSiblings = next->fSiblings;
  357.                 delete next;
  358.                 next = prev->fSiblings;
  359.             }
  360.             else
  361.             {
  362.                 // advance prev to next
  363.                 prev = next;
  364.                 next = prev->fSiblings;
  365.             }
  366.         }
  367.     }
  368. }
  369.  
  370. #endif // FW_USE_NEW_HELPER
  371.