Line data Source code
1 : /* 2 : * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #ifndef event_notifier_h 6 : #define event_notifier_h 7 : 8 : #include <atomic> 9 : 10 : #include <base/util.h> 11 : #include <base/queue_task.h> 12 : #include <boost/shared_ptr.hpp> 13 : 14 : /* 15 : * Event Notifier 16 : * 17 : * This routine is a kind of pub-sub mechanism for non db notifications. 18 : * 19 : * Subscriber: 20 : * All subscribers can register with a key. Key identifies the type of 21 : * notification. Subscriber also provides the task context in which it expects 22 : * the notification. On registeration it is given a handle which can be used to 23 : * deregister. Same subscriber can also register multiple callbacks. Each 24 : * registeration is segregated by handle returned agter registeration. 25 : * 26 : * Publisher: 27 : * Publisher uses key like subscriber for kind of notification. Calls Notify and 28 : * that call in turn call all subscribers. If nobody has subscribed nothing has 29 : * to be done. 30 : * 31 : * Implementatin details: 32 : * There is a vector of handles maintained on per key basis. To achieve task 33 : * context based notification on per susbcriber basis, task trigger is used. 34 : * On every registeration a tasktrigger object is created with callback and task 35 : * id. This object along with key is bundled in handle which is returned to 36 : * subscriber. 37 : * 38 : */ 39 : class EventNotifier; 40 : 41 : struct EventNotifyKey { 42 : public: 43 : enum Type { 44 : END_OF_RIB, 45 : GENERIC 46 : }; 47 : EventNotifyKey(Type type); 48 : virtual ~EventNotifyKey(); 49 : 50 : virtual bool IsLess(const EventNotifyKey &rhs) const; 51 0 : Type type() const {return type_;} 52 : 53 : private: 54 : std::atomic<int> ref_count_; 55 : Type type_; 56 : }; 57 : 58 : struct EventNotifyHandle { 59 : typedef boost::shared_ptr<EventNotifyKey> KeyPtr; 60 : typedef boost::shared_ptr<EventNotifyHandle> Ptr; 61 : typedef boost::function<bool(void)> Callback; 62 : 63 : EventNotifyHandle(KeyPtr key, Callback cb); 64 : virtual ~EventNotifyHandle(); 65 0 : KeyPtr key() const {return key_;} 66 0 : void Notify() const {cb_();} 67 : 68 : private: 69 : KeyPtr key_; 70 : Callback cb_; 71 : }; 72 : 73 : class EventNotifier { 74 : public: 75 : //Callback 76 : typedef boost::function<bool(void)> Callback; 77 : //Key Ptr 78 : typedef boost::shared_ptr<EventNotifyKey> KeyPtr; 79 : typedef SmartPointerComparator<EventNotifyKey, boost::shared_ptr> Comparator; 80 : //subscriber callback list, vector of handles 81 : typedef std::vector<EventNotifyHandle::Ptr> SubscribersList; 82 : typedef SubscribersList::iterator SubscribersListIter; 83 : //key to call back list map 84 : typedef std::map<KeyPtr, SubscribersList, Comparator> NotifyMap; 85 : typedef NotifyMap::iterator NotifyMapIter; 86 : 87 : EventNotifier(Agent *agent); 88 : virtual ~EventNotifier(); 89 : 90 : //Publisher routines 91 : void Notify(EventNotifyKey *key); 92 : 93 : //Subscriber routines 94 : EventNotifyHandle::Ptr RegisterSubscriber(EventNotifyKey *key, 95 : Callback callback); 96 : void DeregisterSubscriber(EventNotifyHandle::Ptr ptr); 97 : 98 : private: 99 : struct WorkQueueMessage { 100 : public: 101 : typedef boost::shared_ptr<WorkQueueMessage> Ptr; 102 : enum Type { 103 : PUBLISHER, 104 : REGISTER_SUBSCRIBER, 105 : DEREGISTER_SUBSCRIBER 106 : }; 107 : WorkQueueMessage(Type type, EventNotifyHandle::Ptr handle); 108 : Type type_; 109 : EventNotifyHandle::Ptr handle_ptr_; 110 : }; 111 : //Work queue enqueue/dequeue 112 : bool Enqueue(WorkQueueMessage::Ptr data); 113 : bool Process(WorkQueueMessage::Ptr data); 114 : 115 : void NotifyInternal(KeyPtr key); 116 : void RegisterSubscriberInternal(EventNotifyHandle::Ptr ptr); 117 : void DeRegisterSubscriberInternal(EventNotifyHandle::Ptr ptr); 118 : 119 : NotifyMap map_; 120 : WorkQueue<WorkQueueMessage::Ptr> work_queue_; 121 : Agent *agent_; 122 : DISALLOW_COPY_AND_ASSIGN(EventNotifier); 123 : }; 124 : 125 : #endif //event_notifier_h