1#ifndef TAMER_RENDEZVOUS_HH
2#define TAMER_RENDEZVOUS_HH 1
18#include <tamer/xbase.hh>
37 public one_argument_rendezvous_tag<rendezvous<I> > {
41 template <
typename T0,
typename T1,
typename T2,
typename T3>
43 T0& x0, T1& x1, T2& x2, T3& x3);
44 template <
typename T0,
typename T1,
typename T2>
46 template <
typename T0,
typename T1>
47 inline event<T0, T1> make_event(
const I& eid, T0& x0, T1& x1);
48 template <
typename T0>
49 inline event<T0> make_event(
const I& eid, T0& x0);
50 inline event<> make_event(
const I& eid);
56 inline bool join(I& eid);
59 inline uintptr_t make_rid(
const I& eid);
60 using tamerpriv::blocking_rendezvous::block;
67 if (waiting_ || ready_) {
92 return ready_ || waiting_;
104 I* eidp =
reinterpret_cast<I*
>(pop_ready());
105 eid = std::move(*eidp);
119 for (tamerpriv::simple_event* e = waiting_; e; e = e->next()) {
120 delete reinterpret_cast<I*
>(e->rid());
122 abstract_rendezvous::remove_waiting();
123 for (tamerpriv::simple_event* e = ready_; e; e = e->next()) {
124 delete reinterpret_cast<I*
>(e->rid());
126 explicit_rendezvous::remove_ready();
134inline uintptr_t rendezvous<I>::make_rid(
const I& eid) {
135 return reinterpret_cast<uintptr_t
>(
new I(eid));
142class simple_rendezvous :
public tamerpriv::explicit_rendezvous,
143 public one_argument_rendezvous_tag<simple_rendezvous<I> > {
145 inline ~simple_rendezvous();
147 template <
typename T0,
typename T1,
typename T2,
typename T3>
148 inline event<T0, T1, T2, T3> make_event(I eid,
149 T0& x0, T1& x1, T2& x2, T3& x3);
150 template <
typename T0,
typename T1,
typename T2>
151 inline event<T0, T1, T2> make_event(I eid, T0& x0, T1& x1, T2& x2);
152 template <
typename T0,
typename T1>
153 inline event<T0, T1> make_event(I eid, T0& x0, T1& x1);
154 template <
typename T0>
155 inline event<T0> make_event(I eid, T0& x0);
156 inline event<> make_event(I eid);
158 inline bool has_ready()
const {
return ready_; }
159 inline bool has_waiting()
const {
return waiting_; }
160 inline bool has_events()
const {
return ready_ || waiting_; }
162 inline bool join(I& eid);
165 inline uintptr_t make_rid(I eid) TAMER_NOEXCEPT;
166 using tamerpriv::blocking_rendezvous::block;
170inline simple_rendezvous<T>::~simple_rendezvous() {
171 if (waiting_ || ready_) {
177inline bool simple_rendezvous<T>::join(T& eid) {
179 eid = tamerpriv::rid_cast<T>::out(pop_ready());
187void simple_rendezvous<T>::clear() {
188 abstract_rendezvous::remove_waiting();
189 explicit_rendezvous::remove_ready();
193inline uintptr_t simple_rendezvous<T>::make_rid(T eid) TAMER_NOEXCEPT {
194 return tamerpriv::rid_cast<T>::in(eid);
199class rendezvous<uintptr_t> :
public simple_rendezvous<uintptr_t> {
203class rendezvous<T*> :
public simple_rendezvous<T*> {
207class rendezvous<int> :
public simple_rendezvous<int> {
211class rendezvous<bool> :
public simple_rendezvous<bool> {
216class rendezvous<> :
public tamerpriv::explicit_rendezvous,
217 public zero_argument_rendezvous_tag<rendezvous<> > {
220 if (waiting_ || ready_) {
225 template <
typename T0,
typename T1,
typename T2,
typename T3>
226 inline event<T0, T1, T2, T3> make_event(T0& x0, T1& x1, T2& x2, T3& x3);
227 template <
typename T0,
typename T1,
typename T2>
228 inline event<T0, T1, T2> make_event(T0& x0, T1& x1, T2& x2);
229 template <
typename T0,
typename T1>
230 inline event<T0, T1> make_event(T0& x0, T1& x1);
231#if !TAMER_HAVE_PREEVENT || !TAMER_PREFER_PREEVENT
232 template <
typename T0>
233 inline event<T0> make_event(T0& x0);
234 inline event<> make_event();
236 template <
typename T0>
237 inline preevent<rendezvous<>, T0> make_event(T0& x0);
238 inline preevent<rendezvous<> > make_event();
240#if TAMER_HAVE_PREEVENT
241 template <
typename T0>
242 inline preevent<rendezvous<>, T0> make_preevent(T0& x0);
243 inline preevent<rendezvous<> > make_preevent();
246 inline bool has_ready()
const {
return ready_; }
247 inline bool has_waiting()
const {
return waiting_; }
248 inline bool has_events()
const {
return ready_ || waiting_; }
260 using tamerpriv::blocking_rendezvous::block;
264class gather_rendezvous :
public tamerpriv::blocking_rendezvous,
265 public zero_argument_rendezvous_tag<gather_rendezvous> {
267 inline gather_rendezvous()
268 : blocking_rendezvous(tamerpriv::rgather) {
270 inline ~gather_rendezvous() {
276 template <
typename T0,
typename T1,
typename T2,
typename T3>
277 inline event<T0, T1, T2, T3>
make_event(T0& x0, T1& x1, T2& x2, T3& x3);
278 template <
typename T0,
typename T1,
typename T2>
279 inline event<T0, T1, T2>
make_event(T0& x0, T1& x1, T2& x2);
280 template <
typename T0,
typename T1>
281 inline event<T0, T1>
make_event(T0& x0, T1& x1);
282#if !TAMER_HAVE_PREEVENT || !TAMER_PREFER_PREEVENT
283 template <
typename T0>
287 template <
typename T0>
288 inline preevent<gather_rendezvous, T0>
make_event(T0& x0);
289 inline preevent<gather_rendezvous>
make_event();
291#if TAMER_HAVE_PREEVENT
292 template <
typename T0>
293 inline preevent<gather_rendezvous, T0> make_preevent(T0& x0);
294 inline preevent<gather_rendezvous> make_preevent();
297 inline bool has_waiting()
const {
306 using tamerpriv::blocking_rendezvous::block;
309 friend class tamerpriv::abstract_rendezvous;
317template <
typename T0 =
void,
typename T1 =
void,
typename T2 =
void,
typename T3 =
void>
318class distribute_rendezvous :
public functional_rendezvous,
319 public zero_argument_rendezvous_tag<distribute_rendezvous<T0, T1, T2, T3> > {
321 typedef tamer::event<T0, T1, T2, T3> event_type;
322 inline distribute_rendezvous();
323 inline ~distribute_rendezvous();
324 static inline void make(event_type& a, event_type b);
326 inline int nchildren()
const {
334 typename event_type::results_tuple_type vs_;
335 struct alignas(event_type) event_space {
336 char space[
sizeof(event_type)];
338 event_space local_es_[nlocal];
339 static void hook(functional_rendezvous*, simple_event*,
bool) TAMER_NOEXCEPT;
340 static void clear_hook(
void*);
341 void add(event_type e);
342 static void hard_make(event_type& a, event_type b);
346template <
typename T0,
typename T1,
typename T2,
typename T3>
347inline distribute_rendezvous<T0, T1, T2, T3>::distribute_rendezvous()
348 : functional_rendezvous(rdistribute, hook),
349 nes_(0), outstanding_(0), es_(reinterpret_cast<event_type*>(local_es_)) {
352template <
typename T0,
typename T1,
typename T2,
typename T3>
353inline distribute_rendezvous<T0, T1, T2, T3>::~distribute_rendezvous() {
354 for (
int i = 0; i != nes_; ++i) {
357 if (es_ !=
reinterpret_cast<event_type*
>(local_es_)) {
358 delete[]
reinterpret_cast<event_space*
>(es_);
362template <
typename T0,
typename T1,
typename T2,
typename T3>
363void distribute_rendezvous<T0, T1, T2, T3>::add(event_type e) {
364 if (nes_ >= nlocal && (nes_ & (nes_ - 1)) == 0 && !grow()) {
367 new((
void*) &es_[nes_]) event_type(std::move(e));
368 if (es_[nes_].__get_simple()->shared()) {
369 tamerpriv::simple_event::at_trigger(es_[nes_].__get_simple(), clear_hook,
this);
375template <
typename T0,
typename T1,
typename T2,
typename T3>
376inline void distribute_rendezvous<T0, T1, T2, T3>::make(event_type& a, event_type b) {
382 hard_make(a, std::move(b));
386template <
typename T0,
typename T1,
typename T2,
typename T3>
387void distribute_rendezvous<T0, T1, T2, T3>::hard_make(event_type& a, event_type b) {
388 simple_event* se = a.__get_simple();
389 if (se == b.__get_simple()) {
392 distribute_rendezvous<T0, T1, T2, T3>* r;
393 if (!se->shared() && !se->has_at_trigger()
394 && se->rendezvous()->rtype() == tamerpriv::rdistribute) {
395 r =
static_cast<distribute_rendezvous<T0, T1, T2, T3>*
>(se->rendezvous());
397 r =
new distribute_rendezvous<T0, T1, T2, T3>;
398 r->add(std::move(a));
401 r->add(std::move(b));
404template <
typename T0,
typename T1,
typename T2,
typename T3>
405bool distribute_rendezvous<T0, T1, T2, T3>::grow() {
406 event_space* new_es =
new event_space[nes_ * 2];
408 event_space* old_es =
reinterpret_cast<event_space*
>(es_);
409 memcpy(new_es, old_es,
sizeof(event_type) * nes_);
410 if (old_es !=
reinterpret_cast<event_space*
>(local_es_)) {
413 es_ =
reinterpret_cast<event_type*
>(new_es);
420template <
typename T0,
typename T1,
typename T2,
typename T3>
421void distribute_rendezvous<T0, T1, T2, T3>::hook(functional_rendezvous* fr,
423 bool values) TAMER_NOEXCEPT {
424 distribute_rendezvous<T0, T1, T2, T3>* dr =
425 static_cast<distribute_rendezvous<T0, T1, T2, T3>*
>(fr);
428 for (
int i = 0; i != dr->nes_; ++i) {
429 dr->es_[i].tuple_trigger(dr->vs_);
431 }
else if (!x->unused()) {
432 for (
int i = 0; i != dr->nes_; ++i) {
433 dr->es_[i].unblock();
436 for (
int i = 0; i != dr->nes_; ++i) {
437 tamerpriv::simple_event::unuse(dr->es_[i].__release_simple());
440 if (--dr->outstanding_ == 0) {
445template <
typename T0,
typename T1,
typename T2,
typename T3>
446void distribute_rendezvous<T0, T1, T2, T3>::clear_hook(
void* arg) {
447 distribute_rendezvous<T0, T1, T2, T3>* dr =
448 static_cast<distribute_rendezvous<T0, T1, T2, T3>*
>(arg);
449 if (--dr->outstanding_ == 0) {
450 for (
int i = 0; i != dr->nes_; ++i) {
454 dr->remove_waiting();
465 inline tamed_class() : tamer_closures_() {}
466 inline tamed_class(
const tamed_class&) : tamer_closures_() {}
467 inline tamed_class& operator=(
const tamed_class&) {
return *
this; }
468 inline ~tamed_class();
470#if TAMER_HAVE_CXX_RVALUE_REFERENCES
471 inline tamed_class(tamed_class&&) : tamer_closures_() {}
472 inline tamed_class& operator=(tamed_class&&) {
return *
this; }
476 tamerpriv::closure* tamer_closures_;
478 friend class tamerpriv::closure;
481inline tamed_class::~tamed_class() {
482 while (tamerpriv::closure* tc = tamer_closures_) {
483 tamer_closures_ = tc->tamer_closures_next_;
484 tc->tamer_block_position_ = (unsigned) -1;
485 tc->tamer_closures_pprev_ = 0;
493inline void closure::initialize_closure(closure_activator f, ...) {
494 tamer_activator_ = f;
495 tamer_block_position_ = 0;
496 tamer_driver_index_ = 0;
497 tamer_blocked_driver_ = 0;
498 tamer_closures_pprev_ = 0;
499 TAMER_IFTRACE(tamer_location_file_ = 0);
500 TAMER_IFTRACE(tamer_location_line_ = 0);
501 TAMER_IFTRACE(tamer_description_ = 0);
504inline void closure::exit_at_destroy(tamed_class* k) {
505 assert(!tamer_closures_pprev_);
506 tamer_closures_pprev_ = &k->tamer_closures_;
507 if ((tamer_closures_next_ = k->tamer_closures_)) {
508 tamer_closures_next_->tamer_closures_pprev_ = &tamer_closures_next_;
510 k->tamer_closures_ =
this;
513inline void closure::initialize_closure(closure_activator f, tamed_class* k) {
514 initialize_closure(f);
523 inline destroy_guard(tamerpriv::closure& cl, tamed_class* k);
524 inline ~destroy_guard();
527 class shiva_closure :
public tamerpriv::closure {
529 tamerpriv::closure* linked_closure_;
531 shiva_closure* shiva_;
533 destroy_guard(
const destroy_guard&) =
delete;
534 destroy_guard(destroy_guard&&) =
delete;
535 destroy_guard& operator=(
const destroy_guard&) =
delete;
536 destroy_guard& operator=(destroy_guard&&) =
delete;
537 static void activator(tamerpriv::closure*);
538 void birth_shiva(tamerpriv::closure& cl, tamed_class* k);
541inline destroy_guard::destroy_guard(tamerpriv::closure& cl, tamed_class* k)
543 if (!cl.tamer_closures_pprev_) {
544 cl.exit_at_destroy(k);
550inline destroy_guard::~destroy_guard() {
A future occurrence.
Definition event.hh:116
A set of watched events.
Definition rendezvous.hh:37
bool has_events() const
Test if any events are ready or waiting.
Definition rendezvous.hh:91
bool has_waiting() const
Test if any events are waiting.
Definition rendezvous.hh:85
bool join(I &eid)
Report the next ready event.
Definition rendezvous.hh:102
~rendezvous()
Destroy rendezvous.
Definition rendezvous.hh:66
bool has_ready() const
Test if any events are ready.
Definition rendezvous.hh:77
void clear()
Remove all events from this rendezvous.
Definition rendezvous.hh:118
event< T0, T1, T2, T3 > make_event(one_argument_rendezvous_tag< R > &r, const I &eid, T0 &x0, T1 &x1, T2 &x2, T3 &x3)
Construct a four-result event on rendezvous r with ID eid.
Definition event.hh:1115
Namespace containing public Tamer classes and functions for the Tamer core.
Definition adapter.hh:17