From: jimad@microsoft.com (Jim Adcock)
Subject: Re: overloading operator new
Date: 23 Dec 92 22:12:34 GMT
Organization: Microsoft Corporation

In article <1992Dec18.125656.4293@meadow.uucp> marc@meadow.UUCP (Marc Riehm) writes:
|I want to be able to take control of memory management in c++, and I've run
|into a problem with overloading operator new.  I have c++ classes which
|provide memory "pool" management: these act as a layer over malloc().  What I
|want to do is to be able to specify which pool to allocate from when I
|instantiate an object of another class.
|
|Thus, say I had class MyObject -- I want to be able to instantiate instances
|of this class in some manner like...
|MyObject *myObj1 = new MyObject(bigHeap)   where bigHeap is a memory pool,  or
|MyObject *myObj2 = new MyObject(altHeap)  etc.
|The store for myObj1 would come from bigHeap, and that for myObj2 from altHeap.
|
|My Turbo C++ 2.0 manual (the only C++ documentation I have available :( )
|says that the first argument of MyObject::new must be a size_t.  i.e. we
|overload new via a method which looks like...
|void *MyObject::new(size_t)
|They imply that there can be other arguments to MyObject::new.  Could anyone
|tell me whether or not this is true and, if it is, how to declare the method
|and how to use MyObject::new?  Are there any side effects on the constructor?

You're on the right track.  What you need to use is the "placement" 
option to operator new.  "Placement" refers to the ability of operator
new to be overloaded with additional parms, for example an additional
void* parameter that specifies where an object is to be created:

void* MyObject::operator new(size_t, void* place) 
{
	return place;
}

This gets used using the following "funny" syntax, for example:

	allocAddress* allocation = new malloc(sizeof(MyObject);

	MyObject* pOb = new (allocAddress) MyObject;

Note that I'm merely explaining here where the term "placement" comes
from, and showing you the weird location that where the extra parms
get specified in using the "placement" operator new.  *You* can 
specify the extra parameters to your operator new to be what you want,
with a meaning that you choose -- you're not restricted to using
these extra parameters to *mean* placement, its just just that in the
common lingo these parameters have come to be *called* the "placement"
parameters to operator new.  Here's a sketch of what you're talking about:

void* MyObject::operator new(size_t size, POOLSPECIFIER pool)
{
	return AllocateFromPool(pool, size);
}

gets used as:

	MyObject* pOb = new (somePool) MyObject;

If you think about it, in a "normal" new the MyObject constructor can
have its own parameters:

	MyObject* pOb = new MyObject(ctorParms);

So the "placement" operator new parameters have to be specified some
other "weird" place:

	MyObject* pOb = new (placementParms) MyObject(ctorParms);

Thus solves the easy part of your problem.  A harder part of the problem
becomes how you correctly DEallocate these allocations back to their
proper pool, because there is no equivalent "placement" operators to 
operator delete.  One MyObject::operator delete(void*) has to work 
for all the pools.  If pools are implemented using contiguous chunks
of memory for example, you could keep a sorted list of address
ranges corresponding to the different pools.