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