TweetFollow Us on Twitter

Deferred Garbage Collection

Volume Number: 13 (1997)
Issue Number: 12
Column Tag: C++ Workshop

Deferred Garbage Collection

by Marc White

Implementing a simple deferred C++ object garbage collection class

Self Deleting Objects

When developing object oriented software using C++ there are certain situations where you may need an object that can delete itself. For instance, you might have a window or dialog class that manages its own mouse clicks and key down events. But what does the dialog object do when it determines that the user has pressed the escape or delete key, or clicked the window's close box? To stay true to the object oriented design, the window should be able to do whatever processing is needed when it determines that it is being closed and then free up the memory allocated for the object by itself.

Delete This

While the C++ syntax delete this is a legal call, it can cause serious problems if the object that makes the call is referenced in any way after the call is made. This could possibly happen while the stack is unwinding after a mouse click or key down event.

The TGarbageCollector Class

The TGarbageCollector class is a simple, drop in utility class that allows any C++ object to be safely deleted at a later time.

Listing 1: The TGarbageCollector Class

The TGarbageCollector class is a non-instance class with two public static methods: Add, and Empty, and one private static member variable: fTrashCan which is pointer to a TGarbage object.

class TGarbageCollector {
friend class TGarbage;
public:
  static void Add      ( void *trash );
  static void Empty    ( void );
  
private:
  static TGarbage      *fTrashCan;
};

TGarbageCollector::Add

The Add method of the TGarbageCollector class simply instantiates a new TGarbage object passing it a pointer to the C++ object to be deleted. Note that the trash pointer is a void pointer.

void TGarbageCollector::Add( void *trash )
{
  // create a new TGarbage object
  new TGarbage( trash );
}

TGarbageCollector::Empty

The Empty method of the TGarbageCollector class deletes all of the TGarbage objects pointed to by the fTrashCan variable. This method should be called periodically at idle time in the application's main event loop. The TGarbage object's destructor maintains the linked list.

void TGarbageCollector::Empty( void )
{
  // delete all of the items in the trash can
  while( TGarbageCollector::fTrashCan )
    delete( TGarbageCollector::fTrashCan );
}

I developed the TGarbageCollector class as a part of an application framework I was designing. The easiest way to design the garbage collection class would have been to have it delete only objects derived from a specific class, perhaps a TTrashableObject class. But, I wanted the garbage collector to be able to delete any C++ object, and I didn't want to have every class in the framework be derived from a single base class.

The TGarbage Class

This is where the TGarbage class comes in. Because the TGarbage class accepts a void pointer as a pointer to the object it will delete, any pointer can be passed into the garbage collection class to be deleted. This means that it is up to the developer (not the compiler) to make sure that the pointer passed in is a pointer to a valid C++ object.

There is one more catch which I will describe in the What's the Catch section, but for now let's take a look at the TGarbage class.

Listing 2: The TGarbage Class

The TGarbage class is a simple self-linking singly linked list class which accepts a void pointer through its constructor. It stores a pointer to the object to delete in the fTrash variable and a pointer to the next TGarbage object in the list in its fNext variable.

class TGarbage {
public:
            TGarbage    ( void *trash );
  virtual    ~TGarbage  ( void );
private:
  void        *fTrash;
  TGarbage    *fNext;
};

TGarbage::TGarbage

The TGarbage constructor stores a pointer to object to delete in its fTrash variable. Next it links itself into the linked list pointed to by the TGarbageCollector's static fTrashCan variable. It can access this private item since the TGarbageCollector has the declared the TGarbage class as a friend.

TGarbage::TGarbage( void *trash ) : fTrash( trash )
{
  // store a pointer to the next item in the chain
  if( TGarbageCollector::fTrashCan )
    this->fNext = TGarbageCollector::fTrashCan;
  else
    this->fNext = nil;
  
  // set this item as the first item in the trash can
  TGarbageCollector::fTrashCan = this;
}

TGarbage::~TGarbage

This is where the real magic happens. When the TGarbage object gets deleted we have no idea what type of object its fTrash variable points to, all that we know is that it is pointing to a C++ object. So just type cast it to a C++ class pointer (in this case a TGarbage pointer) and call the delete operator. The real object's destructor will get called and its memory will be deallocated. It's just that easy!

TGarbage::~TGarbage( void )
{
  // pull this object out of the linked list
  TGarbageCollector::fTrashCan = this->fNext;
  
  // delete the trash
  delete( (TGarbage *)this->fTrash );
}

Sample Usage

