blob: 0af4129941febac84f67103c09db0dc51a655d99 [file] [log] [blame]
/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/
/* -*-C++-*-
****************************************************************************
*
* File: NABasicObject.h (previously under /common)
* Description: This file contains the declaration of NABasicObject, which
* has the new/delete defined to use CollHeap* as the memory
* allocation.
*
* Created: 5/6/98
* Language: C++
*
*
*
****************************************************************************
*/
#ifndef NABASICOBJECT__H
#define NABASICOBJECT__H
#include "Platform.h"
#include "NAStdlib.h"
#include "NABoolean.h"
#define NOT_CHECK_NAHEAP(h) (h)
class NAMemory ;
typedef NAMemory CollHeap ;
// -----------------------------------------------------------------------
// This file contains the
// NABasicObject class for the new/delete operator for memory management, and
// memory management macros, overloaded new operators for the classes
// not derived from NABasicObject.
//
// -class CollHeap - defined in NAHeap.h, abstract base class.
// allocateMemory, deallocateMemory methods defined.
//
// -class NABasicObject
// A base class for all classes that want to use new/delete from CollHeap*
// It contains the implementation for overloaded new/delete operators.
//
// -examples:
// class YourHeap : public CollHeap
// implement your allocateMemory and deallocateMemory methods.
//
// class YourClass : NABasicObject
//
// then, you can do
// YourHeap* aHeap = new YourHeap;
// YourClass* object = new (aHeap) YourClass(aHeap);
// the memory will be allocated through YourHeap
// YourClass* sysObject = new YourClass;
// the memory will be allocated through global new
// delete object;
// delete sysObject;
// the memory allocated will be freed accordingly.
//
// - Some new operators and macro defines (for delete) for CollHeap*
// memory management.
// These are for classes/types that can NOT be derived from NABasicObject.
// e.g. RW classes, basic types, .etc. Also for the new of array which
// goes through the global new/delete always.
// void * operator new(size_t size, CollHeap* h);
// NADELETEBASIC (which despite its name does NOT delete NABasicObjects)
// NADELETE (in fact, neither does this)
// NADELETEARRAY (or this)
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
//
// Examples to use them :
//
// 1. Derive your class from NABasicObject
// (Strongly suggested for the newly developed class)
// example :
// class A : public NABasicObject { }
//
// A* a = new (anyCollHeap*) A;
// delete a;
//
// The memory will be allocated/deallocated from the specified CollHeap*.
//
// A* asys = new A;
// delete asys;
//
// asys will be allocateed/deallocated using the global new/delete operator.
//
// 2. For the existing classes, you can do
// class B;
// B* b = new(anyCollHeap*);
// NADELETE(b,B,anyCollHeap*);
//
// 3. For builtin types, in which there is no need to call a destructor, do
// int* p = new (anyCollHeap*) int[100];
// NADELETEBASIC(p,anyCollHeap); // better name would be NADELETEBUILTIN
// // or NADELETESCALAR ...
//
// 4. For array of elements, do
// class C;
// C* c = new(anyCollHeap*) C[100];
// NADELETEARRAY(c,100, C,anyCollHeap*);
//
// If the array of elements are allocated from CollHeap*, it has to be
// deleted using NADELETEARRAY, because the new of array will always
// go through the global new operator.
// You can only do delete[] array if it is newed from global new
// operator.
//
// Note that global new/delete will still work fine, but just get the memory
// from global new/delete operator.
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// NABasicObject overloads the new/delete operators to use CollHeap* as
// memory management for classes derived from it.
// -----------------------------------------------------------------------
class NABasicObject
{
protected:
virtual ~NABasicObject() {};
public:
// The destructor is not a virtual function, because all the executor
// objects are derived from NABasicObject, and the objects will be
// written to the disk. To save space in the disk, the destructor is
// not a virtual function. So, NABasicObject* cannot used for delete
// it will not call the correct destructor.
//
// The destructor is the default destructor, which does NOT (of course)
// do "delete h_;"! Likewise, the assignment operator here does not
// overwrite the h_ pointer.
NABasicObject();
NABasicObject(const NABasicObject&);
NABasicObject& operator=(const NABasicObject&);
void* operator new[](size_t t, NAMemory* h = 0, NABoolean failureIsFatal = TRUE);
void operator delete[](void*);
void operator delete[](void*, NAMemory*, NABoolean);
// In the future, when the compiler supports the operator new[] and
// operator [] delete, they should be added here for array allocation.
// void* operator new[](size_t, NAMemory* h = 0, NABoolean failureIsFatal = TRUE);
// void operator delete[](void*, etc... -- see .C file comments...)
void* operator new(size_t t, NAMemory* h = 0, NABoolean failureIsFatal = TRUE );
void* operator new(size_t t, void* loc, NAMemory* h = 0);
void operator delete(void*);
void operator delete(void*, NAMemory*, NABoolean);
void operator delete(void*, void*, NAMemory*);
// The CollHeap* returned is where this object is allocated from;
// if this object is allocated through new, it will be some CollHeap* or 0.
// If the object is a local stack variable, the CollHeap* will be
// uninitialized garbage.
// In the design of the derived classes, if you want to use this
// CollHeap* as further memory allocation, it is the user's
// responsibility to make sure the object is not from stack.
NAMemory* collHeap() { return h_; }
// The delete operator sets the object-being-deleted's heap pointer to the
// invalid value below. Thus dangling pointers to this object can *sometimes*
// be identified by use of this eyecatcher when in the debugger, or
// smart-pointer code can explicitly check for this value, in the cases where:
// - the pointed-to memory has not actually been freed (deallocateMemory method
// is often a no-op, so this is common); or
// - the memory has been freed but happens to have been reallocated with a
// new object before the dangling pointer referenced it; or
// - the memory has been freed and the dangling ptr reference occurs in an
// environment that allows freed memory accesses (SunOS Unix, e.g.).
// Note that the first two cases cannot be found even running Purify.
// However, note that "*sometimes*": if the pointed-at object was not
// allocated by "new" but rather on the stack, then its h_ is (as said before)
// random garbage, which *could* be the magic "invalid" value.
// This problem could be solved with an additional "isValid_/isAllocated_"
// flag word, but that would be an additional executor disk space hit ...
//
// The value of 0x1 was chosen because low memory is on most machines going
// to be out-of-bounds for a heap. (0x0 already has a meaning: that no heap
// is to be used, just the global new/delete.)
static CollHeap* invalidHeapPtr() { return (CollHeap*)0x1; }
static CollHeap* systemHeapPtr() { return (CollHeap*)0x0; }
Int32 maybeInvalidObject() { return h_ == invalidHeapPtr();}
// For smart-pointer callers, some defensive programming for Debug build.
#if !defined(NDEBUG)
Int32 checkInvalidObject(const void* const referencingObject=NULL);
#else
Int32 checkInvalidObject(const void* const = NULL)
{ return 0/*not invalid*/; }
#endif
private:
// To add a field into the NABasicObject in later releases,
// need to have versioning in the generated rtd files. Since
// the size will be different.
CollHeap* h_;
};
// -----------------------------------------------------------------------
// The following overloading new operators are for the classes not
// derived from NABasicObject. e.g. RW classes, if needs to be allocated
// other than system area, use the overloaded new.
// -----------------------------------------------------------------------
void * operator new(size_t size, CollHeap* h);
void * operator new[](size_t size, CollHeap* h);
void * operator new[](size_t size, CollHeap* h, NABoolean failureIsFatal);
// The following operator delete functions will be called to free memory if
// the initialization throws an exception. They are needed to remove a
// compiler warning from the .NET 2003 compiler.
// The following operator delete functions will be called to free memory if
// the intialization throws an exception. They are needed to remove a
// compiler warning from the .NET 2003 compiler.
// -----------------------------------------------------------------------
// The followings are macro defines to delete ( i.e. calling the destructor
// and deallocate space ) certain data from certain heap. ( Since delete
// cannot be overloaded with parameter. )
//
// The reason to use macro defines instead of template inlines is because
// the destructor cannot be called from template function, i.e.
// template <class C>
// inline void deleteMe(C* p) { p->~C(); } failed
// in ~C is not a member function name. If someone has found a way to let
// it work, it should be changed into template function, then. This is
// a bug in the compiler, if it ever gets fixed, template function is
// a better approach.
//
// -----------------------------------------------------------------------
// When the compiler supports the destructor in template function,
// the following template functions should be added, used to allocate
// the objects not derived from NABasicObject, e.g. RW objects.
// template<class T>
// void deleteMe(T* p, NAMemory* h)
// {
// p->~p();
// if (h)
// h->deallocateMemory((void*)p);
// else
// ::operator delete((void*)p);
// }
// NADELETEBASIC(p,h) deletes p from CollHeap h without calling the destructor:
// *p is one of the builtin data types char, int, struct, etc.
// (A better name would be NADELETEBUILTIN or NADELETESCALAR,
// as the "BASIC" in this macro does *not* apply to NA*Basic*Object.)
// example :
// char* p = new (CmpCommon::contextHeap()) char[10];
// NADELETEBASIC(p,CmpCommon::contextHeap());
#define NADELETEBASIC(p,h) \
(void) (!(p) || \
((NOT_CHECK_NAHEAP(h) ? (h)->deallocateMemory((void*)p) : delete p), 0) )
#define NADELETEBASICARRAY(p,h) \
(void) (!(p) || \
((NOT_CHECK_NAHEAP(h) ? (h)->deallocateMemory((void*)p) : delete [] p), 0))
// NADELETE(p,C,h) deletes p from CollHeap h, and calls p's destructor ~C.
// so the destructor of class C will be called.
// example :
// ClassA* a = new(CmpCommon::contextHeap()) ClassA;
// NADELETE(a,ClassA,CmpCommon::contextHeap());
#define NADELETE(p,C,h) \
(void) (!(p) || \
((NOT_CHECK_NAHEAP(h) ? ((p)->~C(), (h)->deallocateMemory((void*)p)) : \
delete p), 0))
// NADELETEARRAY(p,n,C,h) deletes p from CollHeap h, p is an array of class C
// so the destructor of C will be called for each element of p (if not NULL).
// The size of array has to be specified in n. (Sorry about that).
// example :
// ClassA* a = new(CmpCommon::contextHeap()) classA[10];
// NADELETEARRAY(a,10,ClassA,CmpCommon::contextHeap());
#define NADELETEARRAY(p,n,C,h) \
{ if (p) { \
if NOT_CHECK_NAHEAP(h) \
{ for (C* t=(p)+n-1; t>=p; t--) t->~C(); (h)->deallocateMemory((void*)p); } \
else delete[] (p); } }
#endif