\input texinfo  @c -*- texinfo -*-
@c %**start of header
@setfilename gnustep-zones.info
@settitle Memory Management in GNUstep
@c %**end of header

@ifinfo
@format
* GNUstep Zones: (gnustep-zones).       Memory management in GNUstep.
@end format
@end ifinfo


@ifinfo
This explains how to use dynamic memory allocation with the GNUstep base
library.

Copyright (C) 1997 Yoo C. Chung and Free Software Foundation, Inc.

Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.

@ignore
Permission is granted to process this file through @TeX{} and print the
results, provided the printed document carries copying permission notice
identical to this one except for the removal of this paragraph (this
paragraph not being relevant to the printed manual).
@end ignore

Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided also that the
entire resulting derived work is distributed under the terms of a
permission notice identical to this one.

Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions.
@end ifinfo


@titlepage
@title Memory Management in GNUstep
@author Yoo C. Chung (wacko@@power1.snu.ac.kr)
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 1997 Yoo C. Chung and Free Software Foundation, Inc.


Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.

Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided also that the
entire resulting derived work is distributed under the terms of a
permission notice identical to this one.

Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions.
@end titlepage


@c important TODO: Need examples!


@ifinfo
@node Top, Memory Management, (dir), (dir)
@comment  node-name,  next,  previous,  up
@top Memory Management in GNUstep

This explains how to use dynamic memory allocation when using the
GNUstep Base Library.
@end ifinfo


@menu
* Memory Management::           Dynamically allocating memory.
* Concept Index::               Index of concepts.
* Function Index::              Index of functions.
* Data Type Index::             Index of data types.
@end menu


@node Memory Management, Concept Index, Top, Top
@comment  node-name,  next,  previous,  up
@chapter Memory Management
@cindex Memory management

GNUstep uses zones for dynamic memory allocation.

@menu
* Memory Management Concepts::  An introduction to concepts and terminology.
* Introduction to Zones::       What are zones?
* Creating Zones::              How to create zones.
* Allocating Memory::           How to get memory from zones.
* Resizing Memory::             How to resize memory within zones.
* Freeing Memory::              Save memory by freeing unused memory.
* Finding Zones::               Finding the zone that contains a chunk.
* Recycling Zones::             When you don't need a zone anymore.
* Naming Zones::                Zones have names.
* Zone Customization::          Custom zones are possible.
* Zone Consistency Checking::   Checking for errors.
* Zone Statistics::             Obtaining statistics about a zone.
* Zone Function Summary::       Summary of zone functions and structures.
@end menu


@node Memory Management Concepts, Introduction to Zones, Memory Management, Memory Management
@comment  node-name,  next,  previous,  up
@section Memory Management Concepts
@cindex Memory management concepts

A program does not always know how much memory it needs for its data (in
fact, this is the case in most programs).  One might statically allocate
(this means that the amount of memory is determined at compile time)
memory with some large size, but this can be either a huge waste or
memory might run out.  So memory must be allocated at runtime in these
cases.  This is called @dfn{dynamic memory allocation}.

Memory returned by a dynamic memory allocator is usually called a
@dfn{memory block} or a @dfn{memory chunk}.  Here we call them memory
chunks.

@ignore
We might give a better introduction here.  But be careful not to give a
long and boring one.  Keep it simple!  We might also give references to
books where one can learn more about memory management.
@end ignore


@node Introduction to Zones, Creating Zones, Memory Management Concepts, Memory Management
@comment  node-name,  next,  previous,  up
@section Introduction to Zones
@cindex Zone introduction

Any reasonably complete C library will contain the functions
@code{malloc} and @code{free}.  One uses these functions for dynamic
memory allocation in many C programs.  These functions usually use all
of the memory for potential allocation.  This could result in two memory
chunks being allocated far from each other in the virtual memory space,
which could lead to increased paging.

Zones can be used to allocate many related memory chunks close to each
other.  A @dfn{zone} is an area (actually a set of areas) in memory
where related chunks of memory can be allocated from.  This might help
in reducing paging on virtual memory systems.  Each zone can have
different behavior (@pxref{Zone Customization}).

The GNUstep Base Library uses zones for dynamic memory allocation.  The
functions that are used to obtain memory chunks from zones are thread
safe.

@ignore
Should give a more detailed and more understandable introduction.  Might
include a little history as well.
@end ignore


@node Creating Zones, Allocating Memory, Introduction to Zones, Memory Management
@comment  node-name,  next,  previous,  up
@section Creating Zones
@cindex Creating zones
@cindex Default zone