Let's take a look at the TGarbageCollector class in action. Code listing 3 shows the DoKeyDown method of a typical dialog class.

Listing 3: A Dialog Class Method

void FDialog::DoKeyDown( char theKey )
{
  switch( theKey ) {
    case kEscKey:
      // add this object to the trash
      TGarbageCollector::Add( this );
      // hide this dialog
      this->Hide();
      // do any other processing needed here before closing
      break;
    default:
      inherited::DoKeyDown( theKey );
  }
}

Notice that the dialog can add itself to the trash at any time once it determines that it needs to be deleted. The dialog object is still valid until the trash gets collected.

Next we'll take a look at the event loop method of a typical application class. This is where the TGarbageCollector's Empty method gets called and all of the objects added to the trash are deleted.

Listing 4: An Application Class Event Loop Method

void FApplication::EventLoop( void )
{
  EventRecord  theEvent;

  while( this->fQuit == false ) {
    if( WaitNextEvent( everyEvent, &theEvent, 30, nil ) ) {
      switch( theEvent.what ) {
        // handle all normal events here
        default:
          TGarbageCollector::Empty();
          break;
      }
    } else {
      TGarbageCollector::Empty();
    }
  }
}

What's The Catch?

So there has to be a catch, right? Well, of course there is. The catch is that any C++ object added to the trash must be structured in the same way as the object used to type cast the void pointer in the TGarbage object before calling its delete operator.

In simpler terms, any object added to the trash must have a virtual destructor, and its destructor must be the first virtual method of that class. This is because of the way a C++ object is structured from a class.

The TGarbage class typecasts the void pointer to the object it is going to delete into a pointer to a TGarbage object. This instructs the compiler to use the virtual table, or vtbl, of the TGarbage class to find the location of the object's destructor which it calls before deallocating the object's memory.

In the case of the TGarbage class, the destructor is the first virtual method of the class and therefore will be the first entry in the vtbl. As long as any object added to the trash can has its destructor as the first item in the vtbl, it will be properly called when the TGarbage class deletes the object.

What would happen if the object being trashed did not have a virtual destructor, or if the destructor was not the first virtual method? If the object's virtual destructor is not the first virtual method in the class, or it's destructor is not virtual, then before the memory for that object is deallocated the first virtual method of that class will be called. In the case of an object that does not have any virtual methods, the object will not even have a vtbl which means that some random memory location is going be executed as a method. Obviously, neither of these two scenarios are desirable, which is why it is very important that the developer structures the classes for trashable objects properly.

Multiple Inheritance

Can objects that use multiple inheritance be successfully deleted using the TGarbageCollector class? In short, yes, as long as they still adhere to the virtual-destructor-first method like the other classes.

However, there is an exception. Depending upon how the compiler implements multiple inheritance (I am using CodeWarrior for this example), as long as the first class specified in the inheritance chain has a virtual destructor as its first virtual method, the order of the virtual methods of the other superclasses does not matter.

Listing 5: Multiple Inheritance

// destructor is the first virtual method
class A {
public:
              A    ( void );
  virtual      ~A    ( void );
};

// destructor is the second virtual method
class B {
public:
              B    ( void );
  virtual void  Test  ( void );
  virtual      ~B    ( void );
};

// inherit from A first, then B
class C : public A, public B {
public:
              C    ( void );
  virtual      ~C    ( void );
};

// inherit from B first, then A 
class D : public B, public A {
public:
              D    ( void );
  virtual      ~D    ( void );
};

In code listing 5, class A follows the virtual-destructor-first method which would allow any object of class A to be deleted properly by the TGarbageCollector class. Class B, however, has its virtual destructor declared as the second virtual method in the class, and therefore, would not be deleted properly by the TGarbageCollector class. The B object's Test method would actually get called when the TGarbage class deleted it.

Since class C inherits from class A first and class B second, class C objects can successfully be deleted using this method. When the TGarbage class calls the C object's delete operator, the class C destructor will be called first, the class B destructor second, and the A destructor third.

Class D, however, inherits from the B class first, which means that it will behave exactly like a B object would when being deleted by the TGarbageCollector, the inherited B object's Test method will get called.

So, even though there is an exception to the virtual-destructor-first rule in the case of multiple inheritance, it is much safer to make sure that any object that might be deleted by the TGarbageCollector have its virtual destructor declared before any other virtual methods.

Summary

The TGarbageCollector class provides a simple means of adding deferred object deletion to any C++ application. However, the developer must make certain that the classes of objects which will be deleted in this manner are structured according to the virtual-destructor-first rule.


