24#ifndef LIBTHREADAR_TAMPON_HPP
25#define LIBTHREADAR_TAMPON_HPP
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;
Exception used to report memory allocation failures.
Exception used to report out or range value or argument.
void unlock()
unlock the mutex
void lock()
lock the mutex
DEPRECATED see fast_tampon instead!
unsigned int size() const
returns the size of the tampon in maximum number of block it can contain
bool is_full() const
for feeder to know whether the next call to get_block_to_feed() will be blocking
void fetch_recycle(T *ptr)
fetcher call - step 2
bool is_not_full() const
to know whether the tampon is not full
unsigned int load() const
returns the current number of blocks currently used in the tampon (fed but not fetched)
tampon & operator=(const tampon &ref)=delete
no assignment operator
tampon(const tampon &ref)=delete
no copy constructor
unsigned int block_size() const
returns the allocation size of each block
void feed_cancel_get_block(T *ptr)
feeder call - step 2 alternative
bool has_readable_block_next() const
to known whether next fetch will be blocking (not skipped blocks)
tampon(unsigned int max_block, unsigned int block_size)
constructor
bool is_quiet_full() const
returns true if only one slot is available before filling the tampon
void get_block_to_feed(T *&ptr, unsigned int &num)
feeder call - step 1
bool is_not_empty() const
to know whether the tampon is not empty
tampon(tampon &&ref) noexcept=default
no move constructor
void fetch(T *&ptr, unsigned int &num)
fetcher call - step 1
void feed(T *ptr, unsigned int written)
feeder call - step 2
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()
bool is_empty() const
to know whether the tampon has objects (readable or skipped)
void fetch_push_back(T *ptr, unsigned int new_num)
fetcher call - step 2 alternative
void fetch_skip_back()
reactivate all skipped blocks, next fetch() will be the oldest available block
void reset()
reset the object fields and mutex as if the object was just created
defines a set of exceptions that are used by libthreadar to report error situations
#define THREADAR_BUG
Macro used to throw an exception_bug when execution reach that statement.
defines the mutex C++ class
This is the only namespace used in libthreadar and all symbols provided by libthreadar are member of ...