summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Laner <laner@itestra.de>2013-07-29 16:36:07 +0200
committerJohannes Schanda <schanda@itestra.de>2013-09-03 18:31:37 +0200
commit0e0aee2aa57114693ba051b2524dcc400966e266 (patch)
tree5d9d21a7fb820f3286847a424d19b72df5e06f6c
parentcb33c616711c7e13b3a14123fbd41fa9dcb92f2a (diff)
downloadgenivi-common-api-runtime-0e0aee2aa57114693ba051b2524dcc400966e266.tar.gz
Added support for selective broadcasts
-Add subclass for event to support additional API for selective -Add hash specialisation for ClientID hashes Change-Id: Ic708338c5e4a821c908a174ca373d212b5f7b3ee
-rw-r--r--Makefile.am5
-rw-r--r--src/CommonAPI/ContainerUtils.cpp21
-rw-r--r--src/CommonAPI/ContainerUtils.h33
-rw-r--r--src/CommonAPI/Event.h197
-rw-r--r--src/CommonAPI/SelectiveEvent.h38
-rw-r--r--src/CommonAPI/Stub.h30
-rw-r--r--src/CommonAPI/types.h21
7 files changed, 237 insertions, 108 deletions
diff --git a/Makefile.am b/Makefile.am
index 136aac9..e1fc9ab 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -35,7 +35,8 @@ lib_LTLIBRARIES = libCommonAPI.la
libCommonAPI_la_SOURCES = \
src/CommonAPI/Runtime.cpp \
- src/CommonAPI/Configuration.cpp
+ src/CommonAPI/Configuration.cpp \
+ src/CommonAPI/ContainerUtils.cpp
CommonAPI_includedir=$(includedir)/CommonAPI-${VERSION}/CommonAPI
CommonAPI_include_HEADERS = \
@@ -44,6 +45,7 @@ CommonAPI_include_HEADERS = \
src/CommonAPI/ByteBuffer.h \
src/CommonAPI/CommonAPI.h \
src/CommonAPI/Configuration.h \
+ src/CommonAPI/ContainerUtils.h \
src/CommonAPI/Event.h \
src/CommonAPI/Factory.h \
src/CommonAPI/Factory.hpp \
@@ -53,6 +55,7 @@ CommonAPI_include_HEADERS = \
src/CommonAPI/OutputStream.h \
src/CommonAPI/Proxy.h \
src/CommonAPI/Runtime.h \
+ src/CommonAPI/SelectiveEvent.h \
src/CommonAPI/SerializableStruct.h \
src/CommonAPI/SerializableVariant.h \
src/CommonAPI/SerializableVariant.hpp \
diff --git a/src/CommonAPI/ContainerUtils.cpp b/src/CommonAPI/ContainerUtils.cpp
new file mode 100644
index 0000000..bb1a360
--- /dev/null
+++ b/src/CommonAPI/ContainerUtils.cpp
@@ -0,0 +1,21 @@
+/* Copyright (C) 2013 BMW Group
+ * Author: Manfred Bathelt (manfred.bathelt@bmw.de)
+ * Author: Juergen Gehring (juergen.gehring@bmw.de)
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ContainerUtils.h"
+#include "types.h"
+
+namespace CommonAPI {
+
+size_t SharedPointerClientIdContentHash::operator()(const std::shared_ptr<ClientId>& t) const {
+ return t->hashCode();
+}
+
+bool SharedPointerClientIdContentEqual::operator()(const std::shared_ptr<ClientId>& a, const std::shared_ptr<ClientId>& b) const {
+ return *a==*b;
+}
+
+} // namespace std
diff --git a/src/CommonAPI/ContainerUtils.h b/src/CommonAPI/ContainerUtils.h
new file mode 100644
index 0000000..a4423ab
--- /dev/null
+++ b/src/CommonAPI/ContainerUtils.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2013 BMW Group
+ * Author: Manfred Bathelt (manfred.bathelt@bmw.de)
+ * Author: Juergen Gehring (juergen.gehring@bmw.de)
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef FUNCTIONALHASH_H_
+#define FUNCTIONALHASH_H_
+
+#include <functional>
+#include <memory>
+
+namespace CommonAPI {
+class ClientId;
+
+struct SharedPointerClientIdContentHash : public std::unary_function<std::shared_ptr<ClientId>, size_t> {
+ size_t operator()(const std::shared_ptr<ClientId>& t) const;
+};
+
+struct SharedPointerClientIdContentEqual : public std::binary_function<std::shared_ptr<ClientId>, std::shared_ptr<ClientId>, bool> {
+ bool operator()(const std::shared_ptr<ClientId>& a, const std::shared_ptr<ClientId>& b) const;
+};
+
+
+} // namespace std
+
+
+#endif /* FUNCTIONALHASH_H_ */
diff --git a/src/CommonAPI/Event.h b/src/CommonAPI/Event.h
index b032da9..9cac1dc 100644
--- a/src/CommonAPI/Event.h
+++ b/src/CommonAPI/Event.h
@@ -20,8 +20,8 @@
namespace CommonAPI {
enum class SubscriptionStatus {
- RETAIN,
- CANCEL
+ RETAIN,
+ CANCEL
};
/**
@@ -29,33 +29,33 @@ enum class SubscriptionStatus {
*
* Class representing an event
*/
-template <typename... _Arguments>
+template<typename ... _Arguments>
class Event {
- public:
- typedef std::tuple<_Arguments...> ArgumentsTuple;
- typedef std::function<void(const _Arguments&...)> Listener;
- typedef std::function<SubscriptionStatus(const _Arguments&...)> CancellableListener;
- typedef std::list<CancellableListener> ListenersList;
- typedef typename ListenersList::iterator Subscription;
-
- class CancellableListenerWrapper;
-
- /**
- * \brief Subscribe a listener to this event
- *
- * Subscribe a listener to this event.
- * ATTENTION: You should not build new proxies or register services in callbacks
- * from events. This can cause a deadlock or assert. Instead, you should set a
- * trigger for your application to do this on the next iteration of your event loop
- * if needed. The preferred solution is to build all proxies you need at the
- * beginning and react to events appropriatly for each.
- *
- * @param listener A listener to be added
- * @return A token identifying this subscription
- */
- inline Subscription subscribe(Listener listener);
-
- /**
+public:
+ typedef std::tuple<_Arguments...> ArgumentsTuple;
+ typedef std::function<void(const _Arguments&...)> Listener;
+ typedef std::function<SubscriptionStatus(const _Arguments&...)> CancellableListener;
+ typedef std::list<CancellableListener> ListenersList;
+ typedef typename ListenersList::iterator Subscription;
+
+ class CancellableListenerWrapper;
+
+ /**
+ * \brief Subscribe a listener to this event
+ *
+ * Subscribe a listener to this event.
+ * ATTENTION: You should not build new proxies or register services in callbacks
+ * from events. This can cause a deadlock or assert. Instead, you should set a
+ * trigger for your application to do this on the next iteration of your event loop
+ * if needed. The preferred solution is to build all proxies you need at the
+ * beginning and react to events appropriatly for each.
+ *
+ * @param listener A listener to be added
+ * @return A token identifying this subscription
+ */
+ virtual inline Subscription subscribe(Listener listener);
+
+ /**
* \brief Subscribe a cancellable listener to this event
*
* Subscribe a cancellable listener to this event
@@ -68,119 +68,124 @@ class Event {
* @param listener A cancellable listener to be added
* @return A token identifying this subscription
*/
- Subscription subscribeCancellableListener(CancellableListener listener);
+ Subscription subscribeCancellableListener(CancellableListener listener);
- /**
+ /**
* \brief Remove a listener from this event
*
* Remove a listener from this event
* Note: Do not call this inside a listener notification callback it will deadlock! Use cancellable listeners instead.
*
* @param listenerSubscription A listener token to be removed
+ * @return true, if the removed subscription was the last one
*/
- void unsubscribe(Subscription listenerSubscription);
+ void unsubscribe(Subscription listenerSubscription);
- virtual ~Event() {}
+ virtual ~Event() {
+ }
- protected:
- // Returns false if all subscriptions were cancelled
- // Does not send *Removed events!
- SubscriptionStatus notifyListeners(const _Arguments&... eventArguments);
+protected:
+ // Returns false if all subscriptions were cancelled
+ // Does not send *Removed events!
+ SubscriptionStatus notifyListeners(const _Arguments&... eventArguments);
- // Events sent during subscribe()
- virtual void onFirstListenerAdded(const CancellableListener& listener) { }
- virtual void onListenerAdded(const CancellableListener& listener) { }
+ // Events sent during subscribe()
+ virtual void onFirstListenerAdded(const CancellableListener& listener) {
+ }
+ virtual void onListenerAdded(const CancellableListener& listener) {
+ }
- // Events sent during unsubscribe()
- virtual void onListenerRemoved(const CancellableListener& listener) { }
- virtual void onLastListenerRemoved(const CancellableListener& listener) { }
+ // Events sent during unsubscribe()
+ virtual void onListenerRemoved(const CancellableListener& listener) { }
+ virtual void onLastListenerRemoved(const CancellableListener& listener) { }
- inline bool hasListeners() const;
+ inline bool hasListeners() const;
- private:
- ListenersList listenersList_;
- std::mutex listenerListMutex_;
+//private:
+ ListenersList listenersList_;
+ std::mutex listenerListMutex_;
};
-template <typename... _Arguments>
+template<typename ... _Arguments>
class Event<_Arguments...>::CancellableListenerWrapper {
- public:
- CancellableListenerWrapper(Listener&& listener): listener_(std::move(listener)) {
- }
-
- SubscriptionStatus operator()(const _Arguments&... eventArguments) {
- listener_(eventArguments...);
- return SubscriptionStatus::RETAIN;
- }
-
- private:
- Listener listener_;
+public:
+ CancellableListenerWrapper(Listener&& listener) :
+ listener_(std::move(listener)) {
+ }
+
+ SubscriptionStatus operator()(const _Arguments&... eventArguments) {
+ listener_(eventArguments...);
+ return SubscriptionStatus::RETAIN;
+ }
+
+private:
+ Listener listener_;
};
-template <typename... _Arguments>
+template<typename ... _Arguments>
typename Event<_Arguments...>::Subscription Event<_Arguments...>::subscribe(Listener listener) {
- return subscribeCancellableListener(CancellableListenerWrapper(std::move(listener)));
+ return subscribeCancellableListener(CancellableListenerWrapper(std::move(listener)));
}
-template <typename... _Arguments>
+template<typename ... _Arguments>
typename Event<_Arguments...>::Subscription Event<_Arguments...>::subscribeCancellableListener(CancellableListener listener) {
listenerListMutex_.lock();
const bool firstListenerAdded = listenersList_.empty();
- listenersList_.emplace_front(std::move(listener));
- Subscription listenerSubscription = listenersList_.begin();
- listenerListMutex_.unlock();
+ listenersList_.emplace_front(std::move(listener));
+ Subscription listenerSubscription = listenersList_.begin();
+ listenerListMutex_.unlock();
- if (firstListenerAdded) {
- onFirstListenerAdded(*listenerSubscription);
- }
+ if (firstListenerAdded) {
+ onFirstListenerAdded(*listenerSubscription);
+ }
- onListenerAdded(*listenerSubscription);
+ onListenerAdded(*listenerSubscription);
- return listenerSubscription;
+ return listenerSubscription;
}
-template <typename... _Arguments>
+template<typename ... _Arguments>
void Event<_Arguments...>::unsubscribe(Subscription listenerSubscription) {
- const CancellableListener cancellableListener = *listenerSubscription;
+ const CancellableListener cancellableListener = *listenerSubscription;
- listenerListMutex_.lock();
- listenersList_.erase(listenerSubscription);
- const bool lastListenerRemoved = listenersList_.empty();
- listenerListMutex_.unlock();
+ listenerListMutex_.lock();
+ listenersList_.erase(listenerSubscription);
+ const bool lastListenerRemoved = listenersList_.empty();
+ listenerListMutex_.unlock();
- onListenerRemoved(cancellableListener);
+ onListenerRemoved(cancellableListener);
- if (lastListenerRemoved) {
- onLastListenerRemoved(cancellableListener);
- }
+ if (lastListenerRemoved) {
+ onLastListenerRemoved(cancellableListener);
+ }
}
-template <typename... _Arguments>
+template<typename ... _Arguments>
SubscriptionStatus Event<_Arguments...>::notifyListeners(const _Arguments&... eventArguments) {
- listenerListMutex_.lock();
- for (auto iterator = listenersList_.begin(); iterator != listenersList_.end(); ) {
- const CancellableListener& cancellableListener = *iterator;
- const SubscriptionStatus listenerSubscriptionStatus = cancellableListener(eventArguments...);
+ listenerListMutex_.lock();
+ for (auto iterator = listenersList_.begin(); iterator != listenersList_.end();) {
+ const CancellableListener& cancellableListener = *iterator;
+ const SubscriptionStatus listenerSubscriptionStatus = cancellableListener(eventArguments...);
- if (listenerSubscriptionStatus == SubscriptionStatus::CANCEL) {
- auto listenerIterator = iterator;
- iterator++;
- listenersList_.erase(listenerIterator);
- } else
- iterator++;
- }
+ if (listenerSubscriptionStatus == SubscriptionStatus::CANCEL) {
+ auto listenerIterator = iterator;
+ iterator++;
+ listenersList_.erase(listenerIterator);
+ } else
+ iterator++;
+ }
- const bool lEmpty = listenersList_.empty();
+ const bool lEmpty = listenersList_.empty();
- listenerListMutex_.unlock();
+ listenerListMutex_.unlock();
- return lEmpty ? SubscriptionStatus::CANCEL : SubscriptionStatus::RETAIN;
+ return lEmpty ? SubscriptionStatus::CANCEL : SubscriptionStatus::RETAIN;
}
-template <typename... _Arguments>
+template<typename ... _Arguments>
bool Event<_Arguments...>::hasListeners() const {
- return !listenersList_.empty();
+ return !listenersList_.empty();
}
} // namespace CommonAPI
diff --git a/src/CommonAPI/SelectiveEvent.h b/src/CommonAPI/SelectiveEvent.h
new file mode 100644
index 0000000..11612c3
--- /dev/null
+++ b/src/CommonAPI/SelectiveEvent.h
@@ -0,0 +1,38 @@
+/* Copyright (C) 2013 BMW Group
+ * Author: Manfred Bathelt (manfred.bathelt@bmw.de)
+ * Author: Juergen Gehring (juergen.gehring@bmw.de)
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_SELECTIVE_EVENT_H_
+#define COMMONAPI_SELECTIVE_EVENT_H_
+
+#include "Event.h"
+
+namespace CommonAPI {
+
+template<typename ... _Arguments>
+class SelectiveEvent: public Event<_Arguments...> {
+public:
+ typedef typename Event<_Arguments...>::Listener Listener;
+ typedef typename Event<_Arguments...>::Subscription Subscription;
+
+ virtual ~SelectiveEvent() {
+ }
+
+ Subscription subscribe(Listener listener) {
+ // just delegate
+ bool success;
+ return subscribe(listener, success);
+ }
+ virtual Subscription subscribe(Listener listener, bool& success) = 0;
+};
+
+} // namespace CommonAPI
+
+#endif
diff --git a/src/CommonAPI/Stub.h b/src/CommonAPI/Stub.h
index 22892f4..d724548 100644
--- a/src/CommonAPI/Stub.h
+++ b/src/CommonAPI/Stub.h
@@ -19,8 +19,9 @@
namespace CommonAPI {
class StubAdapter {
- public:
- virtual ~StubAdapter() { }
+public:
+ virtual ~StubAdapter() {
+ }
virtual const std::string getAddress() const = 0;
virtual const std::string& getDomain() const = 0;
@@ -29,19 +30,26 @@ class StubAdapter {
};
struct StubBase {
- virtual ~StubBase() {}
+ virtual ~StubBase() {
+ }
};
-template <typename _StubAdapter, typename _StubRemoteEventHandler>
-class Stub : public StubBase {
- static_assert(std::is_base_of<StubAdapter, _StubAdapter>::value, "Invalid StubAdapter Class!");
- public:
- typedef _StubAdapter StubAdapterType;
- typedef _StubRemoteEventHandler RemoteEventHandlerType;
+template<typename _StubAdapter, typename _StubRemoteEventHandler>
+class Stub: public StubBase {
+ static_assert(std::is_base_of<StubAdapter, _StubAdapter>::value, "Invalid StubAdapter Class!");
+ public:
+ typedef _StubAdapter StubAdapterType;
+ typedef _StubRemoteEventHandler RemoteEventHandlerType;
- virtual ~Stub() { }
+ virtual ~Stub() {
+ }
- virtual _StubRemoteEventHandler* initStubAdapter(const std::shared_ptr<_StubAdapter>& stubAdapter) = 0;
+ virtual _StubRemoteEventHandler* initStubAdapter(const std::shared_ptr<_StubAdapter>& stubAdapter) = 0;
+};
+
+enum SelectiveBroadcastSubscriptionEvent {
+ SUBSCRIBED,
+ UNSUBSCRIBED
};
} // namespace CommonAPI
diff --git a/src/CommonAPI/types.h b/src/CommonAPI/types.h
index f8663f1..ffc338c 100644
--- a/src/CommonAPI/types.h
+++ b/src/CommonAPI/types.h
@@ -13,6 +13,12 @@
#define COMMONAPI_TYPES_H_
#include <cstdint>
+#include <functional>
+#include <unordered_set>
+#include <memory>
+#include <tuple>
+#include "ContainerUtils.h"
+#include "Event.h"
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
# define COMMONAPI_DEPRECATED __attribute__ ((__deprecated__))
@@ -61,7 +67,22 @@ class ClientId {
public:
virtual ~ClientId() { }
virtual bool operator==(ClientId& clientIdToCompare) = 0;
+ virtual std::size_t hashCode() = 0;
};
+
+template <typename ... Args>
+struct SelectiveBroadcastFunctorHelper {
+ typedef std::function<SubscriptionStatus(Args...)> SelectiveBroadcastFunctor;
+};
+
+
+typedef std::unordered_set<std::shared_ptr<CommonAPI::ClientId>, SharedPointerClientIdContentHash, SharedPointerClientIdContentEqual> ClientIdList;
+template <typename ... Args>
+struct SelectiveBroadcastSubscriptionResult {
+ typedef std::tuple<bool, typename CommonAPI::Event<Args...>::Subscription> SubscriptionResult;
+
+};
+
} // namespace CommonAPI
#endif // COMMONAPI_TYPES_H_