In order to use a zone, it must first be created.  You create zones with
@code{NSCreateZone}, which is declared in @file{NSZone.h}.

@deftypefun NSZone* NSCreateZone (size_t @var{start}, size_t @var{gran}, BOOL @var{canFree})
Creates a memory zone which starts with a size of at least @var{start}
bytes and grows by at least @var{gran} bytes when needed.  If
@var{canFree} is @code{YES}, then memory chunks allocated in the zone
can be freed.  If @var{canFree} is @code{NO}, then memory chunks
allocated in the zone cannot be freed unless the whole zone is recycled,
nor can they be resized.  A pointer pointing to the newly created zone
is returned.

If @var{start} is zero, the zone will start out with some default size.
If @var{gran} is zero, the zone will grow by some default number of
bytes when the zone needs more memory.

If there isn't enough memory to create the zone, a
@code{NSMallocException} is raised.
@end deftypefun

We might want to use a zone that cannot free memory chunks in a
situation where we need to allocate many chunks of memory and free them
all at once after using them by recycling the zone (@pxref{Recycling
Zones}), since a zone that cannot free memory chunks allocates memory
faster than one that is able to free memory chunks.  This is because a
zone that cannot free memory chunks has a lot less bookkeeping to worry
about.

You do not have to explicitly create a zone to dynamically allocate
memory, since there already exists a default zone.  A pointer to the
default zone can be obtained with @code{NSDefaultMallocZone}, which is
also declared in @file{NSZone.h}.

@deftypefun NSZone* NSDefaultMallocZone (void)
Returns the default memory allocation zone.  The default default zone
cannot be recycled.
@end deftypefun


@node Allocating Memory, Resizing Memory, Creating Zones, Memory Management
@comment  node-name,  next,  previous,  up
@section Allocating Memory Chunks
@cindex Allocating memory chunks

In order to allocate a memory chunk from a zone, we need to use
@code{NSZoneMalloc}, which is declared in @file{NSZone.h}.

@deftypefun {void*} NSZoneMalloc (NSZone *@var{zone}, size_t @var{size})
Allocate @var{size} bytes from the zone pointed to by @var{zone}.  A
pointer to the allocated memory chunk is returned.

If @var{size} is zero @code{NULL} is returned.  If there is not enough
memory to allocate @var{size} bytes, a @code{NSMallocException} is
raised.
@end deftypefun

The contents of the allocated memory are uninitialized and
unpredictable.  We can allocate memory filled with zeroes with
@code{NSZoneCalloc}, which is also declared in @file{NSZone.h}.

@deftypefun void* NSZoneCalloc (NSZone *@var{zone}, size_t @var{elems}, size_t @var{bytes})
Allocate memory for @var{elems} elements (each of which are @var{bytes}
bytes) from the zone pointed to by @var{zone}.  The memory chunk is
initialized with zeroes.

If either @var{elems} or @var{bytes} is zero, NULL is returned.  If
there is not enough memory for the request, a @code{NSMallocException}
is raised.
@end deftypefun

One should not depend on @code{NSZoneMalloc} and @code{NSZoneCalloc}
returning @code{NULL} when the request size is zero.  It's bad style,
not to mention that this might change in the future, or might behave
differently on custom zones (@pxref{Zone Customization}).

The zone containing a memory chunk allocated by @code{NSZoneMalloc} or
@code{NSZoneCalloc} can be found with @code{NSZoneFromPointer}
(@pxref{Finding Zones}).


@node Resizing Memory, Freeing Memory, Allocating Memory, Memory Management
@comment  node-name,  next,  previous,  up
@section Resizing Memory Chunks
@cindex Resizing memory chunks

Sometimes one doesn't know how large a memory chunk one might need in
advance.  For example, if a memory chunk is a buffer for a line from a
file, then no matter how large the buffer is, there might always be line
that won't fit into the buffer.

@c The above example was stolen from the libc manual.

One can resize a memory chunk by using @code{NSZoneRealloc}, which is
declared in @file{NSZone.h}.

@deftypefun void* NSZoneRealloc (NSZone *@var{zone}, void *@var{ptr}, size_t @var{size})
Resizes the memory chunk pointed to by @var{ptr} to @var{size} bytes.
If the memory chunk needs to be relocated, then the original contents
will be copied to the new location.  @var{ptr} may be @code{NULL}, in
which case a new memory chunk will be allocated from the zone.  The
pointer to the resized memory chunk is returned.

