Files CCore/inc/task/MultiSem.h CCore/src/task/MultiSem.cpp
MultiSem is a small set of semaphores. Each can be given. But the take operation takes from any of them, if some of them is available. The take operation uses the round-robin priority algorithm to equalize semaphores.
Consider the example with apples. In the multi-semaphore case, there are several baskets for different sorts of apples. Somebody can put an apple to the one of the basket. And somebody can take an apple from a non-empty basket. To do this, he is looking for a non-empty basket in the cyclic order, starting from some basket. Next time the starting basket is changed to the following. If all baskets are empty, he waits.
template <ulen Len>
class MultiSem : public Funchor_nocopy
{
....
public:
// constructors
MultiSem();
explicit MultiSem(TextLabel name);
~MultiSem();
// give
void give(ulen index); // [1,Len]
// take
ulen try_take(); // [0,Len]
ulen take(); // [1,Len]
ulen take(MSec timeout); // [0,Len]
ulen take(TimeScope time_scope); // [0,Len]
// give<Index>
template <ulen Index> // [1,Len]
void give_index() { give(Index); }
// functions
template <ulen Index>
Function<void (void)> function_give() { return FunctionOf(this,&MultiSemBase::give_index<Index>); }
};
give() increments the specified semaphore counter. index is the counter 1-based index, it must be in the range [1,Len].
try_take() tries to decrement one of the semaphore counters. This method never blocks. The return value is the counter 1-based index, if the method was successful. Otherwise it is zero.
take() decrements one of the semaphore counters. It may block the calling thread indefinitely, until the operation becomes possible.
take(MSec) and take(TimeScope) are timed variants of the take(). These methods wait up to the specified timeout is expired, then operation failed. The return value is zero in this case.
HCore MultiSem has the common interface.
template <ulen Len>
class MultiSem : public Funchor_nocopy
{
....
public:
// constructors
MultiSem();
explicit MultiSem(TextLabel name);
~MultiSem();
// give
void give(ulen index); // [1,Len]
// take
ulen try_take(); // [0,Len]
ulen take(); // [1,Len]
ulen take(MSec timeout); // [0,Len]
ulen take(TimeScope time_scope); // [0,Len]
// give<Index>
template <ulen Index> // [1,Len]
void give_index() { give(Index); }
// functions
template <ulen Index>
Function<void (void)> function_give() { return FunctionOf(this,&MultiSemBase::give_index<Index>); }
};
XCore MultiSem is essentially the same, but has give() method variants for different execution contexts.
template <ulen Len>
class MultiSem : public Funchor_nocopy
{
....
public:
// constructors
MultiSem();
explicit MultiSem(TextLabel name);
~MultiSem();
TextLabel getName() const { return name; }
// give
void give(ulen index); // [1,Len]
void give_int(ulen index); // [1,Len]
void give_any(ulen index); // [1,Len]
// take
ulen try_take(); // [0,Len]
ulen take(); // [1,Len]
ulen take(MSec timeout); // [0,Len]
ulen take(TimeScope time_scope); // [0,Len]
// give<Index>
template <ulen Index> // [1,Len]
void give_index() { give(Index); }
template <ulen Index> // [1,Len]
void give_index_int() { give_int(Index); }
template <ulen Index> // [1,Len]
void give_index_any() { give_any(Index); }
// functions
template <ulen Index>
Function<void (void)> function_give() { return FunctionOf(this,&MultiSemBase::give_index<Index>); }
template <ulen Index>
Function<void (void)> function_give_int() { return FunctionOf(this,&MultiSemBase::give_index_int<Index>); }
template <ulen Index>
Function<void (void)> function_give_any() { return FunctionOf(this,&MultiSemBase::give_index_any<Index>); }
};