// Swarm library. Copyright © 1996-2000 Swarm Development Group.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
// 
// The Swarm Development Group can be reached via our website at:
// http://www.swarm.org/

/*
Name:         defalloc.h
Description:  additional interfaces for block-level memory allocation
Library:      defobj
*/

#include <swarmconfig.h> // PTRUINT
#import <defobj/classes.h> // id_Zone_c

//
// getZone() --
//   macro to obtain zone in which object allocated
//
#define getZone(anObject) \
({ PTRUINT _zbits_ = (anObject)->zbits; \
  ( _zbits_ & BitSuballocList ? \
   (id) ((Object_s *)( _zbits_ & ~0x7 ))->zbits : \
   (id) (_zbits_ & ~0x7)); })

//
// getCZone() --
//   macro to obtain version of zone qualified for allocation of object
//   components
//

#if 0
#define getCZone(aZone) \
( _obj_debug ? [(aZone) getComponentZone] : ((id *)(aZone))[3] )
#else
#define getCZone(aZone) (getClass (aZone) == id_Zone_c ? (((id *)(aZone))[3]) : aZone)
#endif

//
// setMappedAlloc(), unsetMappedAlloc(), getMappedAlloc() --
//   macros to set/get bit that indicates that mapping of internal allocations
//   is required within an object
//
#define setMappedAlloc(anObject)  ((anObject)->zbits |= BitMappedAlloc)
#define unsetMappedAlloc(anObject)  ((anObject)->zbits &= ~BitMappedAlloc)
#define getMappedAlloc( anObject )  ((anObject)->zbits & BitMappedAlloc)

//
// bits within the zbits instance variable of any zone-allocated object
//
#define BitMappedAlloc     0x4  // set by suballoc list or explicit macro 
#define BitSuballocList    0x2  // set whenever object contains suballoc list
#define BitComponentAlloc  0x1  // set if object is not in the zone population

//
// struct mapalloc, mapalloc_t --
//   structure that maps an internal allocation within an object
/*
Definition of these types appears in the DefObject.h superclass, since they
are required to declare any mapAllocations: method.  All use of these types,
however, is by macros that require an explicit #import of <defobj/defalloc.h>.
Following is a commented-out copy of the definitions from DefObject.h:

typedef struct mapalloc *mapalloc_t;
struct mapalloc {
  void  (*mappingFunction)( mapalloc_t mapalloc, BOOL objectAllocation );
  void  *alloc;         // allocated object or block
  id    descriptor;     // descriptor for contents of allocated block, if any
  id    zone;           // zone of allocated block, as used by descriptor
  int   size;           // size of allocated block, as used by descriptor
};
*/

//
// MapAllocations --
//   protocol defining message to be implemented for any object for which
//   the MappedAlloc bit has been set
//
@protocol MapAllocations
- (void)     mapAllocations: (mapalloc_t)mapalloc;
@end

//
// mapObject() --
//   macro to identify an internal object within the allocations mapped
//   by a containing object
//
// This macro is for use inside a mapAllocations: method, which must be
// implemented on any method for which the MappedAlloc bit has been set.
// Each object identified by the macro must have been allocated as an
// internal component of the object being mapped.
//
#define mapObject( mapalloc, anObject ) \
( mapalloc->alloc = (anObject), mapalloc->mappingFunction( mapalloc, 1 ) )

//
// includeBlocks() --
//   macro to indicate whether internal blocks to be mapped within a
//   mapAllocations: request to map internal allocations
//
#define includeBlocks( mapalloc ) ( mapalloc->zone != nil )

//
// mapAlloc() --
//   macro to identify an internal allocation of a containing object
//
// This macro checks the current setting of the descriptor variable in the
// mapalloc structure to determine how to map the size and contents of the
// storage block identified.  The default setting of the descriptor is
// t_ByteArray, which checks the size field of the mapalloc structure to
// determine the block size.
//
// Raw storage blocks should be identified as part of an object allocation
// mapping only if the includeBlocks() macro returns true on the mapalloc
// structure of a current mapAllocations: request.
//
#define mapAlloc( mapalloc, aBlock ) \
( mapalloc->alloc = aBlock, mapalloc->mappingFunction( mapalloc, 0 ) )

//
// getSuballocList() --
//   macro to obtain the list of suballocations within an object, if any
//
#define getSuballocList( anObject ) \
({ PTRUINT _zbits_ = (anObject)->zbits; \
 ( _zbits_ & BitSuballocList ? (id) (_zbits_ & ~0x7) : nil); })

//
// struct suballocEntry, suballocEntry_t --
//   pointer to structure contained as member in the list of suballocations
//   for an object
//
typedef struct suballocEntry {
  notify_t  notifyFunction;  // function to notify on change of alloc, if any
  void      *argument;       // argument supplied in the addRef:withArg: call
                             //   that registered the allocation
  id        links[2];        // links that include entry into suballoc list
} *suballocEntry_t;

//
// struct suballocHeader, suballocHeader_t --
//   pointer to header of structure containing an object suballocation
//   (required as argument of addRef:withArg: when notifyFunction is nil)
//
typedef struct suballocHeader {
  size_t  suballocSize;  // total number of bytes in suballoc including header
  int     suballocKey;   // key for sorting suballocations within suballocList
    // remaining bytes of suballocation immediately follow the header ...
} *suballocHeader_t;

//
// _obj_fillalloc, _obj_fillfree -- 
//   fill patterns for allocated and freed blocks, for debugging
//
extern unsigned char  _obj_fillalloc, _obj_fillfree;
