event bus implementation
authorLukasz Stanislawski <l.stanislaws@samsung.com>
Wed, 31 Aug 2016 06:37:01 +0000 (08:37 +0200)
committerLukasz Stanislawski <l.stanislaws@samsung.com>
Tue, 13 Sep 2016 06:04:17 +0000 (08:04 +0200)
Create global bus for application events. Allows
multiple observers to register on one particular event.

Change-Id: I4da624c7cf492224ba53431fd6e03781eb3c81a5

clock/inc/Utils/EventBus.h [new file with mode: 0644]
clock/src/Utils/EventBus.cpp [new file with mode: 0644]

diff --git a/clock/inc/Utils/EventBus.h b/clock/inc/Utils/EventBus.h
new file mode 100644 (file)
index 0000000..94ade98
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _CLOCK_EVENT_BUS_H_
+#define _CLOCK_EVENT_BUS_H_
+
+#include <functional>
+#include <vector>
+#include <map>
+
+namespace utils {
+       class Event {
+               public:
+                       Event(int type) : type_(type) {}
+                       virtual ~Event() {}
+                       int GetType() const { return type_; }
+               private:
+                       int type_;
+       };
+       /**
+        * @brief EventBus class is not thread safe. Please avoid using EventBus in
+        * multithreaded applications.
+        *
+        * How to use Event bus:
+        *
+        * 1. Create new Event type class with static type identifier.
+        * 2. Define static variable identyfying type of your class
+        * 3. Define static function to get event type of your class
+        *
+        * Example:
+        *
+        * class DerivedEvent : public Event {
+        *    public:
+        *        DerivedEvent() : Event(EventType()) {}
+        *    private:
+        *        static int custom_type_;
+        *        static int EventType() {
+        *            if (custom_type_ == 0) {
+        *                custom_type = EventBus::RegisterNewEventType();
+        *            }
+        *            return custom_type;
+        *        }
+        * }
+        *
+        * how to register on evnet:
+        * EventBus::RegisterHandler(DerivedEvent::EventType(), some_callback)
+        *
+        * how to fire event
+        * EventBus::FireEvent(new DerivedEvent());
+        *
+        */
+       class EventBus {
+               public:
+                       /**
+                        * @brief Registers new data type
+                        * @return new event type descriptor (> 1)
+                        */
+                       static int RegisterNewEventType();
+
+                       /**
+                        * @brief Registers handler for given event type
+                        */
+                       static void RegisterHandler(int type, std::function<void(Event*)>);
+
+                       /**
+                        * @brief Deregisters handler for given event type
+                        */
+                       static void DeregisterHandler(int type, std::function<void(Event*)>);
+
+                       /**
+                        * @brief Fire event. This means running all handlers registered
+                        * with @RegisterHandler function.
+                        *
+                        * @param must be allocated with 'new' operator
+                        */
+                       static void FireEvent(Event*);
+
+                       /**
+                        * @brief Deleted copy constructor
+                        */
+                       EventBus(const EventBus &bus) = delete;
+
+                       /**
+                        * @brief Deleted assignment operator
+                        */
+                       void operator=(const EventBus &bus) = delete;
+               private:
+                       static EventBus& GetInstance();
+                       EventBus();
+                       int current_event_id_;
+                       std::map<int, std::vector<std::function<void(Event*)>>> callbacks_;
+       };
+} /* utils */
+
+#endif
diff --git a/clock/src/Utils/EventBus.cpp b/clock/src/Utils/EventBus.cpp
new file mode 100644 (file)
index 0000000..d28c847
--- /dev/null
@@ -0,0 +1,54 @@
+#include "Utils/EventBus.h"
+#include <algorithm>
+
+using namespace utils;
+
+int EventBus::RegisterNewEventType()
+{
+       EventBus &bus = GetInstance();
+       return ++bus.current_event_id_;
+}
+
+void EventBus::RegisterHandler(int type, std::function<void(Event*)> func)
+{
+       EventBus &bus = GetInstance();
+       bus.callbacks_[type].push_back(func);
+}
+
+void EventBus::DeregisterHandler(int type, std::function<void(Event*)> func)
+{
+       EventBus &bus = GetInstance();
+       auto it = bus.callbacks_[type].begin();
+
+       // std::function do not have default comprarison operator, so compare
+       // them by target type's name and by pointer to stored type
+       for (it = bus.callbacks_[type].begin(); it != bus.callbacks_[type].end(); ++it) {
+               if (it->target_type().name() == func.target_type().name() &&
+                       it->target<void(Event*)>() == func.target<void(Event*)>()) {
+                       break;
+               }
+       }
+
+       if (it != bus.callbacks_[type].end()) {
+               bus.callbacks_[type].erase(it);
+       }
+}
+
+void EventBus::FireEvent(Event *event)
+{
+       EventBus &bus = GetInstance();
+       for (auto func: bus.callbacks_[event->GetType()]) {
+               func(event);
+       }
+       delete event;
+}
+
+EventBus& EventBus::GetInstance()
+{
+       static EventBus bus;
+       return bus;
+}
+
+EventBus::EventBus()
+{
+}