2#define TAMER_XBASE_HH 1
20#include <tamer/autoconf.h>
24template <
typename R>
class one_argument_rendezvous_tag {};
25template <
typename R>
class zero_argument_rendezvous_tag {};
28template <
typename T0 = void,
typename T1 = void,
typename T2 = void,
29 typename T3 =
void>
class event;
30#if TAMER_HAVE_PREEVENT
31template <
typename R,
typename T0 =
void>
class preevent;
36class tamer_error :
public std::runtime_error {
public:
37 explicit tamer_error(
const std::string& arg)
38 : runtime_error(arg) {
49const int cancel = -ECANCELED;
50const int timeout = -ETIMEDOUT;
51const int signal = -EINTR;
52const int overflow = -EOVERFLOW;
53const int closed = -EPIPE;
54const int destroy = -ECANCELED;
61class abstract_rendezvous;
62class blocking_rendezvous;
63class explicit_rendezvous;
66class simple_event {
public:
69 inline simple_event() TAMER_NOEXCEPT;
70 inline simple_event(abstract_rendezvous& r, uintptr_t rid,
71 const
char* file,
int line) TAMER_NOEXCEPT;
72 inline ~simple_event() TAMER_NOEXCEPT;
74 static inline
void use(simple_event* e, const
char* file = __builtin_FILE(),
int line = __builtin_LINE()) TAMER_NOEXCEPT;
75 static inline
void unuse(simple_event* e, const
char* file = __builtin_FILE(),
int line = __builtin_LINE()) TAMER_NOEXCEPT;
76 static inline
void unuse_clean(simple_event* e, const
char* file = __builtin_FILE(),
int line = __builtin_LINE()) TAMER_NOEXCEPT;
77 inline
bool unused() const;
79 inline explicit operator
bool() const;
80 inline
bool empty() const;
81 inline abstract_rendezvous* rendezvous() const;
82 inline uintptr_t rid() const;
83 inline simple_event* next() const;
84 inline
bool shared() const;
85 inline
bool has_at_trigger() const;
87 inline const
char* file_annotation() const;
88 inline
int line_annotation() const;
90 inline
void simple_trigger(
bool values);
91 static
void simple_trigger(simple_event* x,
bool values) TAMER_NOEXCEPT;
92 void trigger_list_for_remove() TAMER_NOEXCEPT;
94 static inline
void at_trigger(simple_event* x, simple_event* at_trigger);
95 static inline
void at_trigger(simple_event* x,
void (*f)(
void*),
void* arg);
98 abstract_rendezvous* _r;
100 simple_event* _r_next;
101 simple_event** _r_pprev;
102 void (*at_trigger_f_)(
void*);
103 void* at_trigger_arg_;
106 int line_annotation_;
107 const char* file_annotation_;
110 simple_event(
const simple_event&) =
delete;
111 simple_event(simple_event&&) =
delete;
112 simple_event& operator=(
const simple_event&) =
delete;
113 simple_event& operator=(
const simple_event&&) =
delete;
115 void unuse_trigger() TAMER_NOEXCEPT;
116 static inline event<> at_trigger_event(
void (*f)(
void*),
void* arg);
117 static
void trigger_hook(
void* arg);
118 static
void hard_at_trigger(simple_event* x,
void (*f)(
void*),
void* arg);
120 void print(const
char* prefix, const
char* filename =
nullptr,
int line = 0);
122 friend class abstract_rendezvous;
123 friend class explicit_rendezvous;
127enum rendezvous_type {
134class abstract_rendezvous {
136 explicit abstract_rendezvous(rendezvous_type rtype) TAMER_NOEXCEPT
139 inline ~abstract_rendezvous() TAMER_NOEXCEPT;
141 inline rendezvous_type rtype()
const {
142 return rendezvous_type(rtype_);
145 bool is_volatile()
const;
146 const char* rtype_name()
const;
149 simple_event* waiting_ =
nullptr;
152 inline void remove_waiting() TAMER_NOEXCEPT;
155 abstract_rendezvous(const abstract_rendezvous&) = delete;
156 abstract_rendezvous(abstract_rendezvous&&) = delete;
157 abstract_rendezvous& operator=(const abstract_rendezvous&) = delete;
158 abstract_rendezvous& operator=(abstract_rendezvous&&) = delete;
160 void hard_remove_waiting() TAMER_NOEXCEPT;
162 friend class simple_event;
171 inline void add_blocked(closure* c);
172 inline void make_unblocked(closure* c);
174 inline closure* pop_unblocked();
176 inline unsigned nclosure_slots()
const;
177 inline closure* closure_slot(
unsigned i)
const;
180 inline bool has_unblocked()
const;
181 inline void run_unblocked();
182 inline void clear_unblocked();
184 static simple_driver immediate_driver;
193 mutable unsigned cfree_;
194 mutable unsigned cunblocked_;
195 unsigned cunblocked_tail_;
198 simple_driver(
const simple_driver&) =
delete;
199 simple_driver(simple_driver&&) =
delete;
200 simple_driver& operator=(
const simple_driver&) =
delete;
201 simple_driver& operator=(simple_driver&&) =
delete;
203 void add(closure* c);
206 friend class blocking_rendezvous;
207 friend class closure;
210class blocking_rendezvous :
public abstract_rendezvous {
212 explicit inline blocking_rendezvous(rendezvous_type rtype) TAMER_NOEXCEPT;
213 inline ~blocking_rendezvous() TAMER_NOEXCEPT;
215 inline
bool blocked() const;
216 inline
bool volatile_blocked() const;
218 inline
void block(simple_driver* driver, closure& c,
unsigned position);
219 inline
void block(closure& c,
unsigned position);
220 inline
void unblock();
223 closure* blocked_closure_;
225 void hard_free() TAMER_NOEXCEPT;
227 friend class abstract_rendezvous;
228 friend class simple_driver;
229 friend struct driver_timerset;
232class explicit_rendezvous : public blocking_rendezvous {
234 inline explicit_rendezvous() TAMER_NOEXCEPT
235 : blocking_rendezvous(rexplicit),
236 ready_(), ready_ptail_(&ready_) {
238 inline ~explicit_rendezvous() {
239 TAMER_DEBUG_ASSERT(!ready_);
243 simple_event* ready_;
244 simple_event** ready_ptail_;
246 inline uintptr_t pop_ready() {
247 simple_event* e = ready_;
248 if (!(ready_ = e->_r_next)) {
249 ready_ptail_ = &ready_;
251 uintptr_t x = e->rid();
252 simple_event::unuse_clean(e);
255 inline void remove_ready() {
256 while (simple_event* e = ready_) {
258 simple_event::unuse_clean(e);
260 ready_ptail_ = &ready_;
263 friend class simple_event;
266class functional_rendezvous :
public abstract_rendezvous {
268 typedef void (*hook_type)(functional_rendezvous* fr,
269 simple_event* e,
bool values);
271 inline functional_rendezvous(
void (*f)(functional_rendezvous* fr,
272 simple_event* e,
bool values) TAMER_NOEXCEPT)
273 : abstract_rendezvous(rfunctional), f_(f) {
275 inline functional_rendezvous(rendezvous_type rtype,
276 void (*f)(functional_rendezvous* fr,
277 simple_event* e,
bool values) TAMER_NOEXCEPT)
278 : abstract_rendezvous(rtype), f_(f) {
280 inline ~functional_rendezvous() {
285 void (*f_)(functional_rendezvous* r,
286 simple_event* e,
bool values) TAMER_NOEXCEPT;
288 friend class simple_event;
291typedef void (*closure_activator)(closure*);
295 typedef closure tamer_closure_type;
296 closure_activator tamer_activator_;
297 unsigned tamer_block_position_;
298 unsigned tamer_driver_index_;
299 simple_driver* tamer_blocked_driver_;
300 closure* tamer_closures_next_;
301 closure** tamer_closures_pprev_;
303 int tamer_location_line_;
304 const char* tamer_location_file_;
305 std::string* tamer_description_;
309 inline bool has_location()
const;
310 inline bool has_description()
const;
311 inline const char* location_file()
const;
312 inline int location_line()
const;
313 std::string location()
const;
314 inline std::string description()
const;
315 std::string location_description()
const;
317 inline void initialize_closure(closure_activator f, ...);
318 inline void initialize_closure(closure_activator f, tamed_class* k);
319 inline void set_location(
const char* file,
int line);
320 inline void set_description(std::string description);
322 inline void exit_at_destroy(tamed_class* k);
324 inline void unblock();
331 inline closure_owner(T& c)
334 inline ~closure_owner() {
337 inline void reset() {
345class rendezvous_owner {
347 inline rendezvous_owner(R& r)
350 inline ~rendezvous_owner() {
355 inline void reset() {
364void event_prematurely_dereferenced(simple_event *e, abstract_rendezvous *r);
368inline void abstract_rendezvous::remove_waiting() TAMER_NOEXCEPT {
370 hard_remove_waiting();
374inline abstract_rendezvous::~abstract_rendezvous() TAMER_NOEXCEPT {
375 TAMER_DEBUG_ASSERT(!waiting_);
379inline bool simple_driver::has_unblocked()
const {
380 while (cunblocked_ && !cs_[cunblocked_].c) {
381 unsigned next = cs_[cunblocked_].next;
382 cs_[cunblocked_].next = cfree_;
383 cfree_ = cunblocked_;
386 return cunblocked_ != 0;
389inline closure* simple_driver::pop_unblocked() {
390 if (has_unblocked()) {
391 unsigned i = cunblocked_;
392 closure* c = cs_[i].c;
393 cunblocked_ = cs_[i].next;
395 cs_[i].next = cfree_;
403inline void simple_driver::run_unblocked() {
404 while (closure* c = pop_unblocked()) {
405 c->tamer_activator_(c);
409inline void simple_driver::clear_unblocked() {
410 while (closure* c = pop_unblocked()) {
411 c->tamer_block_position_ = -1;
412 c->tamer_activator_(c);
416inline void simple_driver::add_blocked(closure* c) {
418 c->tamer_driver_index_ = 0;
424inline void simple_driver::make_unblocked(closure* c) {
425 if (!c->tamer_driver_index_) {
429 cs_[cunblocked_tail_].next = c->tamer_driver_index_;
431 cunblocked_ = c->tamer_driver_index_;
433 cunblocked_tail_ = c->tamer_driver_index_;
436inline unsigned simple_driver::nclosure_slots()
const {
440inline closure* simple_driver::closure_slot(
unsigned i)
const {
446inline blocking_rendezvous::blocking_rendezvous(rendezvous_type rtype) TAMER_NOEXCEPT
447 : abstract_rendezvous(rtype), blocked_closure_() {
450inline blocking_rendezvous::~blocking_rendezvous() TAMER_NOEXCEPT {
451 if (blocked_closure_) {
456inline bool blocking_rendezvous::blocked()
const {
457 return blocked_closure_ && blocked_closure_->tamer_blocked_driver_;
460inline bool blocking_rendezvous::volatile_blocked()
const {
461 return blocked_closure_
462 && blocked_closure_->tamer_blocked_driver_
463 && (blocked_closure_->tamer_block_position_ & 1) != 0;
466inline void blocking_rendezvous::block(simple_driver* driver, closure& c,
468 assert(!c.tamer_blocked_driver_);
469 blocked_closure_ = &c;
470 c.tamer_block_position_ = position;
471 c.tamer_blocked_driver_ = driver;
472 driver->add_blocked(&c);
475inline void closure::unblock() {
476 if (simple_driver* d = tamer_blocked_driver_) {
477 tamer_blocked_driver_ = 0;
478 if (d != &simple_driver::immediate_driver) {
479 d->make_unblocked(
this);
481 tamer_activator_(
this);
486inline void blocking_rendezvous::unblock() {
487 if (closure* cl = blocked_closure_) {
488 blocked_closure_ = 0;
494inline closure::~closure() {
495 if (tamer_closures_pprev_
496 && (*tamer_closures_pprev_ = tamer_closures_next_)) {
497 tamer_closures_next_->tamer_closures_pprev_ = tamer_closures_pprev_;
499 delete tamer_description_;
502inline bool closure::has_location()
const {
503 return tamer_location_file_ || tamer_location_line_;
506inline bool closure::has_description()
const {
507 return tamer_description_ && !tamer_description_->empty();
510inline void closure::set_location(
const char* file,
int line) {
511 TAMER_IFTRACE(tamer_location_file_ = file);
512 TAMER_IFTRACE(tamer_location_line_ = line);
513 TAMER_IFNOTRACE((
void) file, (
void) line);
516inline void closure::set_description(std::string description) {
518 if (tamer_description_) {
519 *tamer_description_ = std::move(description);
520 }
else if (!description.empty()) {
521 tamer_description_ =
new std::string(std::move(description));
528inline const char* closure::location_file()
const {
529 return TAMER_IFTRACE_ELSE(tamer_location_file_, 0);
532inline int closure::location_line()
const {
533 return TAMER_IFTRACE_ELSE(tamer_location_line_, 0);
536inline std::string closure::description()
const {
538 if (tamer_description_) {
539 return *tamer_description_;
542 return std::string();
546inline simple_event::simple_event() TAMER_NOEXCEPT
547 : _r(0), _refcount(1) TAMER_IFTRACE(, file_annotation_(0)) {
548#if TAMER_DEBUG && TAMER_DEBUG_LEVEL > 1
553inline simple_event::simple_event(abstract_rendezvous& r, uintptr_t rid,
554 const char* file,
int line) TAMER_NOEXCEPT
555 : _r(&r), _rid(rid), _r_next(r.waiting_), _r_pprev(&r.waiting_),
556 at_trigger_f_(0), at_trigger_arg_(0), _refcount(1)
557 TAMER_IFTRACE(, line_annotation_(line), file_annotation_(file)) {
559 r.waiting_->_r_pprev = &_r_next;
562 TAMER_IFNOTRACE((
void) file, (
void) line);
563#if TAMER_DEBUG && TAMER_DEBUG_LEVEL > 1
564 print(
"create", file, line);
568inline simple_event::~simple_event() TAMER_NOEXCEPT {
569 TAMER_DEBUG_ASSERT(!_r);
570#if TAMER_DEBUG && TAMER_DEBUG_LEVEL > 1
575inline void simple_event::use(simple_event* e,
const char*,
int) TAMER_NOEXCEPT {
581inline void simple_event::unuse(simple_event* e,
const char*,
int) TAMER_NOEXCEPT {
584 if (e->_refcount == 0) {
590inline void simple_event::unuse_clean(simple_event* e,
const char*,
int) TAMER_NOEXCEPT {
593 if (e->_refcount == 0) {
599inline bool simple_event::unused()
const {
600 return _refcount == 0;
603inline simple_event::operator bool()
const {
607inline bool simple_event::empty()
const {
611inline abstract_rendezvous *simple_event::rendezvous()
const {
615inline uintptr_t simple_event::rid()
const {
619inline simple_event *simple_event::next()
const {
623inline bool simple_event::shared()
const {
624 return _r && _refcount > 1;
627inline bool simple_event::has_at_trigger()
const {
628 return at_trigger_f_;
631inline const char* simple_event::file_annotation()
const {
633 return file_annotation_;
639inline int simple_event::line_annotation()
const {
641 return line_annotation_;
647inline void simple_event::simple_trigger(
bool values) {
648 simple_trigger(
this, values);
651inline void simple_event::at_trigger(simple_event* x, simple_event* at_e) {
653 at_trigger(x, trigger_hook, at_e);
657inline void simple_event::at_trigger(simple_event* x,
void (*f)(
void*),
659 if (x && *x && !x->at_trigger_f_) {
660 x->at_trigger_f_ = f;
661 x->at_trigger_arg_ = arg;
663 hard_at_trigger(x, f, arg);
667template <
typename T>
struct rid_cast {
668 static inline uintptr_t in(T x) TAMER_NOEXCEPT {
669 return static_cast<uintptr_t
>(x);
671 static inline T out(uintptr_t x) TAMER_NOEXCEPT {
672 return static_cast<T
>(x);
676template <
typename T>
struct rid_cast<T *> {
677 static inline uintptr_t in(T *x) TAMER_NOEXCEPT {
678 return reinterpret_cast<uintptr_t
>(x);
680 static inline T *out(uintptr_t x) TAMER_NOEXCEPT {
681 return reinterpret_cast<T *
>(x);
A future occurrence.
Definition event.hh:116
A set of watched events.
Definition rendezvous.hh:37
Definition rendezvous.hh:463
Namespace containing public Tamer classes and functions for the Tamer core.
Definition adapter.hh:17