24 #ifndef LIBTHREADAR_TAMPON_H
25 #define LIBTHREADAR_TAMPON_H
130 void feed(T* ptr,
unsigned int written);
145 void fetch(T* & ptr,
unsigned int & num);
190 bool is_quiet_full()
const {
unsigned int tmp = next_feed; shift_by_one(tmp);
return tmp == fetch_head; };
195 unsigned int size()
const {
return table_size; };
203 unsigned int load()
const {
return fetch_head <= next_feed ? next_feed - fetch_head : table_size - (fetch_head - next_feed); };
218 unsigned int data_size;
220 atom() { mem = NULL; data_size = 0; };
225 unsigned int table_size;
226 unsigned int alloc_size;
227 unsigned int next_feed;
228 unsigned int next_fetch;
229 unsigned int fetch_head;
232 mutex waiting_feeder;
233 mutex waiting_fetcher;
236 bool feeder_lock_track;
237 bool fetcher_go_lock;
238 bool fetcher_lock_track;
240 bool is_empty_no_lock()
const {
return next_feed == fetch_head && !full; };
243 bool has_readable_block_next_no_lock()
const {
return next_feed != next_fetch || full; }
246 void shift_by_one(
unsigned int & x)
const;
249 void shift_back_by_one(
unsigned int & x)
const;
255 void shift_by_one_data_in_range(
unsigned int begin,
unsigned int end);
261 table_size = max_block;
262 table =
new atom[table_size];
267 alloc_size = block_size;
270 for(
unsigned int i = 0 ; i < table_size ; ++i)
272 table[i].mem =
new T[alloc_size];
273 if(table[i].mem == NULL)
275 table[i].data_size = 0;
281 for(
unsigned int i = 0; i < table_size ; ++i)
283 if(table[i].mem != NULL)
284 delete [] table[i].mem;
303 for(
unsigned int i = 0 ; i < table_size ; ++i)
305 if(table[i].mem != NULL)
306 delete [] table[i].mem;
320 feeder_go_lock =
true;
321 feeder_lock_track =
true;
325 if(feeder_lock_track)
327 feeder_lock_track =
false;
328 waiting_feeder.lock();
335 ptr = table[next_feed].mem;
343 feed_outside =
false;
345 if(ptr != table[next_feed].mem)
346 throw exception_range(
"returned ptr is not the one given earlier for feeding");
347 table[next_feed].data_size = num;
350 shift_by_one(next_feed);
351 if(next_feed == fetch_head)
355 fetcher_go_lock =
false;
356 waiting_fetcher.unlock();
365 feed_outside =
false;
366 if(ptr != table[next_feed].mem)
367 throw exception_range(
"returned ptr is not the one given earlier for feeding");
376 if(!has_readable_block_next_no_lock())
378 fetcher_go_lock =
true;
379 fetcher_lock_track =
true;
383 if(fetcher_lock_track)
385 fetcher_lock_track =
false;
386 waiting_fetcher.lock();
392 fetch_outside =
true;
393 ptr = table[next_fetch].mem;
394 num = table[next_fetch].data_size;
401 fetch_outside =
false;
402 if(ptr != table[next_fetch].mem)
403 throw exception_range(
"returned ptr is no the one given earlier for fetching");
406 if(next_fetch == fetch_head)
411 shift_by_one(fetch_head);
412 next_fetch = fetch_head;
417 unsigned int tmp = next_fetch;
421 shift_by_one_data_in_range(tmp, next_feed);
428 shift_back_by_one(next_feed);
431 tmp_tom = table[next_feed];
432 table[next_feed] = table[tmp];
433 table[tmp] = tmp_tom;
441 feeder_go_lock =
false;
442 waiting_feeder.unlock();
451 fetch_outside =
false;
453 if(ptr != table[next_fetch].mem)
454 throw exception_range(
"returned ptr is not the one given earlier for fetching");
455 table[next_fetch].data_size = new_num;
459 unsigned int new_num)
461 fetch_push_back(ptr, new_num);
463 if(full && next_fetch == next_feed)
464 throw exception_range(
"cannot skip the last fed block when the tampon is full");
465 shift_by_one(next_fetch);
472 throw exception_range(
"cannot skip back fetching while a block is being fetched");
473 next_fetch = fetch_head;
485 ret = has_readable_block_next_no_lock();
500 ret = is_empty_no_lock();
511 fetch_outside =
false;
512 feed_outside =
false;
514 feeder_go_lock =
false;
515 feeder_lock_track =
false;
516 fetcher_go_lock =
false;
517 fetcher_lock_track =
false;
518 (void)waiting_feeder.try_lock();
519 (void)waiting_fetcher.try_lock();
529 template <
class T>
void tampon<T>::shift_back_by_one(
unsigned int & x)
const
537 template <
class T>
void tampon<T>::shift_by_one_data_in_range(
unsigned int begin,
unsigned int end)
542 unsigned int prev = begin;
543 shift_back_by_one(prev);
544 T* not_squeezed = table[prev].mem;
548 table[prev] = table[begin];
553 table[prev].mem = not_squeezed;
554 table[prev].data_size = 0;
void fetch_push_back(T *ptr, unsigned int new_num)
fetcher call - step 2 alternative
#define THREADAR_BUG
Macro used to throw an exception_bug when execution reach that statement.
defines the mutex C++ class
Class tampon provides asynchronous communication between two threads.
void fetch(T *&ptr, unsigned int &num)
fetcher call - step 1
defines a set of exceptions that are used by libthreadar to report error situations ...
void reset()
reset the object fields and mutex as if the object was just created
bool is_not_full() const
to know whether the tampon is not full
tampon(unsigned int max_block, unsigned int block_size)
constructor
Exception used to report memory allocation failures.
bool has_readable_block_next() const
to known whether next fetch will be blocking (not skipped blocks)
void fetch_recycle(T *ptr)
fetcher call - step 2
void fetch_skip_back()
reactivate all skipped blocks, next fetch() will be the oldest available block
void get_block_to_feed(T *&ptr, unsigned int &num)
feeder call - step 1
unsigned int load() const
returns the current number of blocks currently used in the tampon (fed but not fetched) ...
bool is_quiet_full() const
returns true if only one slot is available before filling the tampon
unsigned int size() const
returns the size of the tampon in maximum number of block it can contain
void unlock()
unlock the mutex
unsigned int block_size() const
returns the allocation size of each block
void fetch_push_back_and_skip(T *ptr, unsigned int new_num)
put back the fetched block and skip to next block for the next fetch()
void feed_cancel_get_block(T *ptr)
feeder call - step 2 alternative
void lock()
lock the mutex
bool is_not_empty() const
to know whether the tampon is not empty
bool is_full() const
for feeder to know whether the next call to get_block_to_feed() will be blocking
void feed(T *ptr, unsigned int written)
feeder call - step 2
This is the only namespace used in libthreadar and all symbols provided by libthreadar are member of ...
Exception used to report out or range value or argument.
bool is_empty() const
to know whether the tampon has objects (readable or skipped)