1 // -*- c-basic-offset: 4; related-file-name: "../../lib/notifier.cc" -*-
2 #ifndef CLICK_NOTIFIER_HH
3 #define CLICK_NOTIFIER_HH
4 #include <click/task.hh>
5 #include <click/atomic.hh>
6 #include <click/algorithm.hh>
7 #if HAVE_CXX_PRAGMA_INTERFACE
8 # pragma interface "click/notifier.hh"
9 #endif
10 CLICK_DECLS
11 
12 class NotifierSignal {
13   public:
14     typedef bool (NotifierSignal::*unspecified_bool_type)() const;
15 
16     inline NotifierSignal();
17     inline NotifierSignal(atomic_uint32_t* value, uint32_t mask);
18     inline NotifierSignal(const NotifierSignal& x);
19     inline ~NotifierSignal();
20 
21     static inline NotifierSignal idle_signal();
22     static inline NotifierSignal busy_signal();
23     static inline NotifierSignal overderived_signal();
24     static inline NotifierSignal uninitialized_signal();
25 
26     inline bool active() const;
27     inline operator unspecified_bool_type() const;
28 
29     inline bool set_active(bool active);
30 
31     inline bool idle() const;
32     inline bool busy() const;
33     inline bool overderived() const;
34     inline bool initialized() const;
35 
36     friend bool operator==(const NotifierSignal &a, const NotifierSignal &b);
37     friend bool operator!=(const NotifierSignal &a, const NotifierSignal &b);
38 
39     NotifierSignal& operator=(const NotifierSignal& x);
40     NotifierSignal& operator+=(const NotifierSignal& x);
41     friend NotifierSignal operator+(NotifierSignal a, const NotifierSignal &b);
42 
43     inline void swap(NotifierSignal& x);
44 
45     String unparse(Router *router) const;
46 
47     static void static_initialize();
48 
49   private:
50     struct vmpair {
51 	atomic_uint32_t *value;
52 	uint32_t mask;
53     };
54     union vmvalue {
55 	atomic_uint32_t *v1;
56 	vmpair *vm;
57     };
58 
59     vmvalue _v;
60     uint32_t _mask;
61 
62     enum {
63 	true_mask = 1, false_mask = 2, overderived_mask = 4,
64 	uninitialized_mask = 8
65     };
66     static atomic_uint32_t static_value;
67 
68     void hard_assign_vm(const NotifierSignal &x);
69     void hard_derive_one(atomic_uint32_t *value, uint32_t mask);
70     static bool hard_equals(const vmpair *a, const vmpair *b);
71 };
72 
73 class Notifier { public:
74 
75     enum SearchOp { SEARCH_STOP = 0, SEARCH_CONTINUE, SEARCH_CONTINUE_WAKE };
76     typedef void (*callback_type)(void *, Notifier *);
77 
78     inline Notifier(SearchOp op = SEARCH_STOP);
79     inline Notifier(const NotifierSignal &signal, SearchOp op = SEARCH_STOP);
80     virtual ~Notifier();
81 
82     /** @brief Return whether the Notifier is initialized. */
initialized() const83     inline bool initialized() const {
84 	return _signal.initialized();
85     }
86 
87     int initialize(const char *name, Router *router);
88 
89     inline const NotifierSignal &signal() const;
90     inline SearchOp search_op() const;
91 
92     inline bool active() const;
93 
94     inline bool set_active(bool active);
95     inline void wake();
96     inline void sleep();
97 
98     virtual int add_activate_callback(callback_type f, void *user_data);
99     virtual void remove_activate_callback(callback_type f, void *user_data);
100     inline int add_listener(Task *task);
101     inline void remove_listener(Task *task);
102     inline int add_dependent_signal(NotifierSignal *signal);
103     inline void remove_dependent_signal(NotifierSignal *signal);
104 
105     static const char EMPTY_NOTIFIER[];
106     static const char FULL_NOTIFIER[];
107 
108     static inline NotifierSignal upstream_empty_signal(Element *e, int port);
109     static inline NotifierSignal upstream_empty_signal(Element *e, int port, Task *task);
110     static inline NotifierSignal upstream_empty_signal(Element *e, int port, Notifier *dependent_notifier);
111     static NotifierSignal upstream_empty_signal(Element *e, int port, callback_type f, void *user_data);
112 
113     static inline NotifierSignal downstream_full_signal(Element *e, int port);
114     static inline NotifierSignal downstream_full_signal(Element *e, int port, Task *task);
115     static inline NotifierSignal downstream_full_signal(Element *e, int port, Notifier *dependent_notifier);
116     static NotifierSignal downstream_full_signal(Element *e, int port, callback_type f, void *user_data);
117 
118     static inline NotifierSignal upstream_empty_signal(Element *e, int port, int) CLICK_DEPRECATED;
119     static inline NotifierSignal upstream_empty_signal(Element *e, int port, int, Notifier *) CLICK_DEPRECATED;
120     static inline NotifierSignal downstream_full_signal(Element *e, int port, int) CLICK_DEPRECATED;
121     static inline NotifierSignal downstream_full_signal(Element *e, int port, int, Notifier *) CLICK_DEPRECATED;
122 
123   private:
124 
125     NotifierSignal _signal;
126     SearchOp _search_op;
127 
128     static void dependent_signal_callback(void *, Notifier *);
129 
130 };
131 
132 class ActiveNotifier : public Notifier { public:
133 
134     ActiveNotifier(SearchOp op = SEARCH_STOP);
135     ~ActiveNotifier();
136 
137     int add_activate_callback(callback_type f, void *v);
138     void remove_activate_callback(callback_type f, void *v);
139     void listeners(Vector<Task*> &v) const CLICK_DEPRECATED;
140 
141     inline void set_active(bool active, bool schedule = true);
142     inline void wake();
143     inline void sleep();
144 
145 #if CLICK_DEBUG_SCHEDULING
146     String unparse(Router *router) const;
147 #endif
148 
149   private:
150 
151     typedef union {
152 	Task *t;
153 	callback_type f;
154 	void *v;
155 	uintptr_t p;
156     } task_or_signal_t;
157 
158     Task* _listener1;
159     task_or_signal_t* _listeners;
160 
161     int listener_add(callback_type f, void *v);
162     int listener_remove(callback_type f, void *v);
163 
164     ActiveNotifier(const ActiveNotifier&); // does not exist
165     ActiveNotifier& operator=(const ActiveNotifier&); // does not exist
166 
167 };
168 
169 
170 /** @brief Construct a busy signal.
171  *
172  * The returned signal is always active. */
NotifierSignal()173 inline NotifierSignal::NotifierSignal()
174     : _mask(true_mask) {
175     _v.v1 = &static_value;
176 }
177 
178 /** @brief Construct an activity signal.
179  *
180  * Elements should not use this constructor directly.
181  * @sa Router::new_notifier_signal */
NotifierSignal(atomic_uint32_t * value,uint32_t mask)182 inline NotifierSignal::NotifierSignal(atomic_uint32_t* value, uint32_t mask)
183     : _mask(mask) {
184     _v.v1 = value;
185 }
186 
187 /** @brief Copy construct a signal. */
NotifierSignal(const NotifierSignal & x)188 inline NotifierSignal::NotifierSignal(const NotifierSignal& x)
189     : _mask(x._mask) {
190     if (likely(_mask))
191 	_v.v1 = x._v.v1;
192     else
193 	hard_assign_vm(x);
194 }
195 
196 /** @brief Destroy a signal. */
~NotifierSignal()197 inline NotifierSignal::~NotifierSignal() {
198     if (unlikely(_mask == 0))
199 	delete[] _v.vm;
200 }
201 
202 /** @brief Return an idle signal.
203  *
204  * The returned signal is never active. */
idle_signal()205 inline NotifierSignal NotifierSignal::idle_signal() {
206     return NotifierSignal(&static_value, false_mask);
207 }
208 
209 /** @brief Return a busy signal.
210  *
211  * The returned signal is always active. */
busy_signal()212 inline NotifierSignal NotifierSignal::busy_signal() {
213     return NotifierSignal(&static_value, true_mask);
214 }
215 
216 /** @brief Return an overderived busy signal.
217  *
218  * Overderived signals replace derived signals that are too complex to
219  * represent.  An overderived signal, like a busy signal, is always
220  * active. */
overderived_signal()221 inline NotifierSignal NotifierSignal::overderived_signal() {
222     return NotifierSignal(&static_value, overderived_mask | true_mask);
223 }
224 
225 /** @brief Return an uninitialized signal.
226  *
227  * Uninitialized signals may be used occasionally as placeholders for true
228  * signals to be added later.  Uninitialized signals are never active. */
uninitialized_signal()229 inline NotifierSignal NotifierSignal::uninitialized_signal() {
230     return NotifierSignal(&static_value, uninitialized_mask);
231 }
232 
233 /** @brief Test if the signal is active. */
active() const234 inline bool NotifierSignal::active() const {
235     // 2012.May.16 This fence is necessary; consider, for example,
236     // InfiniteSource's checking of nonfull notifiers.
237     click_fence();
238     if (likely(_mask))
239 	return (*_v.v1 & _mask) != 0;
240     else {
241 	for (vmpair *vm = _v.vm; vm->mask; ++vm)
242 	    if ((*vm->value & vm->mask) != 0)
243 		return true;
244 	return false;
245     }
246 }
247 
248 /** @brief Test if the signal is active. */
operator unspecified_bool_type() const249 inline NotifierSignal::operator unspecified_bool_type() const {
250     return active() ? &NotifierSignal::active : 0;
251 }
252 
253 /** @brief Test if the signal is idle.
254  * @return true iff the signal is idle, i.e. it will never be active. */
idle() const255 inline bool NotifierSignal::idle() const {
256     return (_mask == false_mask && _v.v1 == &static_value);
257 }
258 
259 /** @brief Test if the signal is busy.
260  * @return true iff the signal is busy, i.e. it will always be active.
261  *
262  * @note An overderived_signal() is busy(), but a busy_signal() is not
263  * overderived(). */
busy() const264 inline bool NotifierSignal::busy() const {
265     return ((_mask & true_mask) && _v.v1 == &static_value);
266 }
267 
268 /** @brief Test if the signal is overderived.
269  * @return true iff the signal equals overderived_signal().
270  *
271  * @note An overderived_signal() is busy(), but a busy_signal() is not
272  * overderived(). */
overderived() const273 inline bool NotifierSignal::overderived() const {
274     return ((_mask & overderived_mask) && _v.v1 == &static_value);
275 }
276 
277 /** @brief Test if the signal is initialized.
278  * @return true iff the signal doesn't equal uninitialized_signal(). */
initialized() const279 inline bool NotifierSignal::initialized() const {
280     return (!(_mask & uninitialized_mask) || _v.v1 != &static_value);
281 }
282 
283 /** @brief Set whether the basic signal is active.
284  * @param active true iff the basic signal is active
285  * @return previous active state
286  *
287  * Use this function to set whether a basic signal is active.
288  *
289  * It is illegal to call set_active() on derived, idle, busy, or
290  * overderived signals.  Some of these actions may cause an assertion
291  * failure. */
set_active(bool active)292 inline bool NotifierSignal::set_active(bool active) {
293     assert(_v.v1 != &static_value && !(_mask & (_mask - 1)));
294     uint32_t expected = *_v.v1;
295 #if !CLICK_USERLEVEL || HAVE_MULTITHREAD
296     while (_mask) {
297 	uint32_t desired = (active ? expected | _mask : expected & ~_mask);
298 	uint32_t actual = _v.v1->compare_swap(expected, desired);
299 	if (expected == actual)
300 	    break;
301 	expected = actual;
302     }
303 #else
304     *_v.v1 = (active ? expected | _mask : expected & ~_mask);
305 #endif
306     return expected & _mask;
307 }
308 
309 /** @brief Assign a signal. */
operator =(const NotifierSignal & x)310 inline NotifierSignal& NotifierSignal::operator=(const NotifierSignal& x) {
311     if (likely(this != &x)) {
312 	if (unlikely(_mask == 0))
313 	    delete[] _v.vm;
314 	_mask = x._mask;
315 	if (likely(_mask))
316 	    _v.v1 = x._v.v1;
317 	else
318 	    hard_assign_vm(x);
319     }
320     return *this;
321 }
322 
323 /** @brief Exchange the values of this signal and @a x. */
swap(NotifierSignal & x)324 inline void NotifierSignal::swap(NotifierSignal& x) {
325     click_swap(_v, x._v);
326     click_swap(_mask, x._mask);
327 }
328 
329 /** @relates NotifierSignal
330  * @brief Test if two NotifierSignals are equal.
331  *
332  * Returns true iff the two NotifierSignals are the same -- i.e., they
333  * combine information about exactly the same sets of basic signals.
334  *
335  * All idle() signals compare equal.  busy_signal() and
336  * overderived_signal() do not compare equal, however. */
operator ==(const NotifierSignal & a,const NotifierSignal & b)337 inline bool operator==(const NotifierSignal& a, const NotifierSignal& b) {
338     if (a._mask == b._mask) {
339 	if (likely(a._mask))
340 	    return a._v.v1 == b._v.v1;
341 	else
342 	    return NotifierSignal::hard_equals(a._v.vm, b._v.vm);
343     } else
344 	return false;
345 }
346 
347 /** @relates NotifierSignal
348  * @brief Test if two NotifierSignals are unequal.
349  *
350  * Returns true iff !(@a a == @a b). */
operator !=(const NotifierSignal & a,const NotifierSignal & b)351 inline bool operator!=(const NotifierSignal& a, const NotifierSignal& b) {
352     return !(a == b);
353 }
354 
355 /** @relates NotifierSignal
356  * @brief Return a derived signal.
357  *
358  * Returns a derived signal that combines information from its arguments.
359  * The result will be active whenever @a a and/or @a b is active.  If the
360  * combination of @a a and @a b is too complex to represent, returns an
361  * overderived signal; this trivially follows the invariant since it is
362  * always active.
363  *
364  * Signal derivation is commutative and associative.  The following
365  * special combinations are worth remembering:
366  *
367  *  - An uninitialized signal plus any other signal is uninitialized.
368  *  - An idle signal plus any signal @a a equals @a a.
369  *  - A busy signal plus any other initialized signal is busy.
370  *  - overderived_signal() plus busy_signal() equals busy_signal().
371  *
372  * @sa NotifierSignal::operator+= */
operator +(NotifierSignal a,const NotifierSignal & b)373 inline NotifierSignal operator+(NotifierSignal a, const NotifierSignal& b) {
374     return a += b;
375 }
376 
377 /** @brief Constructs a Notifier.
378  * @param op controls notifier path search
379  *
380  * This function constructs a Notifier object.  The Notifier's associated
381  * NotifierSignal is initially idle; it becomes associated with a signal after
382  * initialize() is called.
383  *
384  * The @a op argument controls path search.  The rest of this entry
385  * describes it further.
386  *
387  * Elements interested in notification generally search for Notifier objects
388  * along all possible packet paths upstream (or downstream) of one of their
389  * ports.  When a Notifier is found along a path, further searching along that
390  * path is cut off, so only the closest Notifiers are found.  Sometimes,
391  * however, it makes more sense to continue searching for more Notifiers.  The
392  * correct behavior is Notifier-specific, and is controlled by this method.
393  * When the search encounters a Notifier, it consults the Notifier's @a
394  * op variable supplied to the constructor.  It should equal one of
395  * three SearchOp constants, which correspond to the following behavior:
396  *
397  * <dl>
398  * <dt>SEARCH_STOP</dt>
399  * <dd>Stop searching along this path.  This is the default.</dd>
400  * <dt>SEARCH_CONTINUE</dt>
401  * <dd>Continue searching along this path.</dd>
402  * <dt>SEARCH_CONTINUE_WAKE</dt>
403  * <dd>Continue searching along this path, but any further Notifiers should
404  * only be used for adding and removing listeners; ignore their NotifierSignal
405  * objects.  This operation is useful, for example, for schedulers that store
406  * packets temporarily.  Such schedulers provide their own NotifierSignal,
407  * since the scheduler may still hold a packet even when all upstream sources
408  * are empty, but since they aren't packet sources, they don't know when
409  * new packets arrive and can't wake up sleeping listeners.  During
410  * initialization, such schedulers should call Notifier::upstream_empty_signal,
411  * passing their own Notifier as the fourth argument.  This will ensure that
412  * their signal is turned on appropriately whenever an upstream queue becomes
413  * nonempty.</dd>
414  * </dl>
415  */
Notifier(SearchOp op)416 inline Notifier::Notifier(SearchOp op)
417     : _signal(NotifierSignal::uninitialized_signal()), _search_op(op) {
418 }
419 
420 /** @brief Constructs a Notifier associated with a given signal.
421  * @param signal the associated NotifierSignal
422  * @param op controls notifier path search
423  *
424  * This function constructs a Notifier object associated with a specific
425  * NotifierSignal, such as NotifierSignal::idle_signal().  Calling
426  * initialize() on this Notifier will not change the associated
427  * NotifierSignal.  The @a op argument is as in
428  * Notifier::Notifier(SearchOp), above.
429  */
Notifier(const NotifierSignal & signal,SearchOp op)430 inline Notifier::Notifier(const NotifierSignal &signal, SearchOp op)
431     : _signal(signal), _search_op(op) {
432 }
433 
434 /** @brief Return this Notifier's associated NotifierSignal.
435  *
436  * Every Notifier object corresponds to one NotifierSignal; this method
437  * returns it.  The signal is @link NotifierSignal::idle idle() @endlink
438  * before initialize() is called.
439  */
signal() const440 inline const NotifierSignal& Notifier::signal() const {
441     return _signal;
442 }
443 
444 /** @brief Return this Notifier's search operation.
445  *
446  * @sa Notifier() for a detailed explanation of search operations.
447  */
search_op() const448 inline Notifier::SearchOp Notifier::search_op() const {
449     return _search_op;
450 }
451 
452 /** @brief Returns whether the associated signal is active.
453  *
454  * Same as signal().active().
455  */
active() const456 inline bool Notifier::active() const {
457     return _signal.active();
458 }
459 
460 /** @brief Set the associated signal's activity.
461  * @param active true iff the signal should be active
462  * @return previous active state
463  */
set_active(bool active)464 inline bool Notifier::set_active(bool active) {
465     return _signal.set_active(active);
466 }
467 
468 /** @brief Set the associated signal to active.
469  * @sa set_active
470  */
wake()471 inline void Notifier::wake() {
472     set_active(true);
473 }
474 
475 /** @brief Set the associated signal to inactive.
476  * @sa set_active
477  */
sleep()478 inline void Notifier::sleep() {
479     set_active(false);
480 }
481 
482 /** @brief Register a listener with this Notifier.
483  * @param task Task to reschedule when this Notifier becomes active
484  *
485  * When this Notifier's associated signal is activated, the Notifier should
486  * schedule @a task. Not all types of Notifier provide this functionality. The
487  * default implementation does nothing.
488  *
489  * @sa remove_listener, add_activate_callback, add_dependent_signal
490  */
add_listener(Task * task)491 inline int Notifier::add_listener(Task* task) {
492     return add_activate_callback(0, task);
493 }
494 
495 /** @brief Unregister a listener with this Notifier.
496  * @param task listener Task
497  *
498  * Undoes the effect of all prior add_listener(@a task) calls. Does nothing if
499  * @a task was never added. The default implementation does nothing.
500  *
501  * @sa add_listener
502  */
remove_listener(Task * task)503 inline void Notifier::remove_listener(Task* task) {
504     remove_activate_callback(0, task);
505 }
506 
507 /** @brief Register a dependent signal with this Notifier.
508  * @param signal dependent signal
509  *
510  * When this Notifier's associated signal is activated, the Notifier should
511  * also activate @a signal. Not all types of Notifier provide this
512  * functionality. The default implementation does nothing.
513  *
514  * @sa add_listener, add_activate_callback, remove_dependent_signal
515  */
add_dependent_signal(NotifierSignal * signal)516 inline int Notifier::add_dependent_signal(NotifierSignal* signal) {
517     return add_activate_callback(dependent_signal_callback, signal);
518 }
519 
520 /** @brief Unregister a dependent signal with this Notifier.
521  * @param signal dependent signal
522  *
523  * Undoes the effect of all prior add_dependent_signal(@a signal) calls. Does
524  * nothing if @a signal was never added. The default implementation does
525  * nothing.
526  *
527  * @sa add_dependent_signal
528  */
remove_dependent_signal(NotifierSignal * signal)529 inline void Notifier::remove_dependent_signal(NotifierSignal* signal) {
530     remove_activate_callback(dependent_signal_callback, signal);
531 }
532 
533 /** @brief Calculate and return the NotifierSignal derived from all empty
534  * notifiers upstream of element @a e's input @a port.
535  * @param e an element
536  * @param port the input port of @a e at which to start the upstream search
537  *
538  * Searches the configuration upstream of element @a e's input @a port for @e
539  * empty @e notifiers.  These notifiers are associated with packet storage,
540  * and should be true when packets are available (or likely to be available
541  * quite soon), and false when they are not.  All notifiers found are combined
542  * into a single derived signal.  Thus, if any of the base notifiers are
543  * active, indicating that at least one packet is available upstream, the
544  * derived signal will also be active.  Element @a e's code generally uses the
545  * resulting signal to decide whether or not to reschedule itself.
546  *
547  * The returned signal is generally conservative, meaning that the signal
548  * is true whenever a packet exists upstream, but the elements that provide
549  * notification are responsible for ensuring this.
550  *
551  * Overloaded versions of this function can also register a task (as in
552  * add_listener()), a signal (as in add_dependent_notifier()), or a callback
553  * function (as in add_active_callback()) for each located notifier. When
554  * packets become available, the task will be scheduled, the signal will be
555  * activated, or the callback will be called.
556  *
557  * <h3>Supporting upstream_empty_signal()</h3>
558  *
559  * Elements that have an empty notifier must override the Element::cast()
560  * method.  When passed the @a name Notifier::EMPTY_NOTIFIER, this method
561  * should return a pointer to the corresponding Notifier object.
562  *
563  * @sa downstream_full_signal
564  */
upstream_empty_signal(Element * e,int port)565 inline NotifierSignal Notifier::upstream_empty_signal(Element* e, int port) {
566     return upstream_empty_signal(e, port, (callback_type) 0, 0);
567 }
568 
569 /** @brief Calculate and return the NotifierSignal derived from all empty
570  * notifiers upstream of element @a e's input @a port.
571  * @param e an element
572  * @param port the input port of @a e at which to start the upstream search
573  * @param task task to schedule when packets become available
574  * @sa add_listener */
upstream_empty_signal(Element * e,int port,Task * task)575 inline NotifierSignal Notifier::upstream_empty_signal(Element* e, int port,
576                                                       Task* task) {
577     return upstream_empty_signal(e, port, (callback_type) 0, task);
578 }
579 
580 /** @brief Calculate and return the NotifierSignal derived from all empty
581  * notifiers upstream of element @a e's input @a port.
582  * @param e an element
583  * @param port the input port of @a e at which to start the upstream search
584  * @param notifier notifier to activate when packets become available
585  * @sa add_dependent_signal */
upstream_empty_signal(Element * e,int port,Notifier * dependent_notifier)586 inline NotifierSignal Notifier::upstream_empty_signal(Element* e, int port,
587                                                       Notifier* dependent_notifier) {
588     return upstream_empty_signal(e, port, dependent_signal_callback, &dependent_notifier->_signal);
589 }
590 
591 /** @brief Calculate and return the NotifierSignal derived from all full
592  * notifiers downstream of element @a e's output @a port.
593  * @param e an element
594  * @param port the output port of @a e at which to start the downstream search
595  *
596  * Searches the configuration downstream of element @a e's output @a port for
597  * @e full @e notifiers.  These notifiers are associated with packet storage,
598  * and should be true when there is space for at least one packet, and false
599  * when there is not.  All notifiers found are combined into a single derived
600  * signal.  Thus, if any of the base notifiers are active, indicating that at
601  * least one path has available space, the derived signal will also be active.
602  * Element @a e's code generally uses the resulting signal to decide whether
603  * or not to reschedule itself.
604  *
605  * Overloaded versions of this function can also register a task (as in
606  * add_listener()), a signal (as in add_dependent_notifier()), or a callback
607  * function (as in add_active_callback()) for each located notifier. When
608  * space becomes available, the task will be scheduled, the signal will be
609  * activated, or the callback will be called.
610  *
611  * In current Click, the returned signal is conservative: if it's inactive,
612  * then there is no space for packets downstream.
613  *
614  * <h3>Supporting downstream_full_signal()</h3>
615  *
616  * Elements that have a full notifier must override the Element::cast()
617  * method.  When passed the @a name Notifier::FULL_NOTIFIER, this method
618  * should return a pointer to the corresponding Notifier object.
619  *
620  * @sa upstream_empty_signal
621  */
downstream_full_signal(Element * e,int port)622 inline NotifierSignal Notifier::downstream_full_signal(Element* e, int port) {
623     return downstream_full_signal(e, port, (callback_type) 0, 0);
624 }
625 
626 /** @brief Calculate and return the NotifierSignal derived from all full
627  * notifiers downstream of element @a e's output @a port.
628  * @param e an element
629  * @param port the output port of @a e at which to start the downstream search
630  * @param task task to schedule when packets become available
631  * @sa add_listener */
downstream_full_signal(Element * e,int port,Task * task)632 inline NotifierSignal Notifier::downstream_full_signal(Element* e, int port,
633                                                        Task* task) {
634     return downstream_full_signal(e, port, (callback_type) 0, task);
635 }
636 
637 /** @brief Calculate and return the NotifierSignal derived from all full
638  * notifiers downstream of element @a e's output @a port.
639  * @param e an element
640  * @param port the output port of @a e at which to start the downstream search
641  * @param notifier notifier to activate when packets become available
642  * @sa add_dependent_signal */
downstream_full_signal(Element * e,int port,Notifier * dependent_notifier)643 inline NotifierSignal Notifier::downstream_full_signal(Element* e, int port,
644                                                        Notifier* dependent_notifier) {
645     return downstream_full_signal(e, port, dependent_signal_callback, &dependent_notifier->_signal);
646 }
647 
648 /** @cond never */
upstream_empty_signal(Element * e,int port,int x)649 inline NotifierSignal Notifier::upstream_empty_signal(Element* e, int port, int x) {
650     (void) x;
651     assert(x == 0);
652     return upstream_empty_signal(e, port);
653 }
654 
upstream_empty_signal(Element * e,int port,int x,Notifier * notifier)655 inline NotifierSignal Notifier::upstream_empty_signal(Element* e, int port, int x,
656                                                       Notifier* notifier) {
657     (void) x;
658     assert(x == 0);
659     return upstream_empty_signal(e, port, notifier);
660 }
661 
downstream_full_signal(Element * e,int port,int x)662 inline NotifierSignal Notifier::downstream_full_signal(Element* e, int port, int x) {
663     (void) x;
664     assert(x == 0);
665     return downstream_full_signal(e, port);
666 }
667 
downstream_full_signal(Element * e,int port,int x,Notifier * notifier)668 inline NotifierSignal Notifier::downstream_full_signal(Element* e, int port, int x,
669                                                        Notifier* notifier) {
670     (void) x;
671     assert(x == 0);
672     return downstream_full_signal(e, port, notifier);
673 }
674 /** @endcond never */
675 
676 /** @brief Set the associated signal's activity, possibly scheduling any
677  * listener tasks.
678  * @param active true iff the signal should be active
679  * @param schedule if true, wake up listener tasks
680  *
681  * If @a active and @a schedule are both true, and the signal was previously
682  * inactive, then any listener Tasks are scheduled with Task::reschedule().
683  *
684  * @sa wake, sleep, add_listener
685  */
set_active(bool active,bool schedule)686 inline void ActiveNotifier::set_active(bool active, bool schedule) {
687     bool was_active = Notifier::set_active(active);
688     if (active && schedule && !was_active) {
689 	// 2007.Sep.6: Perhaps there was a race condition here.  Make sure
690 	// that we set the notifier to active BEFORE rescheduling downstream
691 	// tasks.  This is because, in a multithreaded environment, a task we
692 	// reschedule might run BEFORE we set the notifier; after which it
693 	// would go to sleep forever.
694 	if (_listener1)
695 	    _listener1->reschedule();
696 	else if (task_or_signal_t *tos = _listeners) {
697 	    for (; tos->p > 1; tos++)
698 		tos->t->reschedule();
699 	    if (tos->p == 1)
700 		for (tos++; tos->p; tos += 2)
701 		    tos->f(tos[1].v, this);
702 	}
703     }
704 }
705 
706 /** @brief Set the associated signal to active and schedule any listener
707  * tasks.
708  *
709  * If the signal was previously inactive, then any listener Tasks are
710  * scheduled with Task::reschedule().
711  *
712  * @sa set_active, add_listener
713  */
wake()714 inline void ActiveNotifier::wake() {
715     set_active(true, true);
716 }
717 
718 /** @brief Set the associated signal to inactive.
719  * @sa set_active
720  */
sleep()721 inline void ActiveNotifier::sleep() {
722     set_active(false, true);
723 }
724 
click_swap(NotifierSignal & x,NotifierSignal & y)725 inline void click_swap(NotifierSignal& x, NotifierSignal& y) {
726     x.swap(y);
727 }
728 
729 CLICK_ENDDECLS
730 #endif
731