home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 April: Mac OS SDK / Dev.CD Apr 99 SDK1.toast / Development Kits / Apple Shared Library Manager / ASLM Examples / Example Tools / Sources / TPoolNotifierExample.cp < prev    next >
Encoding:
Text File  |  1996-11-19  |  6.6 KB  |  174 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        TPoolNotifierExample.cp
  3.  
  4.     Contains:    This module shows an example use of TStandardPool and TPoolNotifier
  5.                 The Shared Library Manager provides the TPoolNotifier class to assist in
  6.                 automatically “growing” a pool when the pool comes dangerously close to
  7.                 running out of memory. 
  8.  
  9.     Copyright:    © 1993 by Apple Computer, Inc., all rights reserved.
  10.  
  11. */
  12.  
  13. #include "TInitSLM.h"            // the TInitSLM class and SLM include files
  14. #include "TPoolNotifierExample.h"
  15. #include <Desk.h>                // for the SystemTask routine
  16.  
  17. ///————————————————————————————————————————————————————————————————————————————————————
  18. /// CONSTANTS
  19. ///————————————————————————————————————————————————————————————————————————————————————
  20.  
  21. const size_t kBlockSize1 = 500;
  22. const size_t kBlockSize2 = 750;
  23. const size_t kLowLimit = 2000;    // low mark we want to be notified about
  24. const size_t kHiLimit = 2250;    // high mark we want to be notified about
  25.  
  26. ///————————————————————————————————————————————————————————————————————————————————————
  27. ///    PROTOTYPES
  28. ///————————————————————————————————————————————————————————————————————————————————————
  29.  
  30. size_t get_free_bytes( TMemoryPool* thePool );
  31.  
  32.  
  33. /*————————————————————————————————————————————————————————————————————————————————————
  34.     main 
  35.     
  36.     In this example we start by creating a TStandardPool and with the minimum size
  37.     required. We have subclassed the TPoolNotifier so we can intercept the
  38.     calls to Notify and GrowBy routines simply for the sake of displaying a message.
  39.     This notifier is attached to the pool we create so it can be notified when
  40.     it needs to graow.
  41.     
  42.     A number of different things are done to the pool to make it grow, not grow, be
  43.     notified of low and high memory, and sometimes fail to allocate memory. The
  44.     execution of the code is all sequential so just follow the comments as you
  45.     read through the code so you can tell what will happen to the pool and why.
  46.     You may want to run the tool first so you can see what the output looks like.
  47. ————————————————————————————————————————————————————————————————————————————————————*/
  48.  
  49. main()
  50. {    
  51.     TInitSLM initLibraryManager;            // initialize the shared library manager
  52.     
  53.     if( initLibraryManager.Failed() )    // If we failed, let go home.
  54.         return 1;
  55.  
  56.     // Any MPW tool that uses the SLM and calls SystemTask or WaitNextEvent
  57.     // needs to call InitGraf
  58.     InitGraf( (Ptr)&qd.thePort );
  59.         
  60.     TStandardPool *thepool = new (1,kCurrentZone) TStandardPool;
  61.     
  62.     if( thepool ) {                        // make sure we didn't fail
  63.         
  64.         thepool->SetNotifyMarks( kLowLimit, kHiLimit );
  65.                 
  66.         TMyPoolNotifier    *poolnotifier = new TMyPoolNotifier(0, kBlockSize2);
  67.         
  68.         if( poolnotifier ) {            // if poolnotifier succeeded then continue
  69.     
  70.             // attach the notifier to our pool
  71.             thepool->SetNotifier(poolnotifier);
  72.         
  73.             if( thepool->CheckPool() ) { // make sure the pool is ok
  74.         
  75.                 thepool->TracePoolInfo();// show the PoolInfo in TraceMonitor
  76.                 cout << "Current bytes free = " << get_free_bytes(thepool) << "\n\n";
  77.     
  78.     
  79.                 // Make the SLM think we are executing at interrupt time so it won't
  80.                 // try to grow the pool immediately. Instead it will schedule an
  81.                 // operation to grow the pool at system task time. We're just doing
  82.                 // this for the sake of demonstrating what happens if your pool
  83.                 // runs out of memory at interrupt time. Obviously you would only
  84.                 // want to do this in a real interrupt service routine.
  85.                 
  86.                 EnterInterrupt();
  87.                 
  88.                 
  89.                 // Attempt to allocate a block of memory. Since our pool is empty
  90.                 // and the SLM thinks we are at interrupt time, it will fail. But
  91.                 // since we have a notifier attached to the pool it will schedule
  92.                 // an operation to grow the pool later.
  93.                 
  94.                 cout << "About to do allocation of kBlockSize1 for 1st time" << endl;
  95.                 if (thepool->Allocate(kBlockSize1))
  96.                     cout << "Hey, the Allocate was suppose to fail!" << endl;
  97.                 else
  98.                     cout << "The Allocate failed as expected." << endl;
  99.                 cout << "Current bytes free = " << get_free_bytes(thepool) << "\n\n";
  100.                 LeaveInterrupt();    // we're done fooling the SLM
  101.                 
  102.                 
  103.                 // Now call SystemTask so the operation that was scheduled has a
  104.                 // chance to run and grow the pool.
  105.                 
  106.                 cout << "Calling SystemTask() so pool will grow." << endl;
  107.                 SystemTask();
  108.                 cout << "Current bytes free = " << get_free_bytes(thepool) << "\n\n";
  109.                 
  110.                 
  111.                 // Now try allocating the block again. We'll disable the notifer
  112.                 // first because we want to show that it doesn't need to be called
  113.                 
  114.                 thepool->SetNotifier(NULL);
  115.                 cout << "About to do allocation of kBlockSize1 for 2nd time" << endl;
  116.                 if (thepool->Allocate(kBlockSize1))
  117.                     cout << "The Allocate succeeded as expected." << endl;
  118.                 else
  119.                     cout << "Hey, the Allocate was suppose to succeed!" << endl;
  120.                 cout << "Current bytes free = " << get_free_bytes(thepool) << "\n\n";
  121.             
  122.             
  123.                 // Add enough memory so our pool's free memory is just above the low limit
  124.                 // for the notifier. This will cause the notifier to be called next time
  125.                 // we allocate a block because this will put the pool just below the
  126.                 // low limit.
  127.                 
  128.                 cout << "Adding " << kLowLimit+kStandardPoolChunkOverhead;
  129.                 cout << " to the pool." << endl;
  130.                 thepool->AddMemoryToPool(kLowLimit+kStandardPoolChunkOverhead);
  131.                 cout << "Current bytes free = " << get_free_bytes(thepool) << "\n\n";
  132.                 
  133.                 
  134.                 // Now allocate a block of size kBlockSize2. First we re-enable the
  135.                 // pool notifier. It will be called to grow the pool because the
  136.                 // available memory is will fall below the low limit for the notifier
  137.                 
  138.                 thepool->SetNotifier(poolnotifier);    // re-enable our notifier
  139.                 cout << "About to do allocation of kBlockSize2" << endl;
  140.                 void*    theblock;
  141.                 if (theblock = thepool->Allocate(kBlockSize2))
  142.                     cout << "The Allocate succeeded as expected." << endl;
  143.                 else
  144.                     cout << "Hey, the Allocate was suppose to succeed!" << endl;
  145.                 cout << "Current bytes free = " << get_free_bytes(thepool) << "\n\n";
  146.                 
  147.                 
  148.                 // Now we'll free up the block of memory. This should cause our notifier to
  149.                 // be called because the high water mark was reached.
  150.                 
  151.                 cout << "About to free up the block." << endl;
  152.                 if (theblock)
  153.                     delete theblock;
  154.                 cout << "Current bytes free = " << get_free_bytes(thepool) << "\n\n";
  155.             }
  156.         }
  157.         delete thepool;                    // first delete the pool
  158.         delete poolnotifier;            // then the notifier
  159.     }
  160.     return 0;
  161. }
  162.  
  163. /*————————————————————————————————————————————————————————————————————————————————————
  164.     get_free_bytes
  165.     
  166.     find out how many bytes are free in the pool
  167. ————————————————————————————————————————————————————————————————————————————————————*/
  168. size_t get_free_bytes( TMemoryPool* thePool )
  169. {
  170.     PoolInfo info;
  171.     thePool->GetPoolInfo(info);
  172.     return info.fFreeBytes;
  173. }
  174.