If @var{size} is zero, the memory chunk pointed to by @var{ptr} is
freed.  If there is not enough memory to resize the chunk, a
@code{NSMallocException} is raised.
@end deftypefun

One shouldn't depend on @code{NSZoneRealloc} freeing the pointer with a
size argument of zero or allocating a new chunk with a pointer argument
of @code{NULL}, because it's bad style (in my humble opinion).


@node Freeing Memory, Finding Zones, Resizing Memory, Memory Management
@comment  node-name,  next,  previous,  up
@section Freeing Memory Chunks
@cindex Freeing memory chunks

A memory chunk may no longer be needed after it is used.  Then it would
be better to free the memory chunk so it can be reused for other memory
allocation requests.  A memory chunk can be freed with
@code{NSZoneFree}, which is declared in @file{NSZone.h}.

@deftypefun void NSZoneFree (NSZone *@var{zone}, void *@var{ptr})
This frees the allocated memory chunk that @var{ptr} points at.  The
memory chunk must have been allocated from the zone pointed to by
@var{zone}.
@end deftypefun

Note that unlike the C library function @code{free}, calling
@code{NSZoneFree} with a pointer argument of @code{NULL} is an error.


@node Finding Zones, Recycling Zones, Freeing Memory, Memory Management
@comment  node-name,  next,  previous,  up
@section Finding Zones Containing a Memory Chunk
@cindex Finding zones

Sometimes one might need to find out the zone that contains a memory
chunk.  For example, objects derived from @code{NSObject} usually need
to find out the zone it resides in to deallocate itself.  One can find
the zone with @code{NSZoneFromPointer}, which is declared in
@file{NSZone.h}.

@deftypefun NSZone* NSZoneFromPointer (void *@var{ptr})
Finds the zone that contains the memory chunk pointed to by @var{ptr}
and returns a pointer to it.  @var{ptr} must be a pointer returned by
@code{NSZoneMalloc} or @code{NSZoneRealloc}.
@end deftypefun

@code{NSZoneFromPointer} takes a constant amount of time regardless of
how many zones or memory chunks there are, so it would save space to use
@code{NSZoneFromPointer} instead of saving the zone separately.


@node Recycling Zones, Naming Zones, Finding Zones, Memory Management
@comment  node-name,  next,  previous,  up
@section Recycling Zones
@cindex Recycling zones

A zone can become useless after a while.  Then it would be better to
recycle the zone to save memory.  This can be done with
@code{NSRecycleZone}, which is declared in @file{NSZone.h}.

@deftypefun void NSRecycleZone (NSZone *@var{zone})
This function recycles the zone.  All memory in the zone will be
reclaimed.
@end deftypefun

Note that when a zone in GNUstep are recycled, all memory in the zone
will be recycled, unlike zones in the Foundation Kit of OpenStep, where
zones that can free memory return live objects to the default zone.


@node Naming Zones, Zone Customization, Recycling Zones, Memory Management
@comment  node-name,  next,  previous,  up
@section Naming Zones
@cindex Naming zones
@cindex Zone names

Memory allocation zones can be named.  You might want to do this as a
debugging aid.  You can set the name of a zone with @code{NSSetZoneName}
and obtain the name of a zone with @code{NSZoneName}, which are declared
in @file{NSZone.h}.

@deftypefun void NSSetZoneName (NSZone *@var{zone}, NSString *@var{name})
This sets a name for the zone pointed to by @var{zone}.  If @var{name}
is @code{nil}, the name of the zone will be unset if there was a name
previously set.  Otherwise a copy will be made of @var{name} in the
default zone, and the name of the zone will be set to the copy.
@end deftypefun

@deftypefun NSString* NSZoneName (NSZone *@var{zone})
Returns the name for the zone pointed to by @var{zone}.  Don't release
it unless you have retained it.
@end deftypefun


@node Zone Customization, Zone Consistency Checking, Naming Zones, Memory Management
@comment  node-name,  next,  previous,  up
@section Customization
@cindex Customizing zones

The behavior of memory allocation zones can be customized in GNUstep,
unlike zones with the Foundation Kit of OpenStep, which has a fixed
default zone and only two kinds of zones possible.

@menu
* Setting Default Zone::        The default zone can be changed.
* Creating Custom Zones::       Zones with customized behavior can be created.
@end menu


@node Setting Default Zone, Creating Custom Zones, Zone Customization, Zone Customization
@comment  node-name,  next,  previous,  up
@subsection Setting the Default Zone
@cindex Setting default zone