Marc White is a Macintosh programmer at US WEST Dex, Inc., where he develops client/server software used to paginate the US WEST phone directories. He can be reached at mwhite@eagle.mrg.uswest.com.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

FileMaker Pro 19.4.2 - Quickly build cus...
FileMaker Pro is the tool you use to create a custom app. You also use FileMaker Pro to access your app on a computer. Start by importing data from a spreadsheet or using a built-in Starter app to... Read more
Adobe Illustrator 26.0.3 - Professional...
You can download Adobe Illustrator for Mac as a part of Creative Cloud for only $20.99/month. Adobe Illustrator for Mac is the vector graphics classics in the design industry. It is a digital... Read more
WhatRoute 2.4.9 - Geographically trace o...
WhatRoute is designed to find the names of all the routers an IP packet passes through on its way from your Mac to a destination host. It also measures the round-trip time from your Mac to the router... Read more
Notion 2.0.20 - A unified workspace for...
Notion is the unified workspace for modern teams. Notion Features: Integration with Slack Documents Wikis Tasks Release notes were unavailable when this listing was updated. Download Now]]> Read more
Monterey Cache Cleaner 17.0.2 - Clear ca...
Monterey Cache Cleaner is an award-winning general-purpose tool for macOS X. MCC makes system maintenance simple with an easy point-and-click interface to many macOS X functions. Novice and expert... Read more
Firetask Pro 4.6.8 - Innovative task man...
Firetask Pro represents the next generation of easy-to-use, project-oriented task management apps. By combining David Allen's powerful Getting Things Done (GTD®) approach with classical task... Read more
Smultron 13.0.4 - Easy-to-use, powerful...
Smultron 13 is the text editor for all of us. Smultron is powerful and confident without being complicated. Its elegance and simplicity helps everyone being creative and to write and edit all sorts... Read more
Box Sync 4.0.8057 - Online synchronizati...
Box Sync gives you a hard-drive in the Cloud for online storage. Note: You must first sign up to use Box. What if the files you need are on your laptop -- but you're on the road with your iPhone? No... Read more
Audio Hijack 3.8.10 - Record and enhance...
Audio Hijack (was Audio Hijack Pro) drastically changes the way you use audio on your computer, giving you the freedom to listen to audio when you want and how you want. Record and enhance any audio... Read more
Direct Mail 6.0.1 - Create and send grea...
Direct Mail is an easy-to-use, fully-featured email marketing app purpose-built for macOS. Create, send, and track great looking email campaigns that get results. Start your newsletter by selecting... Read more

Latest Forum Discussions

See All

SwitchArcade Round-Up: ‘Pokemon Legends:...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for January 28th, 2022. We’ve got a bunch of new releases to look at today, with a few big hitters, a few mid-level diversions, and a healthy supply of compost. Since it’s Friday, we... | Read more »
Phantom Blade: Executioners, S-Game...
S-Game has kicked off its first Closed Beta Test for Phantom Blade: Executioners, inviting a selected few to get first dibs on the upcoming KungFuPunk action RPG on mobile. The CBT officially begins this January 28th, and beta testers will receive... | Read more »
‘Infinite Galaxy’ First Anniversary: Cel...
Cultivating a new generation of valiant commanders across 240 countries worldwide, Infinite Galaxy has quenched players’ thirst to explore the vastness of space – and there are only more intergalactic adventures to embark on from here on out. Camel... | Read more »
War and Order: How to brave the cold in...
War and Order's 6th-anniversary celebrations are underway, and all in good time too - this season not only brings about fabulous festivities, but it also lets players experience the harsh winter in an entirely new way. [Read more] | Read more »
‘Hidden Folks+’ Is This Week’s New Apple...
The original Hidden Folks from Adriaan de Jongh is an excellent hidden objects game featuring hand drawn visuals. It is an absolute joy to play, and it has now released on Apple Arcade in the form of Hidden Folks+ () as an App Store great. If you’... | Read more »
Mini Metro’s First Big Update of 2022 Ad...
Last year saw great updates for Dinosaur Polo Club’s Mini Metro ($3.99) which is also available on Apple Arcade as an App Store Great. | Read more »
SwitchArcade Round-Up: ‘Gunvolt Chronicl...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for January 27th, 2022. In today’s article, we’ve got a whole bunch of new releases to check out. It’s a dangerous one for the wallet today, as there are several interesting games to... | Read more »
SIEGE: Apocalypse lets you engage in mil...
Launching today to the delight of military enthusiasts across the globe, SIEGE: Apocalypse is a new 1v1 military battler from KIXEYE that's set in the early days of the War Commander universe. Players need to collect and upgrade unit cards to build... | Read more »
‘SIEGE: Apocalypse’, KIXEYE’s Military-T...
Military fans across the globe now have more reasons to dive into the War Commander universe as KIXEYE launches SIEGE: Apocalypse on both iOS and Android devices today. The 1v1 military battler pits two players against each other in intense real-... | Read more »
‘Yu-Gi-Oh! Master Duel’ Is Rolling Out N...
Following its launch on PC and all consoles last week, Yu-Gi-Oh! Master Duel has finally released on mobile platforms. Since launch, the game has exploded on multiple platforms with it having over 260k concurrent players on Steam. It has full... | Read more »

