Loading...
Searching...
No Matches
Use Counter

Generic object usage counter (get, put and deallocate on zero count). More...

## Files

file | use_count.h
| Generic object usage counter API (get, put and deallocate on zero count).
file | use_count.c
| Generic object usage counter Implementation (get, put and deallocate on zero count).

## Data Structures

struct | osmo_use_count
| Use counter state for one used object, managing N distinct named counters. More...
struct | osmo_use_count_entry
| One named counter in the list managed by osmo_use_count. More...

## Macros

#define | osmo_use_count_get_put(USE_LIST, USE, CHANGE)
| Change the use count for a given use token.

## Typedefs

typedef int(* | osmo_use_count_cb_t) (struct osmo_use_count_entry *use_count_entry, int32_t old_use_count, const char *file, int line)
| Invoked when a use count changes.

## Functions

int | _osmo_use_count_get_put (struct osmo_use_count *uc, const char *use, int32_t change, const char *file, int line)
| Implementation for osmo_use_count_get_put(), which can also be directly invoked to pass source file information.
const char * | osmo_use_count_name_buf (char *buf, size_t buf_len, const struct osmo_use_count *uc)
| Write a comprehensive listing of use counts to a string buffer.
int | osmo_use_count_to_str_buf (char *buf, size_t buf_len, const struct osmo_use_count *uc)
| Write a comprehensive listing of use counts to a string buffer.
char * | osmo_use_count_to_str_c (void *ctx, const struct osmo_use_count *uc)
| Write a comprehensive listing of use counts to a talloc allocated string buffer.
int32_t | osmo_use_count_total (const struct osmo_use_count *uc)
| Return the sum of all use counts, min- and max-clamped at INT32_MIN and INT32_MAX.
int32_t | osmo_use_count_by (const struct osmo_use_count *uc, const char *use)
| Return use count by a single use token.
struct osmo_use_count_entry * | osmo_use_count_find (const struct osmo_use_count *uc, const char *use)
void | osmo_use_count_free (struct osmo_use_count_entry *use_count_entry)
| Deallocate a use count entry.
void | osmo_use_count_make_static_entries (struct osmo_use_count *uc, struct osmo_use_count_entry *buf, size_t buf_n_entries)
| Add N static use token entries to avoid dynamic allocation of use count tokens.
static bool | count_safe (int32_t *val_p, int32_t add)
| Add two int32_t but make sure to min- and max-clamp at INT32_MIN and INT32_MAX, respectively.
static struct osmo_use_count_entry * | osmo_use_count_repurpose_zero_entry (struct osmo_use_count *uc, const char *use)
| Find a use count entry that currently has zero count, and re-use that for this new use token.
static struct osmo_use_count_entry * | osmo_use_count_create (struct osmo_use_count *uc, const char *use)
| Allocate a new use count entry, happens implicitly in osmo_use_count_get_put().

## Detailed Description

Generic object usage counter (get, put and deallocate on zero count).

For an example and a detailed description, see struct osmo_use_count.

## Macro Definition Documentation

## osmo_use_count_get_put

#define osmo_use_count_get_put | ( |  | USE_LIST,
|  |  | USE,
|  |  | CHANGE )

Value:
_osmo_use_count_get_put(USE_LIST, USE, CHANGE, __FILE__, __LINE__)
_osmo_use_count_get_put
int _osmo_use_count_get_put(struct osmo_use_count *uc, const char *use, int32_t change, const char *file, int line)
Implementation for osmo_use_count_get_put(), which can also be directly invoked to pass source file i...
Definition use_count.c:234

Change the use count for a given use token.

Parameters

  USE_LIST | A struct osmo_use_count*, e.g. &my_obj->use_count.
  USE | A use token: arbitrary string (const char*). This must remain valid memory, e.g. string constants.
  CHANGE | Signed integer value to add to the use count: positive means get(), negative means put().

Returns
  Negative on range violations or USE_LIST == NULL, the use_cb()'s return value, or 0 on success.

## Typedef Documentation

## osmo_use_count_cb_t

typedef int(* osmo_use_count_cb_t) (struct osmo_use_count_entry *use_count_entry, int32_t old_use_count, const char *file, int line)

Invoked when a use count changes.

The implementation is free to trigger actions on arbitrary use count changes, typically to free the use_count->talloc_object when the total use count reaches zero.

The implementation may modify use_count_entry->count, for example for handling of get()/put() bugs, to clamp specific use tokens to specific counts, or to prevent the caller from put()ting into negative counts. When returning an error, there is no implicit undo – if errors need to be corrected, this function is responsible for that.

