📄 notifier.hh
字号:
// -*- c-basic-offset: 4; related-file-name: "../../lib/notifier.cc" -*-#ifndef CLICK_NOTIFIER_HH#define CLICK_NOTIFIER_HH#include <click/task.hh>#include <click/atomic.hh>CLICK_DECLSclass NotifierSignal { public: /** @brief Construct a busy signal. * * The returned signal is always active. */ inline NotifierSignal(); /** @brief Construct an activity signal. * * Elements should not use this constructor directly. * @sa Router::new_notifier_signal */ inline NotifierSignal(atomic_uint32_t* value, uint32_t mask); /** @brief Copy construct a signal. */ inline NotifierSignal(const NotifierSignal &x); /** @brief Destroy a signal. */ inline ~NotifierSignal(); /** @brief Return an idle signal. * * The returned signal is never active. */ static inline NotifierSignal idle_signal(); /** @brief Return a busy signal. * * The returned signal is always active. */ static inline NotifierSignal busy_signal(); /** @brief Return an overderived busy signal. * * Overderived signals replace derived signals that are too complex to * represent. An overderived signal, like a busy signal, is always * active. */ static inline NotifierSignal overderived_signal(); /** @brief Return an uninitialized signal. * * Uninitialized signals may be used occasionally as placeholders for true * signals to be added later. Uninitialized signals are never active. */ static inline NotifierSignal uninitialized_signal(); typedef bool (NotifierSignal::*unspecified_bool_type)() const; /** @brief Return whether the signal is active. * @return true iff the signal is currently active. */ inline operator unspecified_bool_type() const; /** @brief Return whether the signal is active. * @return true iff the signal is currently active. */ inline bool active() const; /** @brief Return whether the signal is idle. * @return true iff the signal is idle, i.e. it will never be active. */ inline bool idle() const; /** @brief Return whether the signal is busy. * @return true iff the signal is busy, i.e. it will always be active. * * @note An overderived_signal() is busy(), but a busy_signal() is not * overderived(). */ inline bool busy() const; /** @brief Return whether the signal is overderived. * @return true iff the signal equals overderived_signal(). * * @note An overderived_signal() is busy(), but a busy_signal() is not * overderived(). */ inline bool overderived() const; /** @brief Return whether the signal is initialized. * @return true iff the signal doesn't equal uninitialized_signal(). */ inline bool initialized() const; /** @brief Set whether the basic signal is active. * @param active true iff the basic signal is active * * Use this function to set whether a basic signal is active. * * It is illegal to call set_active() on derived, idle, busy, or * overderived signals. Some of these actions may cause an assertion * failure. */ inline void set_active(bool active); /** @brief Assign a signal. */ NotifierSignal &operator=(const NotifierSignal &x); /** @brief Make this signal derived by adding information from @a x. * @param x the signal to add * * Creates a derived signal that combines information from this signal and * @a x. Equivalent to "*this = (*this + @a x)". * * @sa operator+(NotifierSignal, const NotifierSignal&) */ NotifierSignal &operator+=(const NotifierSignal& x); /** @brief Return a human-readable representation of the signal. * @param router the relevant router or null * * Useful for signal debugging. */ String unparse(Router *router) const; static void static_initialize(); /** @relates NotifierSignal * @brief Compare two NotifierSignals for equality. * * Returns true iff the two NotifierSignals are the same -- i.e., they * combine information about exactly the same sets of basic signals. * * All idle() signals compare equal. busy_signal() and * overderived_signal() do not compare equal, however. */ friend bool operator==(const NotifierSignal &a, const NotifierSignal &b); /** @relates NotifierSignal * @brief Compare two NotifierSignals for inequality. * * Returns true iff !(@a a == @a b). */ friend bool operator!=(const NotifierSignal &a, const NotifierSignal &b); /** @relates NotifierSignal * @brief Return a derived signal. * * Returns a derived signal that combines information from its arguments. * The result will be active whenever @a a and/or @a b is active. If the * combination of @a a and @a b is too complex to represent, returns an * overderived signal; this trivially follows the invariant since it is * always active. * * Signal derivation is commutative and associative. The following * special combinations are worth remembering: * * - An idle() signal plus any other signal @a a equals @a a. Thus, * idle_signal() is the identity for signal derivation. * - A busy() signal plus any other signal is busy(). Thus, * busy_signal() is the "zero element" for signal derivation. * * @sa NotifierSignal::operator+= */ friend NotifierSignal operator+(NotifierSignal a, const NotifierSignal &b); private: struct vmpair { atomic_uint32_t *value; uint32_t mask; }; union { atomic_uint32_t *v1; vmpair *vm; } _v; uint32_t _mask; enum { true_mask = 1, false_mask = 2, overderived_mask = 4, uninitialized_mask = 8 }; static atomic_uint32_t static_value; void hard_assign_vm(const NotifierSignal &x); void hard_derive_one(atomic_uint32_t *value, uint32_t mask); static bool hard_equals(const vmpair *a, const vmpair *b);};class Notifier { public: enum SearchOp { SEARCH_STOP = 0, SEARCH_CONTINUE, SEARCH_CONTINUE_WAKE }; inline Notifier(SearchOp op = SEARCH_STOP); inline Notifier(const NotifierSignal &signal, SearchOp op = SEARCH_STOP); virtual ~Notifier(); int initialize(const char *name, Router *router); inline const NotifierSignal &signal() const; inline SearchOp search_op() const; inline bool active() const; inline void set_active(bool active); inline void wake(); inline void sleep(); virtual int add_listener(Task *task); virtual void remove_listener(Task *task); virtual int add_dependent_signal(NotifierSignal *signal); static const char EMPTY_NOTIFIER[]; static const char FULL_NOTIFIER[]; static NotifierSignal upstream_empty_signal(Element* e, int port, Task* task, Notifier* dependent_notifier = 0); static NotifierSignal downstream_full_signal(Element* e, int port, Task* task, Notifier* dependent_notifier = 0); private: NotifierSignal _signal; SearchOp _search_op;};class ActiveNotifier : public Notifier { public: ActiveNotifier(SearchOp op = SEARCH_STOP); ~ActiveNotifier(); int add_listener(Task *task); // complains on out of memory void remove_listener(Task *task); int add_dependent_signal(NotifierSignal *signal); void listeners(Vector<Task*> &v) const; inline void set_active(bool active, bool schedule = true); inline void wake(); inline void sleep(); private: typedef union { Task *t; NotifierSignal *s; void *v; } task_or_signal_t; Task* _listener1; task_or_signal_t* _listeners; int listener_change(void *what, int where, bool rem); ActiveNotifier(const ActiveNotifier&); // does not exist ActiveNotifier& operator=(const ActiveNotifier&); // does not exist};inlineNotifierSignal::NotifierSignal() : _mask(true_mask){ _v.v1 = &static_value;}inlineNotifierSignal::NotifierSignal(atomic_uint32_t* value, uint32_t mask) : _mask(mask){ _v.v1 = value;}inlineNotifierSignal::NotifierSignal(const NotifierSignal &x) : _mask(x._mask){ if (likely(_mask)) _v.v1 = x._v.v1; else hard_assign_vm(x);}inlineNotifierSignal::~NotifierSignal(){ if (unlikely(_mask == 0)) delete[] _v.vm;}inline NotifierSignalNotifierSignal::idle_signal(){ return NotifierSignal(&static_value, false_mask);}inline NotifierSignalNotifierSignal::busy_signal(){ return NotifierSignal(&static_value, true_mask);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -