24 #ifndef LIBTHREADAR_TAMPON_H
25 #define LIBTHREADAR_TAMPON_H
140 void feed(T* ptr,
unsigned int written);
155 void fetch(T* & ptr,
unsigned int & num);
200 bool is_quiet_full()
const {
unsigned int tmp = next_feed; shift_by_one(tmp);
return tmp == fetch_head; };
205 unsigned int size()
const {
return table_size; };
213 unsigned int load()
const {
return fetch_head <= next_feed ? next_feed - fetch_head : table_size - (fetch_head - next_feed); };
223 unsigned int data_size;
225 atom() { mem =
nullptr; data_size = 0; };
230 unsigned int table_size;
231 unsigned int alloc_size;
232 unsigned int next_feed;
233 unsigned int next_fetch;
234 unsigned int fetch_head;
237 mutex waiting_feeder;
238 mutex waiting_fetcher;
241 bool feeder_lock_track;
242 bool fetcher_go_lock;
243 bool fetcher_lock_track;
245 bool is_empty_no_lock()
const {
return next_feed == fetch_head && !full; };
248 bool has_readable_block_next_no_lock()
const {
return next_feed != next_fetch || full; }
251 void shift_by_one(
unsigned int & x)
const;
254 void shift_back_by_one(
unsigned int & x)
const;
260 void shift_by_one_data_in_range(
unsigned int begin,
unsigned int end);
266 table_size = max_block;
267 table =
new atom[table_size];
272 alloc_size = block_size;
275 for(
unsigned int i = 0 ; i < table_size ; ++i)
277 table[i].mem =
new T[alloc_size];
278 if(table[i].mem ==
nullptr)
280 table[i].data_size = 0;
286 for(
unsigned int i = 0; i < table_size ; ++i)
288 if(table[i].mem !=
nullptr)
289 delete [] table[i].mem;
308 for(
unsigned int i = 0 ; i < table_size ; ++i)
310 if(table[i].mem !=
nullptr)
311 delete [] table[i].mem;
325 feeder_go_lock =
true;
326 feeder_lock_track =
true;
330 if(feeder_lock_track)
332 feeder_lock_track =
false;
333 waiting_feeder.lock();
340 ptr = table[next_feed].mem;
348 feed_outside =
false;
350 if(ptr != table[next_feed].mem)
351 throw exception_range(
"returned ptr is not the one given earlier for feeding");
352 table[next_feed].data_size = num;
355 shift_by_one(next_feed);
356 if(next_feed == fetch_head)
360 fetcher_go_lock =
false;
361 waiting_fetcher.unlock();
370 feed_outside =
false;
371 if(ptr != table[next_feed].mem)
372 throw exception_range(
"returned ptr is not the one given earlier for feeding");
381 if(!has_readable_block_next_no_lock())
383 fetcher_go_lock =
true;
384 fetcher_lock_track =
true;
388 if(fetcher_lock_track)
390 fetcher_lock_track =
false;
391 waiting_fetcher.lock();
397 fetch_outside =
true;
398 ptr = table[next_fetch].mem;
399 num = table[next_fetch].data_size;
406 fetch_outside =
false;
407 if(ptr != table[next_fetch].mem)
408 throw exception_range(
"returned ptr is no the one given earlier for fetching");
411 if(next_fetch == fetch_head)
416 shift_by_one(fetch_head);
417 next_fetch = fetch_head;
422 unsigned int tmp = next_fetch;
426 shift_by_one_data_in_range(tmp, next_feed);
433 shift_back_by_one(next_feed);
436 tmp_tom = table[next_feed];
437 table[next_feed] = table[tmp];
438 table[tmp] = tmp_tom;
446 feeder_go_lock =
false;
447 waiting_feeder.unlock();
456 fetch_outside =
false;
458 if(ptr != table[next_fetch].mem)
459 throw exception_range(
"returned ptr is not the one given earlier for fetching");
460 table[next_fetch].data_size = new_num;
464 unsigned int new_num)
466 fetch_push_back(ptr, new_num);
468 if(full && next_fetch == next_feed)
469 throw exception_range(
"cannot skip the last fed block when the tampon is full");
470 shift_by_one(next_fetch);
477 throw exception_range(
"cannot skip back fetching while a block is being fetched");
478 next_fetch = fetch_head;
490 ret = has_readable_block_next_no_lock();
505 ret = is_empty_no_lock();
516 fetch_outside =
false;
517 feed_outside =
false;
519 feeder_go_lock =
false;
520 feeder_lock_track =
false;
521 fetcher_go_lock =
false;
522 fetcher_lock_track =
false;
523 (void)waiting_feeder.try_lock();
524 (void)waiting_fetcher.try_lock();
534 template <
class T>
void tampon<T>::shift_back_by_one(
unsigned int & x)
const
542 template <
class T>
void tampon<T>::shift_by_one_data_in_range(
unsigned int begin,
unsigned int end)
547 unsigned int prev = begin;
548 shift_back_by_one(prev);
549 T* not_squeezed = table[prev].mem;
553 table[prev] = table[begin];
558 table[prev].mem = not_squeezed;
559 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
DEPRECATED see fast_tampon instead!
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
tampon & operator=(const tampon &ref)=delete
no assignment operator
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)