Loading...
Searching...
No Matches
Memory Management Tutorial

This page gives a short overview of home-based memory management used with Sofia. More...

## Files

file | su_alloc.h
| Home-based memory management interface.
file | su_alloc_stat.h
| Home-based memory management statistics.

## Functions

int | su_home_threadsafe (su_home_t *home)
| Convert su_home_t object to a thread-safe one.
char * | su_strdup (su_home_t *home, char const *s)
| Duplicate a string, allocate memory from home.

## Detailed Description

This page gives a short overview of home-based memory management used with Sofia.

Such home-based memory management is useful when a lot of memory blocks are allocated for given task. The allocations are done via the memory home, which keeps a reference to each block. When the memory home is then freed, it will free all blocks to which it has reference.

Typically, there is a home object which contains a su_home_t structure in the beginning of the object (sort of inheritance from su_home_t):

struct context {
su_home_t ctx_home[1];
other_t *ctx_stuff;
...
}
su_home_t
SU_HOME_T su_home_t
Memory home type.
Definition su_alloc.h:50

A new home memory pool can be created with su_home_new():

struct context *ctx = su_home_new(sizeof (struct context));
su_home_new
void * su_home_new(isize_t size))
Create a new su_home_t object.
Definition su_alloc.c:548

It is also possible to create a secondary memory pool that can be released separately:

struct context *ctx = su_home_clone(tophome, sizeof (struct context));
su_home_clone
void * su_home_clone(su_home_t *parent, isize_t size))
Clone a su_home_t object.
Definition su_alloc.c:723

Note that the tophome has a reference to ctx structure; whenever tophome is freed, the ctx is also freed.

You can also create an independent home object by passing NULL as tophome argument. This is identical to the call to su_home_new().

The memory allocations using ctx proceed then as follows:

zeroblock = su_zalloc(ctx->ctx_home, sizeof (*zeroblock));
su_zalloc
void * su_zalloc(su_home_t *h, isize_t size))
Allocate and zero a memory block.
Definition su_alloc.c:1466

The home memory pool - the home object and all the memory blocks allocated using it - are freed when su_home_unref() is called:

su_home_unref(ctx->ctx_home).
su_home_unref
int su_home_unref(su_home_t *)
Unreference a su_home_t object.
Definition su_alloc.c:650

Note
  For historical reasons, su_home_unref() is also known as su_home_zap().

As you might have guessed, it is also possible to use reference counting with home objects. The function su_home_ref() increases the reference count, su_home_unref() decreases it. A newly allocated or initialized home object has reference count of 1.

Note
  Please note that while it is possible to create new references to secondary home objects which have a parent home, the secondary home objects will always be destroyed when the parent home is destroyed even if there are other references left to them.

The memory blocks in a cloned home object are freed when the object with home itself is freed:

su_free(tophome, ctx);
su_free
void su_free(su_home_t *h, void *)
Free a memory block.
Definition su_alloc.c:802

Note

The su_home_destroy() function is deprecated as it does not free the home object itself. Like su_home_deinit(), it should be called only on home objects with reference count of 1.

The function su_home_init() initializes a home object structure. When the initialized home object is destroyed or deinitialized or its reference count reaches zero, the memory allocate thorugh it reclaimed but the home object structure itself is not freed.

# Destructors

It is possible to give a destructor function to a home object. The destructor releases other resources associated with the home object besides memory. The destructor function will be called when the reference count of home reaches zero (upon calling su_home_unref()) or the home object is otherwise deinitialized (calling su_home_deinit() on objects allocated from stack).

# Combining Allocations

In some cases, an operation that makes multiple memory allocations may fail, making those allocations redundant. If the allocations are made through a temporary home, they can be conveniently freed by calling su_home_deinit(), for instance. If, however, the operation is successful, and one wants to keep the allocations, the allocations can be combined into an existing home with su_home_move(). For example,

int example(su_home_t *home, ...)
{
su_home_t temphome[1] = { SU_HOME_INIT(temphome) };
... do lot of allocations with temphome ...
if (success)
su_home_move(home, temphome);
su_home_deinit(temphome);
return success;
}
su_home_move
int su_home_move(su_home_t *dst, su_home_t *src)
Move allocations from a su_home_t object to another.
Definition su_alloc.c:1087
su_home_deinit
void su_home_deinit(su_home_t *h)
Free memory blocks allocated through home.
Definition su_alloc.c:1060

Note that the temphome is deinitialized in every case, but when operation is successful, the allocations are moved from temphome to home.

# Threadsafe Operation

If multiple threads need to access same home object, it must be marked as threadsafe by calling su_home_threadsafe() with the home pointer as argument. The threadsafeness is not inherited by clones.

The threadsafe home objects can be locked and unlocked with su_home_mutex_lock() and su_home_mutex_unlock(). These operations are no-op on home object that is not threadsafe.

# Preloading a Memory Home

In some situations there is quite heavy overhead if the global heap allocator is used. The overhead caused by the large number of small allocations can be reduced by using su_home_preload(): it allocates or preloads some a memory to home to be used as a kind of private heap. The preloaded memory area is then used to satisfy small enough allocations. For instance, the SIP parser typically preloads some 2K of memory when it starts to parse the message.

# Using Stack

In some situation, it is sensible to use memory allocated from stack for some operations. The su_home_auto() function can be used for that purpose. The memory area from stack is used to satisfy the allocations as far as possible; if it is not enough, allocation is made from heap.

The word auto refers to the automatic scope; however, the home object that was initialized with su_home_auto() must be explicitly deinitialized with su_home_deinit() or su_home_unref() when the program exits the scope where the stack frame used in su_home_auto() was allocated.

## Function Documentation

## su_home_threadsafe()

int su_home_threadsafe | ( | su_home_t * | home | ) |

Convert su_home_t object to a thread-safe one.

Convert a memory home object as thread-safe by allocating mutexes and modifying function pointers in su_alloc.c module.

Parameters

  home | memory home object to be converted thread-safe.

Return values

  0 | when successful,
  -1 | upon an error.

## su_strdup()

char * su_strdup | ( | su_home_t * | home,
|  | char const * | s )

Duplicate a string, allocate memory from home.

The function su_strdup() duplicates the string s. It allocates `strlen(s)+1` bytes from home, copies the contents of s to the newly allocated memory, and returns pointer to the duplicated string.

Parameters

  home | pointer to memory home
  s | string to be duplicated

Returns
  The function su_strdup() returns pointer to the newly created string, or `NULL` upon an error.

Sofia-SIP 1.12.11devel - Copyright (C) 2006 Nokia Corporation. All rights reserved. Licensed under the terms of the GNU Lesser General Public License.