mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
4.8 KiB
158 lines
4.8 KiB
#ifndef __REFERENCE_CNTR_H
|
|
#define __REFERENCE_CNTR_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/** \ingroup cds
|
|
* @{
|
|
*
|
|
* \defgroup cds_ref_cnt Reference counting
|
|
*
|
|
* Experimental functions for reference counting (to simplify
|
|
* this code elsewhere).
|
|
*
|
|
* Reference counter (\ref reference_counter_data_t) holds integer number which
|
|
* should be changed using functions \ref add_reference and \ref
|
|
* remove_reference. Using these functions is the number read/changed from
|
|
* locked section guarded by one mutex from a set of 'group mutexes'.
|
|
*
|
|
* Often used scenario:
|
|
* - list of structures, change in the list (adding, removing) is guarded by
|
|
* one mutex,
|
|
* - each structure has reference counter, when the count is zero, the
|
|
* structure can be removed from the list and freed
|
|
*
|
|
* Note that mutex for adding references is needed because references are not
|
|
* added from critical section guarded by main list mutex but can be added whenever.
|
|
*
|
|
* Typical usage:
|
|
* \code
|
|
* struct some_structure {
|
|
* ...
|
|
* reference_counter_data_t ref;
|
|
* ...
|
|
* };
|
|
*
|
|
* reference_counter_group_t *some_grp;
|
|
*
|
|
* void init()
|
|
* {
|
|
* some_grp = init_reference_counter_group(16);
|
|
* }
|
|
*
|
|
* void destroy()
|
|
* {
|
|
* free_reference_counter_group(some_grp);
|
|
* }
|
|
*
|
|
* ...
|
|
*
|
|
* // adding a member:
|
|
* struct some_struct *ss = malloc(...);
|
|
* init_reference_counter(some_grp, &ss->ref);
|
|
* lock(list);
|
|
* add_to_list(ss);
|
|
* unlock(list);
|
|
*
|
|
* ...
|
|
* // adding a reference doesn't need to lock list
|
|
* // can be done only by a reference owner
|
|
* add_reference(&ss->ref);
|
|
*
|
|
* // releasing a member when not needed for caller and there is
|
|
* // no way how to obtain reference for released member
|
|
* // (no way how to find a member in list)
|
|
* if (remove_reference(&ss->ref)) {
|
|
* // last reference removed
|
|
* lock(list);
|
|
* remove_from_list(ss);
|
|
* free(ss);
|
|
* unlock(list);
|
|
* }
|
|
*
|
|
* // or
|
|
* // releasing a member when not needed for caller and it is possible
|
|
* // to 'search' in the list (reference to released member can be somehow
|
|
* // obtained by inspecting the list):
|
|
* lock(list);
|
|
* if (remove_reference(&ss->ref)) {
|
|
* // last reference removed
|
|
* remove_from_list(ss);
|
|
* free(ss);
|
|
* }
|
|
* unlock(list);
|
|
* \endcode
|
|
*
|
|
* \todo use atomic operations instead of locking
|
|
* @{ */
|
|
|
|
#include <cds/sync.h>
|
|
|
|
/** Structure holding reference counter value. */
|
|
typedef struct {
|
|
int cntr; /**< counter value */
|
|
cds_mutex_t *mutex; /**< mutex asigned to this reference counter */
|
|
} reference_counter_data_t;
|
|
|
|
/** Structure holding information about group of reference counters.
|
|
* It holds array of mutexes which are assigned to single reference
|
|
* counters in this group. The assignment is done using an operation
|
|
* on pointer to reference_counter_data_t. */
|
|
typedef struct {
|
|
int mutex_cnt; /**< number of mutexes for this group */
|
|
|
|
/** number of next mutex to be assigned - this member is NOT
|
|
* read/changed from critical section but it doesn't matter
|
|
* if it will be rewritten between processes because it is used
|
|
* for load distributing only (the worst thing that can happen
|
|
* is that the same mutex is assigned twice) */
|
|
int mutex_to_assign;
|
|
cds_mutex_t mutexes[1]; /**< array of mutexes (allocated together with the structure)*/
|
|
} reference_counter_group_t;
|
|
|
|
/** Initializes reference counter - sets its value to 1.
|
|
* After call to this function, the caller is owner of first
|
|
* reference. From now it can call other functions like
|
|
* \ref add_reference or \ref remove_reference.
|
|
*
|
|
* This function initializes the mutex - it chooses one from
|
|
* group mutexes. The mutex can not be changed after this
|
|
* call (it is only for reading). */
|
|
void init_reference_counter(reference_counter_group_t *grp, reference_counter_data_t *ref);
|
|
|
|
/** Adds reference - increments reference counter.
|
|
* This function can be called only by owner of at least one reference! */
|
|
void add_reference(reference_counter_data_t *ref);
|
|
|
|
/** Returns the value of reference counter. This function is mostly
|
|
* useless. */
|
|
int get_reference_count(reference_counter_data_t *ref);
|
|
|
|
/** Removes reference - decrements reference counter.
|
|
* This function can be called only by owner of at least one reference!
|
|
*
|
|
* \retval 0 if reference removed, but other references exist
|
|
* \retval 1 if removed last reference
|
|
* */
|
|
int remove_reference(reference_counter_data_t *ref);
|
|
|
|
/** Creates and initializes group of reference counters. All reference
|
|
* counters 'belonging' to this group are using the same set of mutexes. */
|
|
reference_counter_group_t *create_reference_counter_group(int mutex_cnt);
|
|
|
|
/** Destroys all resources used by reference counter group.
|
|
* After this function call no reference counter initialized
|
|
* by this group can be used. */
|
|
void free_reference_counter_group(reference_counter_group_t *grp);
|
|
|
|
/** @}
|
|
* @} */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|