Be aware: use token strings are not copied, and use count entries usually remain listed also when they reach a zero count. This is trivially perfectly ok when using string literals as use tokens. It is also possible to use dynamically allocated string tokens, but should a use token string become invalid memory when reaching zero count, it is the responsibility of this function to set the use_count_entry->use = NULL; this is required to avoid subsequent osmo_use_count_get_put() invocations from calling strcmp() on invalid memory. (Setting use = NULL cannot be done implicitly after this callback invocation, because callback implementations are allowed to completely deallocate the talloc_object and the use_count list entries, and setting use = NULL after that would be a use-after-free.)

Parameters

  [in] | use_count_entry | Use count entry that is being modified.
  [in] | old_use_count | Use count the item had before the change in use count.
  [in] | file | Source file string, passed in as FILE from macro osmo_use_count_get_put().
  [in] | line | Source file line, passed in as LINE from macro osmo_use_count_get_put().

Returns
  0 on success, negative if any undesired use count is reached; this rc will be returned by osmo_use_count_get_put().

## Function Documentation

## _osmo_use_count_get_put()

int _osmo_use_count_get_put | ( | struct osmo_use_count * | uc,
|  | const char * | use,
|  | int32_t | change,
|  | const char * | file,
|  | int | line )

Implementation for osmo_use_count_get_put(), which can also be directly invoked to pass source file information.

For arguments besides file and line, see osmo_use_count_get_put().

Parameters

  [in] | file | Source file path, as in FILE.
  [in] | line | Source file line, as in LINE.

References osmo_use_count_entry::count, count_safe(), osmo_use_count_entry::entry, llist_add_tail(), llist_del(), osmo_use_count_create(), osmo_use_count_find(), osmo_use_count_repurpose_zero_entry(), osmo_use_count_entry::use, osmo_use_count::use_cb, and osmo_use_count::use_counts.

## count_safe()

bool count_safe | ( | int32_t * | val_p,
|  | int32_t | add )

inline static

Add two int32_t but make sure to min- and max-clamp at INT32_MIN and INT32_MAX, respectively.

Referenced by _osmo_use_count_get_put(), and osmo_use_count_total().

## osmo_use_count_by()

int32_t osmo_use_count_by | ( | const struct osmo_use_count * | uc,
|  | const char * | use )

Return use count by a single use token.

Parameters

  [in] | uc | Use counts to look up in.
  [in] | use | Use token.

Returns
  Use count, or 0 if uc is NULL or use token is not present.

References osmo_use_count_entry::count, osmo_use_count_find(), and osmo_use_count_entry::use.

## osmo_use_count_create()

struct osmo_use_count_entry * osmo_use_count_create | ( | struct osmo_use_count * | uc,
|  | const char * | use )

static

Allocate a new use count entry, happens implicitly in osmo_use_count_get_put().

References osmo_use_count_entry::entry, INIT_LLIST_HEAD, llist_add_tail(), llist_head::next, osmo_use_count::talloc_object, osmo_use_count_entry::use, osmo_use_count_entry::use_count, and osmo_use_count::use_counts.

Referenced by _osmo_use_count_get_put().

## osmo_use_count_find()

struct osmo_use_count_entry * osmo_use_count_find | ( | const struct osmo_use_count * | uc,
|  | const char * | use )

References osmo_use_count_entry::entry, llist_for_each_entry, llist_head::next, osmo_use_count_entry::use, and osmo_use_count::use_counts.

Referenced by _osmo_use_count_get_put(), and osmo_use_count_by().

## osmo_use_count_free()

void osmo_use_count_free | ( | struct osmo_use_count_entry * | use_count_entry | ) |

Deallocate a use count entry.

Normally, this is not necessary – it is ok and even desirable to leave use count entries around even when they reach a count of zero, until the use_count->talloc_object deallocates and removes all of them in one flush. This avoids repeated allocation and deallocation for use tokens, because use count entries that have reached zero count are repurposed for any other use tokens. A cleanup makes sense only if a very large number of differing use tokens surged at the same time, and the owning object will not be deallocated soon; if so, this should be done by the osmo_use_count_cb_t implementation.

osmo_use_count_free() must not be called on use count entries that were added by osmo_use_count_make_static_entries(). This is the responsibility of the osmo_use_count_cb_t() implementation.

Parameters

  [in] | use_count_entry | Use count entry to unlist and free.

References osmo_use_count_entry::entry, and llist_del().

## osmo_use_count_make_static_entries()

void osmo_use_count_make_static_entries | ( | struct osmo_use_count * | uc,
|  | struct osmo_use_count_entry * | buf,
|  | size_t | buf_n_entries )

