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 | |
char * | su_strdup (su_home_t *home, char const *s) |
Duplicate a string, allocate memory from home. |
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; ... }
A new home memory pool can be created with su_home_new():
struct context *ctx = su_home_new(sizeof (struct context));
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));
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));
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).
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.
The memory blocks in a cloned home object are freed when the object with home itself is freed:
su_free(tophome, ctx);
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.
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).
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; }
Note that the temphome is deinitialized in every case, but when operation is successful, the allocations are moved from temphome to home.
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.
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.
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.
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.
home | pointer to memory home | |
s | string to be duplicated |
NULL
upon an error.