Initially there is a default default zone.  But the performance of the
default allocator might not be satisfactory for a program.  In such
cases, you may want to change the default zone to a zone that has more
satisfactory performance.  You can do this with
@code{NSSetDefaultMallocZone}, which is declared in @file{NSZone.h}.

@deftypefun void NSSetDefaultMallocZone (NSZone *@var{zone})
This sets the default memory allocation zone to the zone pointed to by
@var{zone}.
@end deftypefun

You shouldn't change the default zone unless you know what you're doing.

Note that @code{NSSetDefaultMallocZone} is not defined by OpenStep.


@node Creating Custom Zones,  , Setting Default Zone, Zone Customization
@comment  node-name,  next,  previous,  up
@subsection Creating Custom Zones
@cindex Creating a custom zone
@tindex struct _NSZone

A zone with a custom behavior and implementation can be created.  For
example, all memory chunks allocated within a zone may have the same
size, in which case a much more simpler allocator than the default one
can be used.

A custom zone can be created by appropriately setting the members of the
structure @code{NSZone} (actually this is a typedef to @code{struct
_NSZone}), which is declared in @file{NSZone.h}.

@deftp {Data Type} NSZone
This is actually a typedef to @code{struct _NSZone}.  This structure
contains the following members, all of which must be set to be properly
used as a zone.

@table @code

@item void *(*malloc)(NSZone *@var{zone}, size_t @var{size})
This is a pointer to the function that allocates @var{size} bytes from
the zone pointed to by @var{zone}.  (@pxref{Allocating Memory})

@item void *(*realloc)(NSZone *@var{zone}, void *@var{ptr}, size_t @var{size})
This is a pointer to the function that resizes the memory chunk pointed
to by @var{ptr}, which was allocated from the zone pointed to by
@var{zone}, to @var{size} bytes.  (@pxref{Resizing Memory})

@item void (*free)(NSZone *@var{zone}, void *@var{ptr})
This is a pointer to the function that returns the memory chunk pointed
to be @var{ptr} to the zone pointed to by @var{zone}.  (@pxref{Freeing
Memory})

@item void (*recycle)(NSZone *@var{zone})
This is a pointer to the function that recycles the zone pointed to by
@var{zone}.  (@pxref{Recycling Zones})

@item BOOL (*check)(NSZone *@var{zone})
This is a pointer to the function that checks the integrity of the zone
that is pointed to by @var{zone}.  (@pxref{Zone Consistency Checking})

@item struct NSZoneStats (*stats)(NSZone *@var{zone})
This is a pointer to the function that returns statistics about the zone
pointed to by @var{zone}.  (@pxref{Zone Statistics})

@item size_t gran
This holds the granularity of the zone.  (@pxref{Creating Zones})

@item NSString *name
This points to the name of the zone.  (@pxref{Naming Zones})

@end table

@end deftp

To create the functions that a zone uses, you'll probably have to use
@code{NSZoneRegisterChunk} and @code{NSZoneChunkOverhead}, which are
also declared in @file{NSZone.h}.

@deftypefun void* NSZoneRegisterChunk (NSZone *@var{zone}, void *@var{chunk})
This registers the memory chunk pointed to by @var{chunk} so that
@code{NSZoneFromPointer} will work (@pxref{Finding Zones}).  A pointer
to the beginning of the memory that should actually be returned to the
user is returned.
@end deftypefun

@deftypefun size_t NSZoneChunkOverhead (void)
This returns the overhead that is needed for @code{NSZoneFromPointer}
(@pxref{Finding Zones}) to work in bytes.
@end deftypefun

Creating a custom zone could be an error prone process, so don't use
them unless you know what you're doing (and willing to go through a
potentially long debugging process).

Note that @code{NSZoneRegisterChunk} and @code{NSZoneChunkOverhead} are
not defined in OpenStep.


@node Zone Consistency Checking, Zone Statistics, Zone Customization, Memory Management
@comment  node-name,  next,  previous,  up
@section Zone Consistency Checking
@cindex Checking consistency of a zone

You can check the integrity of a zone by using @code{NSZoneCheck}, which
is declared in @file{NSZone.h}.

@deftypefun BOOL NSZoneCheck (NSZone *@var{zone})
Checks the integrity of the zone pointed to by @var{zone}.  Returns
@code{YES} if there are no errors, returns @code{NO} otherwise.
@end deftypefun

Note that @code{NSZoneCheck} is not defined in OpenStep.