Add N static use token entries to avoid dynamic allocation of use count tokens.

When not using this function, use count entries are talloc allocated from uc->talloc_object as talloc context. This means that there are small dynamic allocations for each use count token. osmo_use_count_get_put() normally leaves zero-count entries around and re-purposes them later, so the number of small allocations is at most the number of concurrent differently-named uses of the same object. If that is not enough, this function allows completely avoiding dynamic use count allocations, by adding N static entries with a zero count and a NULL use token. They will be used by osmo_use_count_get_put(), and, if the caller avoids using osmo_use_count_free(), the osmo_use_count implementation never deallocates them. The idea is that the entries are members of the uc->talloc_object, or that they will by other means be implicitly deallocated by the talloc_object. It is fine to call osmo_use_count_make_static_entries(buf_n_entries=N) and later have more than N concurrent uses, i.e. it is no problem to mix static and dynamic entries. To completely avoid dynamic use count entries, N has to >= the maximum number of concurrent differently-named uses that will occur in the lifetime of the talloc_object.

struct my_object { struct osmo_use_count use_count; struct osmo_use_count_entry use_count_buf[3]; // planning for 3 concurrent users };

void example() { struct my_object *o = talloc_zero(ctx, struct my_object); osmo_use_count_make_static_entries(&o->use_count, o->use_count_buf, ARRAY_SIZE(o->use_count_buf)); }

References osmo_use_count_entry::entry, INIT_LLIST_HEAD, llist_add_tail(), llist_head::next, osmo_use_count_entry::use_count, and osmo_use_count::use_counts.

## osmo_use_count_name_buf()

const char * osmo_use_count_name_buf | ( | char * | buf,
|  | size_t | buf_len,
|  | const struct osmo_use_count * | uc )

Write a comprehensive listing of use counts to a string buffer.

Reads like "12 (3*barring,fighting,8*kungfoo)".

Parameters

  [in,out] | buf | Destination buffer.
  [in] | buf_len | sizeof(buf).
  [in] | uc | Use counts to print.

Returns
  buf, always nul-terminated (except when buf_len < 1).

References osmo_use_count_to_str_buf().

## osmo_use_count_repurpose_zero_entry()

struct osmo_use_count_entry * osmo_use_count_repurpose_zero_entry | ( | struct osmo_use_count * | uc,
|  | const char * | use )

static

Find a use count entry that currently has zero count, and re-use that for this new use token.

References osmo_use_count_entry::count, osmo_use_count_entry::entry, llist_for_each_entry, llist_head::next, osmo_use_count_entry::use, and osmo_use_count::use_counts.

Referenced by _osmo_use_count_get_put().

## osmo_use_count_to_str_buf()

int osmo_use_count_to_str_buf | ( | char * | buf,
|  | size_t | buf_len,
|  | const struct osmo_use_count * | uc )

Write a comprehensive listing of use counts to a string buffer.

Reads like "12 (3*barring,fighting,8*kungfoo)".

Parameters

  [in,out] | buf | Destination buffer.
  [in] | buf_len | sizeof(buf).
  [in] | uc | Use counts to print.

Returns
  number of bytes that would be written, like snprintf().

References osmo_strbuf::buf, osmo_strbuf::chars_needed, osmo_use_count_entry::count, osmo_use_count_entry::entry, llist_for_each_entry, llist_head::next, OSMO_STRBUF_PRINTF, osmo_use_count_total(), osmo_use_count_entry::use, and osmo_use_count::use_counts.

Referenced by osmo_use_count_name_buf(), and osmo_use_count_to_str_c().

## osmo_use_count_to_str_c()

char * osmo_use_count_to_str_c | ( | void * | ctx,
|  | const struct osmo_use_count * | uc )

Write a comprehensive listing of use counts to a talloc allocated string buffer.

Reads like "12 (3*barring,fighting,8*kungfoo)".

Parameters

  [in] | ctx | talloc pool to allocate from.
  [in] | uc | Use counts to print.

Returns
  buf, always nul-terminated.

References OSMO_NAME_C_IMPL, and osmo_use_count_to_str_buf().

## osmo_use_count_total()

int32_t osmo_use_count_total | ( | const struct osmo_use_count * | uc | ) |

Return the sum of all use counts, min- and max-clamped at INT32_MIN and INT32_MAX.

Parameters

  [in] | uc | Use counts to sum up.

Returns
  Accumulated counts, or 0 if uc is NULL.

References osmo_use_count_entry::count, count_safe(), osmo_use_count_entry::entry, llist_for_each_entry, llist_head::next, and osmo_use_count::use_counts.

Referenced by osmo_use_count_to_str_buf().