summaryrefslogtreecommitdiff
path: root/include/CommonAPI
diff options
context:
space:
mode:
authorJürgen Gehring <juergen.gehring@bmw.de>2015-07-28 06:46:54 -0700
committerJürgen Gehring <juergen.gehring@bmw.de>2015-07-28 06:46:54 -0700
commit3d2fb21d0e93b6b595610285e910ac80c099a174 (patch)
tree56265166864b3ce52ef713f827d4f580ec38f667 /include/CommonAPI
parent56d1059459c24971bcbf45adef60f6dfd0b44667 (diff)
downloadgenivi-common-api-runtime-3d2fb21d0e93b6b595610285e910ac80c099a174.tar.gz
CommonAPI 3.1.3
Diffstat (limited to 'include/CommonAPI')
-rw-r--r--include/CommonAPI/AttributeExtension.hpp17
-rw-r--r--include/CommonAPI/CommonAPI.hpp1
-rw-r--r--include/CommonAPI/Event.hpp150
-rw-r--r--include/CommonAPI/Extensions/AttributeCacheExtension.hpp129
-rw-r--r--include/CommonAPI/Logger.hpp19
-rw-r--r--include/CommonAPI/MainLoopContext.hpp9
6 files changed, 244 insertions, 81 deletions
diff --git a/include/CommonAPI/AttributeExtension.hpp b/include/CommonAPI/AttributeExtension.hpp
index aee1f8d..cc26723 100644
--- a/include/CommonAPI/AttributeExtension.hpp
+++ b/include/CommonAPI/AttributeExtension.hpp
@@ -4,7 +4,7 @@
// 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."
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
#endif
#ifndef COMMON_API_DBUS_ATTRIBUTE_EXTENSION_HPP_
@@ -17,10 +17,6 @@
#include <CommonAPI/Event.hpp>
#include <CommonAPI/Types.hpp>
-#ifdef WIN32
-#include "Attribute.hpp"
-#endif
-
namespace CommonAPI {
template<typename _AttributeType>
@@ -47,17 +43,6 @@ std::shared_ptr<
> createProxyWithDefaultAttributeExtension(
const std::string &_domain, const std::string &_instance);
-#ifdef WIN32
-template<typename _AttributeType>
-class WINDummyAttributeExtension : public CommonAPI::AttributeExtension<_AttributeType> {
- typedef AttributeExtension<_AttributeType> __baseClass_t;
- WINDummyAttribute dummyAttribute;
-public:
- WINDummyAttributeExtension() {};
- ~WINDummyAttributeExtension() {}
-};
-#endif
-
} // namespace CommonAPI
#endif // COMMON_API_DBUS_ATTRIBUTE_EXTENSION_HPP_
diff --git a/include/CommonAPI/CommonAPI.hpp b/include/CommonAPI/CommonAPI.hpp
index 5568330..81748d1 100644
--- a/include/CommonAPI/CommonAPI.hpp
+++ b/include/CommonAPI/CommonAPI.hpp
@@ -11,6 +11,7 @@
#endif
#include "Address.hpp"
+#include "Attribute.hpp"
#include "AttributeExtension.hpp"
#include "ByteBuffer.hpp"
#include "MainLoopContext.hpp"
diff --git a/include/CommonAPI/Event.hpp b/include/CommonAPI/Event.hpp
index 982f9a3..d56ea4b 100644
--- a/include/CommonAPI/Event.hpp
+++ b/include/CommonAPI/Event.hpp
@@ -66,14 +66,15 @@ public:
protected:
void notifyListeners(const _Arguments&... eventArguments);
+ void notifySpecificListener(const Subscription subscription, const _Arguments&... eventArguments);
virtual void onFirstListenerAdded(const Listener& listener) {}
- virtual void onListenerAdded(const Listener& listener) {}
+ virtual void onListenerAdded(const Listener& listener, const Subscription subscription) {}
virtual void onListenerRemoved(const Listener& listener) {}
virtual void onLastListenerRemoved(const Listener& listener) {}
-//private:
+private:
ListenersMap subscriptions_;
Subscription nextSubscription_;
@@ -86,80 +87,113 @@ protected:
template<typename ... _Arguments>
typename Event<_Arguments...>::Subscription Event<_Arguments...>::subscribe(Listener listener) {
- Subscription subscription;
- bool isFirstListener;
+ Subscription subscription;
+ bool isFirstListener;
- subscriptionMutex_.lock();
- subscription = nextSubscription_++;
- // TODO?: check for key/subscription overrun
- listener = pendingSubscriptions_[subscription] = std::move(listener);
- isFirstListener = (0 == subscriptions_.size());
- subscriptionMutex_.unlock();
+ subscriptionMutex_.lock();
+ subscription = nextSubscription_++;
+ // TODO?: check for key/subscription overrun
+ listener = pendingSubscriptions_[subscription] = std::move(listener);
+ isFirstListener = (0 == subscriptions_.size());
+ subscriptionMutex_.unlock();
- if (isFirstListener)
- onFirstListenerAdded(listener);
- onListenerAdded(listener);
+ if (isFirstListener)
+ onFirstListenerAdded(listener);
+ onListenerAdded(listener, subscription);
- return subscription;
+ return subscription;
}
template<typename ... _Arguments>
void Event<_Arguments...>::unsubscribe(Subscription subscription) {
- bool isLastListener(false);
- bool hasUnsubscribed(false);
+ bool isLastListener(false);
+ bool hasUnsubscribed(false);
+ Listener listener;
+
+ subscriptionMutex_.lock();
+ auto listenerIterator = subscriptions_.find(subscription);
+ if (subscriptions_.end() != listenerIterator
+ && pendingUnsubscriptions_.end() == pendingUnsubscriptions_.find(subscription)) {
+ listener = listenerIterator->second;
+ pendingUnsubscriptions_.insert(subscription);
+ isLastListener = (1 == subscriptions_.size());
+ hasUnsubscribed = true;
+ }
+ else {
+ listenerIterator = pendingSubscriptions_.find(subscription);
+ if (pendingSubscriptions_.end() != listenerIterator) {
+ listener = listenerIterator->second;
+ pendingSubscriptions_.erase(listenerIterator);
+ isLastListener = (0 == subscriptions_.size());
+ hasUnsubscribed = true;
+ }
+ }
+ subscriptionMutex_.unlock();
- subscriptionMutex_.lock();
- auto listener = subscriptions_.find(subscription);
- if (subscriptions_.end() != listener
- && pendingUnsubscriptions_.end() == pendingUnsubscriptions_.find(subscription)) {
- pendingUnsubscriptions_.insert(subscription);
- isLastListener = (1 == subscriptions_.size());
- hasUnsubscribed = true;
- }
- else {
- listener = pendingSubscriptions_.find(subscription);
- if (pendingSubscriptions_.end() != listener) {
- pendingSubscriptions_.erase(subscription);
- isLastListener = (0 == subscriptions_.size());
- hasUnsubscribed = true;
- }
- }
- subscriptionMutex_.unlock();
-
- if (hasUnsubscribed) {
- onListenerRemoved(listener->second);
- if (isLastListener) {
- onLastListenerRemoved(listener->second);
- }
- }
+ if (hasUnsubscribed) {
+ onListenerRemoved(listener);
+ if (isLastListener) {
+ onLastListenerRemoved(listener);
+ }
+ }
}
template<typename ... _Arguments>
void Event<_Arguments...>::notifyListeners(const _Arguments&... eventArguments) {
- subscriptionMutex_.lock();
- notificationMutex_.lock();
- for (auto iterator = pendingUnsubscriptions_.begin();
- iterator != pendingUnsubscriptions_.end();
- iterator++) {
- subscriptions_.erase(*iterator);
- }
- pendingUnsubscriptions_.clear();
-
- for (auto iterator = pendingSubscriptions_.begin();
- iterator != pendingSubscriptions_.end();
- iterator++) {
- subscriptions_.insert(*iterator);
- }
- pendingSubscriptions_.clear();
-
- subscriptionMutex_.unlock();
- for (auto iterator = subscriptions_.begin(); iterator != subscriptions_.end(); iterator++) {
+ subscriptionMutex_.lock();
+ notificationMutex_.lock();
+ for (auto iterator = pendingUnsubscriptions_.begin();
+ iterator != pendingUnsubscriptions_.end();
+ iterator++) {
+ subscriptions_.erase(*iterator);
+ }
+ pendingUnsubscriptions_.clear();
+
+ for (auto iterator = pendingSubscriptions_.begin();
+ iterator != pendingSubscriptions_.end();
+ iterator++) {
+ subscriptions_.insert(*iterator);
+ }
+ pendingSubscriptions_.clear();
+
+ subscriptionMutex_.unlock();
+ for (auto iterator = subscriptions_.begin(); iterator != subscriptions_.end(); iterator++) {
iterator->second(eventArguments...);
}
notificationMutex_.unlock();
}
+template<typename ... _Arguments>
+void Event<_Arguments...>::notifySpecificListener(const Subscription subscription, const _Arguments&... eventArguments) {
+ subscriptionMutex_.lock();
+ notificationMutex_.lock();
+ for (auto iterator = pendingUnsubscriptions_.begin();
+ iterator != pendingUnsubscriptions_.end();
+ iterator++) {
+ subscriptions_.erase(*iterator);
+ }
+ pendingUnsubscriptions_.clear();
+
+ for (auto iterator = pendingSubscriptions_.begin();
+ iterator != pendingSubscriptions_.end();
+ iterator++) {
+
+ subscriptions_.insert(*iterator);
+ }
+ pendingSubscriptions_.clear();
+
+
+ subscriptionMutex_.unlock();
+ for (auto iterator = subscriptions_.begin(); iterator != subscriptions_.end(); iterator++) {
+ if (subscription == iterator->first) {
+ iterator->second(eventArguments...);
+ }
+ }
+
+ notificationMutex_.unlock();
+}
+
} // namespace CommonAPI
#endif // COMMONAPI_EVENT_HPP_
diff --git a/include/CommonAPI/Extensions/AttributeCacheExtension.hpp b/include/CommonAPI/Extensions/AttributeCacheExtension.hpp
new file mode 100644
index 0000000..92bced6
--- /dev/null
+++ b/include/CommonAPI/Extensions/AttributeCacheExtension.hpp
@@ -0,0 +1,129 @@
+// Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// 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/.
+
+#ifndef COMMONAPI_EXTENSIONS_ATTRIBUTE_CACHE_EXTENSION_HPP_
+#define COMMONAPI_EXTENSIONS_ATTRIBUTE_CACHE_EXTENSION_HPP_
+
+#include <CommonAPI/CommonAPI.hpp>
+
+#include <cassert>
+#include <memory>
+#include <type_traits>
+
+namespace CommonAPI {
+namespace Extensions {
+
+template<typename _AttributeType,
+ bool = (std::is_base_of<
+ CommonAPI::ObservableAttribute<
+ typename _AttributeType::ValueType>,
+ _AttributeType>::value
+ || std::is_base_of<
+ CommonAPI::ObservableReadonlyAttribute<
+ typename _AttributeType::ValueType>,
+ _AttributeType>::value)>
+class AttributeCacheExtension {
+};
+
+template<typename _AttributeType>
+class AttributeCacheExtension<_AttributeType, false> : public CommonAPI::AttributeExtension<
+ _AttributeType> {
+protected:
+ typedef CommonAPI::AttributeExtension<_AttributeType> __baseClass_t;
+
+ typedef typename _AttributeType::ValueType value_t;
+
+ AttributeCacheExtension(_AttributeType& baseAttribute)
+ : CommonAPI::AttributeExtension<_AttributeType>(baseAttribute) {
+ }
+
+ ~AttributeCacheExtension() {
+ }
+};
+
+template<typename _AttributeType>
+class AttributeCacheExtension<_AttributeType, true> : public CommonAPI::AttributeExtension<
+ _AttributeType> {
+ typedef CommonAPI::AttributeExtension<_AttributeType> __baseClass_t;
+
+protected:
+ typedef typename _AttributeType::ValueType value_t;
+ typedef std::shared_ptr<const value_t> valueptr_t;
+
+ AttributeCacheExtension(_AttributeType& baseAttribute)
+ : CommonAPI::AttributeExtension<_AttributeType>(baseAttribute) {
+ auto &event = __baseClass_t::getBaseAttribute().getChangedEvent();
+ subscription_ =
+ event.subscribe(
+ std::bind(
+ &AttributeCacheExtension<_AttributeType, true>::onValueUpdate,
+ this, std::placeholders::_1));
+ }
+
+ ~AttributeCacheExtension() {
+ auto &event = __baseClass_t::getBaseAttribute().getChangedEvent();
+ event.unsubscribe(subscription_);
+ }
+
+public:
+ /**
+ * @brief getCachedValue Retrieve attribute value from the cache
+ * @return The value of the attribute or a null pointer if the value is not
+ * yet available. Retrieving a non-cached value will trigger
+ * retrieval of the value. Changes to the cached value are emitted
+ * via the getChangedEvent.
+ */
+ valueptr_t getCachedValue() {
+ if (cachedValue_) {
+ return cachedValue_;
+ }
+
+ // This may get called more than once if a previous retrieval is still
+ // on-going (saving the current state would just take up extra resources)
+ __baseClass_t::getBaseAttribute().getValueAsync(
+ std::bind(&AttributeCacheExtension<_AttributeType, true>::valueRetrieved,
+ this, std::placeholders::_1, std::placeholders::_2));
+
+ return nullptr;
+ }
+
+ /**
+ * @brief getCachedValue Retrieve attribute value from the cache returning a
+ * default value if the cache was empty.
+ * @param errorValue The value to return if the value could not be found in
+ * the cache.
+ * @return The value of the attribute or errorValue.
+ */
+ valueptr_t getCachedValue(const value_t &errorValue) {
+ valueptr_t result = getCachedValue();
+
+ if (!result)
+ result = std::make_shared<const value_t>(errorValue);
+
+ return result;
+ }
+
+private:
+
+ void valueRetrieved(const CommonAPI::CallStatus &callStatus, value_t t) {
+ if (callStatus == CommonAPI::CallStatus::SUCCESS) {
+ assert(!cachedValue_ || *cachedValue_ == t);
+ onValueUpdate(t);
+ }
+ }
+
+ void onValueUpdate(const value_t& t) {
+ cachedValue_ = std::make_shared<const value_t>(t);
+ }
+
+ valueptr_t cachedValue_;
+
+ typename _AttributeType::ChangedEvent::Subscription subscription_;
+};
+
+} // namespace Extensions
+} // namespace CommonAPI
+
+#endif // COMMONAPI_EXTENSIONS_ATTRIBUTE_CACHE_EXTENSION_HPP_
diff --git a/include/CommonAPI/Logger.hpp b/include/CommonAPI/Logger.hpp
index d2761ac..2247ea1 100644
--- a/include/CommonAPI/Logger.hpp
+++ b/include/CommonAPI/Logger.hpp
@@ -120,20 +120,25 @@ public:
};
COMMONAPI_EXPORT Logger();
+ COMMONAPI_EXPORT ~Logger();
template<typename... _LogEntries>
COMMONAPI_EXPORT static void log(Level _level, _LogEntries... _entries) {
- std::stringstream buffer;
- log_intern(buffer, _entries...);
- Logger::get()->doLog(_level, buffer.str());
+#if defined(USE_CONSOLE) || defined(USE_FILE) || defined(USE_DLT)
+ if (_level < maximumLogLevel_) {
+ std::stringstream buffer;
+ log_intern(buffer, _entries...);
+ Logger::get()->doLog(_level, buffer.str());
+ }
+#endif
}
- COMMONAPI_EXPORT static void init(bool, const std::string &, bool = false, const std::string & = "");
+ COMMONAPI_EXPORT static void init(bool, const std::string &, bool, const std::string &);
private:
- COMMONAPI_EXPORT static inline std::shared_ptr<Logger> get() {
- static std::shared_ptr<Logger> theLogger = std::make_shared<Logger>();
- return theLogger;
+ COMMONAPI_EXPORT static inline Logger *get() {
+ static Logger theLogger;
+ return &theLogger;
}
COMMONAPI_EXPORT static void log_intern(std::stringstream &_buffer) {
diff --git a/include/CommonAPI/MainLoopContext.hpp b/include/CommonAPI/MainLoopContext.hpp
index b2e1056..4487292 100644
--- a/include/CommonAPI/MainLoopContext.hpp
+++ b/include/CommonAPI/MainLoopContext.hpp
@@ -111,6 +111,15 @@ struct Watch {
*/
virtual const pollfd& getAssociatedFileDescriptor() = 0;
+#ifdef WIN32
+ /**
+ * \brief Returns the event bound to the file descriptor that is managed by this watch.
+ *
+ * @return The event bound to the associated file descriptor.
+ */
+ virtual const HANDLE& getAssociatedEvent() = 0;
+#endif
+
/**
* \brief Returns a vector of all dispatch sources that depend on the watched file descriptor.
*