@node Zone Statistics, Zone Function Summary, Zone Consistency Checking, Memory Management
@comment  node-name,  next,  previous,  up
@section Zone Statistics
@cindex Zone statistics

You can obtain statistics about a zone with @code{NSZoneStats} which
returns the statistics in a @code{struct NSZoneStats}.  These are
declared in @file{NSZone.h}.

@deftp {Data Type} {struct NSZoneStats}

This structure type is used to return statistics about a zone, and has
the following members:

@table @code

@item size_t bytes_total
This is the total size of memory managed by the zone, in bytes.

@item size_t chunks_used
This is the number of memory chunks in use in the zone.

@item size_t bytes_used
This is the number of bytes in use.

@item size_t chunks_free
This is the number of memory chunks that are not in use.

@item size_t bytes_free
This is the number of bytes managed by the zone that are not in use.

@end table

@end deftp

@deftypefun {struct NSZoneStats} NSZoneStats (NSZone *@var{zone})
This returns statistics about the zone pointed to by @var{zone} in a
structure of type @code{struct NSZoneStats}.
@end deftypefun

Note that @code{NSZoneStats} (and obviously @code{struct NSZoneStats})
is not defined in OpenStep.


@node Zone Function Summary,  , Zone Statistics, Memory Management
@comment  node-name,  next,  previous,  up
@section Summary

Here is a summary of the functions and data types that work with memory
allocation zones, which are all declared in @file{NSZone.h}:

@table @code

@item NSZone* NSCreateZone (size_t @var{start}, size_t @var{gran}, BOOL @var{canFree})
Creates a zone.  (@pxref{Creating Zones})

@item NSZone* NSDefaultMallocZone (void)
Returns the default zone.  (@pxref{Creating Zones})

@item void* NSZoneMalloc (NSZone *@var{zone}, size_t @var{size})
Allocates memory from a zone.  (@pxref{Allocating Memory})

@item void* NSZoneCalloc (NSZone *@var{zone}, size_t @var{elems}, size_t @var{bytes})
Allocates memory initialized with zeroes from a zone.
(@pxref{Allocating Memory})

@item void* NSZoneRealloc (NSZone *@var{zone}, void *@var{ptr}, size_t @var{size})
Resizes a memory chunk that had been allocated from a zone.
(@pxref{Resizing Memory})

@item void NSZoneFree (NSZone *@var{zone}, void *@var{ptr})
Returns a memory chunk to the zone.  (@pxref{Freeing Memory})

@item NSZone* NSZoneFromPointer (void *@var{ptr})
Finds the zone that contains a memory chunk.  (@pxref{Finding Zones})

@item void NSRecycleZone (NSZone *@var{zone})
Recycles a zone.  (@pxref{Recycling Zones})

@item void NSSetZoneName (NSZone *@var{zone}, NSString *@var{name})
Sets a name for a zone.  (@pxref{Naming Zones})

@item NSString* NSZoneName (NSZone *@var{zone})
Returns the name for a zone.  (@pxref{Naming Zones})

@item void NSSetDefaultMallocZone (NSZone *@var{zone})
Set the default zone.  (@pxref{Setting Default Zone})

@item void* NSZoneRegisterChunk (NSZone *@var{zone}, void *@var{chunk})
Function used in custom zones to register a memory chunk.
(@pxref{Creating Custom Zones})

@item void* NSZoneChunkOverhead (void)
Function used in custom zones to find overhead for each memory chunk.
(@pxref{Creating Custom Zones})

@item BOOL NSZoneCheck (NSZone *@var{zone})
Checks the integrity of a zone.  (@pxref{Zone Consistency Checking})

@item struct NSZoneStats NSZoneStats (NSZone *@var{zone})
Returns statistics about a zone.  (@pxref{Zone Statistics})

@item NSZone
Typedef to @code{struct _NSZone}, which is a structure type that
actually holds the zone.  (@pxref{Creating Custom Zones})

@item struct NSZoneStats
Structure type used to return statistics about a zone.  (@pxref{Zone
Statistics})

@end table


@node Concept Index, Function Index, Memory Management, Top
@comment  node-name,  next,  previous,  up
@unnumbered Concept Index

@printindex cp


@node Function Index, Data Type Index, Concept Index, Top
@comment  node-name,  next,  previous,  up
@unnumbered Function Index

@printindex fn


@node Data Type Index,  , Function Index, Top
@comment  node-name,  next,  previous,  up
@unnumbered Data Type Index

@printindex tp


@bye