Price Scanner via MacPrices.net

Apple has clearance 2020 13″ MacBook Airs ava...
Apple has clearance, Certified Refurbished, 2020 13″ Intel-based MacBook Airs in stock today starting at only $719 and up to $370 off original MSRP. Each MacBook features a new outer case, comes with... Read more
The cheapest iPhones for sale today at Apple...
Apple has restocked Apple Certified Refurbished iPhone 8 models starting at only $359. Each refurbished iPhone comes with a fresh external case, standard Apple 1-year warranty, and free shipping.... Read more
14″ MacBook Pro with Apple M1 Max CPU now in...
Looking for a new 14″ MacBook Pro with an Apple M1 Max CPU? Stock is finally trickling into Apple resellers. B&H has Silver 14″ M1 Max MacBook Pros in stock today for $2899 including free 1-2 day... Read more
14″ MacBook Pros with Apple M1 Pro CPUs are i...
Amazon is reporting stock of 14″ MacBook Pros with M1 Pro CPUs today with a $50 discount. Shipping is free, and delivery is available by February 1st for most configurations. Be sure to make your... Read more
Apple has restocked 13″ M1 MacBook Pros for $...
Apple has restocked a full line of 13″ M1 MacBook Pros available Certified Refurbished, starting at only $1099 and up to $230 off original MSRP. These are the cheapest M1 MacBook Pros for sale today... Read more
Apple’s AirPods Max headphones are on sale fo...
Amazon has Silver, Blue, and Space Gray Apple AirPods Max headphones on sale today for $100 off MSRP. Shipping is free, and all models are in stock today. Their price is the lowest currently... Read more
Open a new line of service at Verizon and get...
Verizon is giving away 64GB Apple iPhone 12 minis or your choice of an iPhone 11 to customers who choose one of these phones and open a new line of service. Offer is available online only, and no... Read more
Open-box 13″ M1 MacBook Airs now available st...
QuickShip Electronics has open-box return 13″ M1 MacBook Airs in stock and on sale for $200-$400 off MSRP on their eBay store right now with free express delivery. According to QuickShip, “The item... Read more
Verizon’s 2022 iPad promo: $100-$310 off any...
Verizon has cellular-capable iPads on sale for $100-$310 off MSRP when purchased with an Unlimited service plan. Sale price is applied to your account monthly over a 24 or 30 month period, depending... Read more
Sunday Sale: Apple AirPods are on sale for up...
Amazon has Apple AirPods on sale for $10-$100 off MSRP today, depending on the model. All are in stock today with free delivery: – AirPods Max headphones (Blue): $449 $100 off MSRP – AirPods Max... Read more

Jobs Board

Registered Nurse (RN) Employee Health PSJH -...
…is calling for a Registered Nurse (RN) Employee Health PSJH to our location in Apple Valley, CA.** We are seeking a Registered Nurse (RN) Employee Health PSJH to be Read more
Systems Administrator - Pearson (United State...
…and troubleshoot Windows operating systems (workstation and server), laptop computers, Apple iPads, Chromebooks and printers** + **Administer and troubleshoot all Read more
IT Assistant Level 1- IT Desktop Support Anal...
…providing tier-1 or better IT help desk support in a large Windows and Apple environment * Experience using IT Service Desk Management Software * Knowledge of IT Read more
Human Resources Business Partner PSJH - Provi...
…**is calling a** **Human Resources Business Partner, PSJH** **to our location in Apple Valley, CA.** **Applicants that meet qualifications will receive a text with Read more
Manager Community Health Investment Programs...
…is calling a Manager Community Health Investment Programs PSJH to our location in Apple Valley, CA.** **Qualified candidates will be invited to do a self-paced video Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.