home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 39 / IOPROG_39.ISO / SOFT / sdkjava40.exe / data1.cab / fg_Samples / Samples / Profiler / heapmon / rootrefs.hpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-04  |  6.1 KB  |  259 lines

  1. // rootrefs.hpp
  2. //
  3. // Created 10/06/98
  4. //
  5. // (C)Copyright 1998-1999 Microsoft Corporation, All rights reserved.
  6. //
  7.  
  8. #ifndef __ROOTREFS_HPP__
  9. #define __ROOTREFS_HPP__
  10.  
  11. #include "ids.hpp"
  12.  
  13.  
  14. class RootReferencesRecorder
  15. {
  16.     struct RootRecord
  17.     {
  18.         ID rootid;
  19.         unsigned nrefs;
  20.         ObjectID refs[1];
  21.     };
  22.  
  23.     struct RecordsPage
  24.     {
  25.         size_t size;
  26.         RecordsPage *next;
  27.         RootRecord records[1];
  28.     };
  29.  
  30.     RecordsPage *pages;
  31.     RootRecord *lastrecord;
  32. #ifdef DEBUG
  33.     unsigned pagecount;
  34. #endif
  35.  
  36. // BUGBUG
  37. #define OS_PAGE_SIZE 4096
  38. #define INITIAL_REFS_PER_PAGE ((OS_PAGE_SIZE-sizeof(RecordsPage)+sizeof(ObjectID))/sizeof(ObjectID))
  39.  
  40.  
  41.     RootRecord *GetNewRootRecord (ID root, unsigned nrefs, ObjectID **pstop)
  42.     {
  43.         RootRecord *rec = NULL;
  44.  
  45.         size_t size = sizeof(RecordsPage)+(nrefs-1)*sizeof(ObjectID);
  46. #ifndef DEBUG
  47.         size = ((size + OS_PAGE_SIZE - 1) & ~(OS_PAGE_SIZE-1));
  48. #endif
  49.         // TODO wastes 15 uncommitted pages
  50.         RecordsPage *newpage = (RecordsPage*)VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
  51.         if (newpage != NULL)
  52.         {
  53.             newpage->size = size;
  54.  
  55.             rec = &newpage->records[0];
  56.             
  57.             rec->rootid = root;
  58.             rec->nrefs = 0;
  59.             
  60.             newpage->next = pages;
  61.             pages = newpage;
  62.  
  63. #ifdef DEBUG
  64.             pagecount++;
  65.             ASSERT(pagecount < 1000);
  66. #endif
  67.  
  68.             lastrecord = rec;
  69.  
  70.             *pstop = (ObjectID*)((BYTE*)newpage+size);
  71.         }
  72.  
  73.         return rec;
  74.     }
  75.  
  76.     RootRecord *GetRootRecord (ID root, ObjectID **pstop)
  77.     {
  78.         if (lastrecord != NULL)
  79.         {
  80.             ObjectID *stop = (ObjectID*)((BYTE*)pages+pages->size);
  81.  
  82.             ASSERT((BYTE*)lastrecord >= (BYTE*)pages && (BYTE*)lastrecord + sizeof(RootRecord) <= (BYTE*)stop);
  83.         
  84.             if (lastrecord->rootid == root)
  85.             {
  86.                 *pstop = stop;
  87.                 return lastrecord;
  88.             }
  89.  
  90.             BYTE *lastend = (BYTE*)&lastrecord->refs[lastrecord->nrefs];
  91.  
  92.             if (lastend + sizeof(RootRecord) < (BYTE*)stop)
  93.             {
  94.                 lastrecord = (RootRecord*)lastend;
  95.                 lastrecord->rootid = root;
  96.                 lastrecord->nrefs = 0;
  97.                 *pstop = stop;
  98.                 return lastrecord;
  99.             }
  100.         }
  101.  
  102.         return GetNewRootRecord(root, INITIAL_REFS_PER_PAGE, pstop);
  103.     }
  104.  
  105.     BOOL RecordReferences (RootRecord *rec, ObjectID *stop, unsigned *pnrefs, const ObjectID **prefs)
  106.     {
  107.         const ObjectID *refs = *prefs;
  108.         unsigned nrefs = *pnrefs;
  109.  
  110.         ObjectID *dest = &rec->refs[rec->nrefs];
  111.  
  112.         unsigned ntocopy = min(nrefs, (unsigned)(stop - dest));
  113.  
  114.         CopyMemory(dest, refs, ntocopy*sizeof(ObjectID));
  115.  
  116.         rec->nrefs += ntocopy;
  117.         *pnrefs = nrefs - ntocopy;
  118.         *prefs = refs + ntocopy;
  119.  
  120.         return TRUE;
  121.     }
  122.  
  123. public:
  124.  
  125.     RootReferencesRecorder ()
  126.     {
  127.         pages = NULL;
  128.         lastrecord = NULL;
  129. #ifdef DEBUG
  130.         pagecount = 0;
  131. #endif
  132.     }
  133.  
  134.     ~RootReferencesRecorder ()
  135.     {
  136.         Reset();
  137.     }
  138.  
  139.     BOOL AddRootReferences (ID root, unsigned nrefs, const ObjectID *refs)
  140.     {
  141.         BOOL result;
  142.  
  143.         ObjectID *stop = NULL;
  144.         RootRecord *rec = GetRootRecord(root, &stop);
  145.         result = (rec != NULL);
  146.         if (result)
  147.         {
  148.             for (;;)
  149.             {
  150.                 result = RecordReferences(rec, stop, &nrefs, &refs);
  151.                 if (!result || !nrefs)
  152.                     break;
  153.  
  154.                 rec = GetNewRootRecord(root, nrefs, &stop);
  155.                 result = (rec != NULL);
  156.                 if (!result)
  157.                     break;
  158.             }
  159.         }
  160.  
  161.         return result;
  162.     }
  163.  
  164.     typedef int IterateProc (ID rootid, ObjectID refid, PVOID token);
  165.  
  166.     int Iterate (IterateProc *cb, PVOID token)
  167.     {
  168.         int result = 1;
  169.     
  170.         RecordsPage *page = pages;
  171.         while (page != NULL)
  172.         {
  173.             RootRecord *rec = &page->records[0];
  174.  
  175.             for (;;)
  176.             {
  177.                 ID rootid = rec->rootid;
  178.                 if (rootid == NULL)
  179.                     break;
  180.  
  181.                 ObjectID *id = &rec->refs[0];
  182.                 ObjectID *stop = id + rec->nrefs;
  183.  
  184.                 while (id < stop)
  185.                 {
  186.                     result = (*cb)(rootid, *id, token);
  187.                     if (result <= 0)
  188.                         break;
  189.                     id++;
  190.                 }
  191.  
  192.                 if ((BYTE*)stop == (BYTE*)page+page->size)
  193.                     break;
  194.                 rec = (RootRecord*)stop;
  195.             }
  196.  
  197.             page = page->next;
  198.         }
  199.  
  200.         return result;
  201.     }
  202.  
  203.     typedef int IterateRootsProc (ID rootid, PVOID token);
  204.  
  205.     int IterateRoots (IterateRootsProc *cb, PVOID token)
  206.     {
  207.         int result = 1;
  208.     
  209.         RecordsPage *page = pages;
  210.         while (page != NULL)
  211.         {
  212.             RootRecord *rec = &page->records[0];
  213.  
  214.             for (;;)
  215.             {
  216.                 ID rootid = rec->rootid;
  217.                 if (rootid == NULL)
  218.                     break;
  219.  
  220.                 ObjectID *id = &rec->refs[0];
  221.                 ObjectID *stop = id + rec->nrefs;
  222.  
  223.                 result = (*cb)(rootid, token);
  224.                 if (result <= 0)
  225.                     break;
  226.  
  227.                 if ((BYTE*)stop == (BYTE*)page+page->size)
  228.                     break;
  229.                 rec = (RootRecord*)stop;
  230.             }
  231.  
  232.             page = page->next;
  233.         }
  234.  
  235.         return result;
  236.     }
  237.  
  238.     VOID Reset ()
  239.     {
  240.         RecordsPage *page = pages;
  241.         while (page != NULL)
  242.         {
  243.             RecordsPage *trash = page;
  244.             page = page->next;
  245.             EVAL(VirtualFree(trash, trash->size, MEM_DECOMMIT));
  246.             EVAL(VirtualFree(trash, 0, MEM_RELEASE));
  247.         }
  248.         pages = NULL;
  249.         lastrecord = NULL;
  250. #ifdef DEBUG
  251.         pagecount = 0;
  252. #endif
  253.     }
  254. };
  255.  
  256.  
  257. #endif /* __ROOTREFS_HPP__ */
  258.  
  259.