Product SiteDocumentation Site

Name

tc_waitq_init, tc_waitq_wakeup_all, tc_waitq_wakeup_one, tc_waitq_wait_event, tc_waitq_unregister — libtc wait queue functions

Synopsis

#include <tc/threaded_cr.h>

void tc_waitq_init(struct tc_waitq *wq);

enum tc_rv tc_waitq_wait_event(struct tc_waitq *wq, CONDITION);

void tc_waitq_wakeup_all(struct tc_waitq *wq);

void tc_waitq_wakeup_one(struct tc_waitq *wq);

void tc_waitq_unregister(struct tc_waitq *wq);

Description

tc_waitqs are can be used to wait for an arbitrary condition in one tc_thread.
Before a tc_waitq may be used, it has to be initialized with a call to tc_waitq_init(). It may not be used after a call to its destructor tc_waitq_unregister().
When one tc_thread potentially changes some state, so that a waiting for condition might become true for an other thread it can trigger re-evaluation of the waiting condition in other threads by calls to tc_waitq_wakeup_all() or tc_waitq_wakeup_one(). The former wakes all tc_threads sleeping on that tc_waitq, while the latter wakes only one.
The tc_waitq_wait_event() macro sleeps on an tc_waitq until the CONDITION evaluates to true.

Return value

tc_waitq_wait_event() returns RV_OK if the condition became true and RV_INTR if the call was interrupted by a tc_signal.

Example

The following example outlines a simple memory allocator, that blocks further allocations when it is exhausted.
struct mempool {
	atomic_t available;
	struct tc_waitq wq;
};

void mempool_init(struct mempool *mp, int size)
{
	atomic_set(&mp->available, size);
	tc_waitq_init(&mp->wq);
}

static int _try_alloc(struct mempool *mp, int size)
{
	if (atomic_sub_return(size, &mp->available) > 0)
		return 1;

	atomic_add_return(size, &mp->available);
	return 0;
}

void *mempool_alloc(struct mempool *mp, int size)
{
	void *rv;

	if (tc_waitq_wait_event(&mp->wq, _try_alloc(mp, size) == 1) != RV_OK)
		return NULL;

	rv = malloc(size);
	if (!rv)
		atomic_add_return(size, &mp->available);
	return rv;
}

void mempool_free(struct mempool *mp, void* mem, int size)
{
	free(mem);
	atomic_add_return(size, &mp->available);
	tc_waitq_wakeup(&mp->wq);
}
      

Author

Philipp Reisner