summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Rauwolf <rauwolf@itestra.de>2013-04-18 15:33:05 +0200
committerPhilip Rauwolf <rauwolf@itestra.de>2013-04-18 15:33:05 +0200
commit9172b25386ddd12cde97ad5382d7968f8437a53d (patch)
tree1d9c77704d8ef28083a5a48bac1a579867c00797
parent494c298ce4b02d96c5b12773af20ef858596b5ef (diff)
downloadgenivi-common-api-runtime-9172b25386ddd12cde97ad5382d7968f8437a53d.tar.gz
Added MainloopContext
Change-Id: Ic44bb8c9340c426bb1c3c7ab82dcede5f6f55e7e
-rw-r--r--Makefile.am35
-rw-r--r--src/CommonAPI/MainLoopContext.h323
-rw-r--r--src/CommonAPI/Runtime.cpp5
-rw-r--r--src/CommonAPI/Runtime.h15
4 files changed, 360 insertions, 18 deletions
diff --git a/Makefile.am b/Makefile.am
index c3a79fb..bc817d1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,9 +14,9 @@ MOSTLYCLEANFILES += ${DX_CLEANFILES}
# ------------------------------------------------------------------------------
MAINTAINERCLEANFILES = \
- Makefile.in \
- aclocal.m4 \
- configure
+ Makefile.in \
+ aclocal.m4 \
+ configure
clean-local:
-rm -rf src-gen
@@ -27,34 +27,35 @@ maintainer-clean-local:
-rm -f m4/libtool*.m4
-rm -f m4/lt*.m4
-
+
lib_LTLIBRARIES = libCommonAPI.la
libCommonAPI_la_SOURCES = \
- src/CommonAPI/Runtime.cpp
+ src/CommonAPI/Runtime.cpp
CommonAPI_includedir=$(includedir)/CommonAPI-${VERSION}/CommonAPI
CommonAPI_include_HEADERS = \
- src/CommonAPI/Attribute.h \
+ src/CommonAPI/Attribute.h \
src/CommonAPI/AttributeExtension.h \
src/CommonAPI/ByteBuffer.h \
src/CommonAPI/Event.h \
src/CommonAPI/Factory.h \
- src/CommonAPI/InputStream.h \
+ src/CommonAPI/InputStream.h \
+ src/CommonAPI/MainLoopContext.h \
src/CommonAPI/MiddlewareInfo.h \
- src/CommonAPI/OutputStream.h \
+ src/CommonAPI/OutputStream.h \
src/CommonAPI/Proxy.h \
- src/CommonAPI/Runtime.h \
- src/CommonAPI/SerializableStruct.h \
- src/CommonAPI/SerializableVariant.h \
- src/CommonAPI/SerializableVariant.hpp \
- src/CommonAPI/Stub.h \
- src/CommonAPI/types.h
+ src/CommonAPI/Runtime.h \
+ src/CommonAPI/SerializableStruct.h \
+ src/CommonAPI/SerializableVariant.h \
+ src/CommonAPI/SerializableVariant.hpp \
+ src/CommonAPI/Stub.h \
+ src/CommonAPI/types.h
libCommonAPI_la_LIBADD = -ldl
libCommonAPI_la_LDFLAGS = \
- ${AM_LDFLAGS} \
- -version-info ${LIBCOMMONAPI_CURRENT}:${LIBCOMMONAPI_REVISION}:${LIBCOMMONAPI_AGE}
+ ${AM_LDFLAGS} \
+ -version-info ${LIBCOMMONAPI_CURRENT}:${LIBCOMMONAPI_REVISION}:${LIBCOMMONAPI_AGE}
pkgconfigdir = ${libdir}/pkgconfig
pkgconfig_DATA = CommonAPI.pc
@@ -63,7 +64,7 @@ pkgconfig_DATA = CommonAPI.pc
if ENABLE_TESTS
check_PROGRAMS = \
- VariantTest
+ VariantTest
TESTS = ${check_PROGRAMS}
diff --git a/src/CommonAPI/MainLoopContext.h b/src/CommonAPI/MainLoopContext.h
new file mode 100644
index 0000000..13bc4d9
--- /dev/null
+++ b/src/CommonAPI/MainLoopContext.h
@@ -0,0 +1,323 @@
+/* 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/. */
+
+#ifndef COMMONAPI_MAIN_LOOP_CONTEXT_H_
+#define COMMONAPI_MAIN_LOOP_CONTEXT_H_
+
+
+#include <stdint.h>
+#include <poll.h>
+#include <limits>
+#include <vector>
+#include <chrono>
+
+
+namespace CommonAPI {
+
+
+enum class DispatchPriority {
+ VERY_HIGH,
+ HIGH,
+ DEFAULT,
+ LOW,
+ VERY_LOW
+};
+
+
+static int64_t getCurrentTimeInMs() {
+ return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
+}
+
+
+/**
+ * \brief Describes a basic element that periodically needs to be dispatched.
+ *
+ * A DispatchSource is not directly related to a file descriptor, but
+ * may be dependent on a watch that manages a file descriptor. If this
+ * is the case, the corresponding Watch will provide information about
+ * which DispatchSources are dependent.
+ */
+struct DispatchSource {
+ virtual ~DispatchSource() {}
+
+ /**
+ * Indicates whether this source is ready to be dispatched.
+ * "Prepare" will be called before polling the file descriptors.
+ *
+ * @return 'true' if the source is ready to be dispatched.
+ */
+ virtual bool prepare(int64_t& timeout) = 0;
+
+ /**
+ * Indicates whether this source is ready to be dispatched.
+ * "Check" will be called after polling the file descriptors.
+ *
+ * @return 'true' if the source is ready to be dispatched.
+ */
+ virtual bool check() = 0;
+
+ /**
+ * The return value indicates whether this dispatch source currently has
+ * more data to dispatch. The mainloop may chose to ignore the return value.
+ *
+ * @return 'true' if there currently is more to dispatch, 'false' if not.
+ */
+ virtual bool dispatch() = 0;
+};
+
+
+/**
+ * \brief Describes an element that manages a file descriptor.
+ *
+ * The watch is ready to be dispatched whenever it's managed file descriptor
+ * has events in it's revents-field.
+ *
+ * It is possible that there are DispatchSources of which the dispatch readiness
+ * directly depends on the dispatching of the watch. If this is the case, such
+ * DispatchSources can be retrieved from this Watch.
+ */
+struct Watch {
+ virtual ~Watch() {}
+
+ /**
+ * \brief Dispatches the watch.
+ *
+ * Should only be called once the associated file descriptor has events ready.
+ *
+ * @param eventFlags The events that shall be retrieved from the file descriptor.
+ */
+ virtual void dispatch(unsigned int eventFlags) = 0;
+
+ /**
+ * \brief Returns the file descriptor that is managed by this watch.
+ *
+ * @return The associated file descriptor.
+ */
+ virtual const pollfd& getAssociatedFileDescriptor() = 0;
+
+ /**
+ * \brief Returns a vector of all dispatch sources that depend on the watched file descriptor.
+ *
+ * The returned vector will not be empty if and only if there are any sources
+ * that depend on availability of data of the watched file descriptor. Whenever this
+ * Watch is dispatched, those sources likely also need to be dispatched.
+ */
+ virtual const std::vector<DispatchSource*>& getDependentDispatchSources() = 0;
+};
+
+
+constexpr int64_t TIMEOUT_INFINITE = std::numeric_limits<int64_t>::max();
+constexpr int64_t TIMEOUT_NONE = 0;
+
+
+/**
+ * \brief Describes a basic timeout.
+ *
+ * Timeouts will be taken into consideration when waiting in a call to poll
+ * for a file descriptor to become ready. When the lowest known timeout expires,
+ * the call to poll will return, regardless of whether a file descriptor was ready
+ * or not.
+ */
+struct Timeout {
+ virtual ~Timeout() {}
+
+ /**
+ * Needs to be called when this timeout is expired.
+ *
+ * @return 'true' if the timeout shall be rescheduled, 'false' if it shall be removed.
+ */
+ virtual bool dispatch() = 0;
+
+ /**
+ * \brief The timeout interval in milliseconds.
+ *
+ * Returns TIMEOUT_INFINITE for "dispatch never", TIMEOUT_NONE for "dispatch immediately",
+ * or any positive value as an interval of time in milliseconds that needs to pass before
+ * this timeout is to be dispatched.
+ */
+ virtual int64_t getTimeoutInterval() const = 0;
+
+ /**
+ * \brief Returns the point in time at which this timeout needs to be dispatched next.
+ *
+ * After a initialization and after each dispatch, this timeout will re-calculate it's next
+ * ready time. This value may be ignored if a different mechanism for monitoring timeout intervals
+ * is used.
+ */
+ virtual int64_t getReadyTime() const = 0;
+};
+
+
+typedef std::function<void(DispatchSource*, const DispatchPriority)> DispatchSourceAddedCallback;
+typedef std::function<void(DispatchSource*)> DispatchSourceRemovedCallback;
+typedef std::function<void(Watch*, const DispatchPriority)> WatchAddedCallback;
+typedef std::function<void(Watch*)> WatchRemovedCallback;
+typedef std::function<void(Timeout*, const DispatchPriority)> TimeoutSourceAddedCallback;
+typedef std::function<void(Timeout*)> TimeoutSourceRemovedCallback;
+typedef std::function<void()> WakeupCallback;
+
+typedef std::list<std::pair<DispatchSourceAddedCallback, DispatchSourceRemovedCallback>> DispatchSourceListenerList;
+typedef std::list<std::pair<WatchAddedCallback, WatchRemovedCallback>> WatchListenerList;
+typedef std::list<std::pair<TimeoutSourceAddedCallback, TimeoutSourceRemovedCallback>> TimeoutSourceListenerList;
+typedef std::list<WakeupCallback> WakeupListenerList;
+
+typedef DispatchSourceListenerList::iterator DispatchSourceListenerSubscription;
+typedef WatchListenerList::iterator WatchListenerSubscription;
+typedef TimeoutSourceListenerList::iterator TimeoutSourceListenerSubscription;
+typedef WakeupListenerList::iterator WakeupListenerSubscription;
+
+
+/**
+ * \brief Provides hooks for your Main Loop implementation.
+ *
+ * By registering callbacks with this class, you will be notified about all DispatchSources,
+ * Watches, Timeouts and Wakeup-Events that need to be handled by your Main Loop implementation.
+ *
+ */
+class MainLoopContext {
+ public:
+ MainLoopContext() {}
+ MainLoopContext(const MainLoopContext&) = delete;
+ MainLoopContext& operator=(const MainLoopContext&) = delete;
+ MainLoopContext(MainLoopContext&&) = delete;
+ MainLoopContext& operator=(MainLoopContext&&) = delete;
+
+ /**
+ * \brief Registers for all DispatchSources that are added or removed.
+ */
+ inline DispatchSourceListenerSubscription subscribeForDispatchSources(DispatchSourceAddedCallback dispatchAddedCallback, DispatchSourceRemovedCallback dispatchRemovedCallback) {
+ dispatchSourceListeners_.emplace_front(dispatchAddedCallback, dispatchRemovedCallback);
+ return dispatchSourceListeners_.begin();
+ }
+
+ /**
+ * \brief Registers for all Watches that are added or removed.
+ */
+ inline WatchListenerSubscription subscribeForWatches(WatchAddedCallback watchAddedCallback, WatchRemovedCallback watchRemovedCallback) {
+ watchListeners_.emplace_front(watchAddedCallback, watchRemovedCallback);
+ return watchListeners_.begin();
+ }
+
+ /**
+ * \brief Registers for all Timeouts that are added or removed.
+ */
+ inline TimeoutSourceListenerSubscription subscribeForTimeouts(TimeoutSourceAddedCallback timeoutAddedCallback, TimeoutSourceRemovedCallback timeoutRemovedCallback) {
+ timeoutSourceListeners_.emplace_front(timeoutAddedCallback, timeoutRemovedCallback);
+ return timeoutSourceListeners_.begin();
+ }
+
+ /**
+ * \brief Registers for all Wakeup-Events that need to interrupt a call to "poll".
+ */
+ inline WakeupListenerSubscription subscribeForWakeupEvents(WakeupCallback wakeupCallback) {
+ wakeupListeners_.emplace_front(wakeupCallback);
+ return wakeupListeners_.begin();
+ }
+
+ /**
+ * \brief Unsubscribes your listeners for DispatchSources.
+ */
+ inline void unsubscribeForDispatchSources(DispatchSourceListenerSubscription subscription) {
+ dispatchSourceListeners_.erase(subscription);
+ }
+
+ /**
+ * \brief Unsubscribes your listeners for Watches.
+ */
+ inline void unsubscribeForWatches(WatchListenerSubscription subscription) {
+ watchListeners_.erase(subscription);
+ }
+
+ /**
+ * \brief Unsubscribes your listeners for Timeouts.
+ */
+ inline void unsubscribeForTimeouts(TimeoutSourceListenerSubscription subscription) {
+ timeoutSourceListeners_.erase(subscription);
+ }
+
+ /**
+ * \brief Unsubscribes your listeners for Wakeup-Events.
+ */
+ inline void unsubscribeForWakeupEvents(WakeupListenerSubscription subscription) {
+ wakeupListeners_.erase(subscription);
+ }
+
+ /**
+ * \brief Notifies all listeners about a new DispatchSource.
+ */
+ inline void registerDispatchSource(DispatchSource* dispatchSource, const DispatchPriority dispatchPriority = DispatchPriority::DEFAULT) {
+ for(auto listener = dispatchSourceListeners_.begin(); listener != dispatchSourceListeners_.end(); ++listener) {
+ listener->first(dispatchSource, dispatchPriority);
+ }
+ }
+
+ /**
+ * \brief Notifies all listeners about the removal of a DispatchSource.
+ */
+ inline void deregisterDispatchSource(DispatchSource* dispatchSource) {
+ for(auto listener = dispatchSourceListeners_.begin(); listener != dispatchSourceListeners_.end(); ++listener) {
+ listener->second(dispatchSource);
+ }
+ }
+
+ /**
+ * \brief Notifies all listeners about a new Watch.
+ */
+ inline void registerWatch(Watch* watch, const DispatchPriority dispatchPriority = DispatchPriority::DEFAULT) {
+ for(auto listener = watchListeners_.begin(); listener != watchListeners_.end(); ++listener) {
+ listener->first(watch, dispatchPriority);
+ }
+ }
+
+ /**
+ * \brief Notifies all listeners about the removal of a Watch.
+ */
+ inline void deregisterWatch(Watch* watch) {
+ for(auto listener = watchListeners_.begin(); listener != watchListeners_.end(); ++listener) {
+ listener->second(watch);
+ }
+ }
+
+ /**
+ * \brief Notifies all listeners about a new Timeout.
+ */
+ inline void registerTimeoutSource(Timeout* timeoutEvent, const DispatchPriority dispatchPriority = DispatchPriority::DEFAULT) {
+ for(auto listener = timeoutSourceListeners_.begin(); listener != timeoutSourceListeners_.end(); ++listener) {
+ listener->first(timeoutEvent, dispatchPriority);
+ }
+ }
+
+ /**
+ * \brief Notifies all listeners about the removal of a Timeout.
+ */
+ inline void deregisterTimeoutSource(Timeout* timeoutEvent) {
+ for(auto listener = timeoutSourceListeners_.begin(); listener != timeoutSourceListeners_.end(); ++listener) {
+ listener->second(timeoutEvent);
+ }
+ }
+
+ /**
+ * \brief Notifies all listeners about a wakeup event that just happened.
+ */
+ inline void wakeup() {
+ for(auto listener = wakeupListeners_.begin(); listener != wakeupListeners_.end(); ++listener) {
+ (*listener)();
+ }
+ }
+
+ private:
+ DispatchSourceListenerList dispatchSourceListeners_;
+ WatchListenerList watchListeners_;
+ TimeoutSourceListenerList timeoutSourceListeners_;
+ WakeupListenerList wakeupListeners_;
+};
+
+
+} // namespace CommonAPI
+
+
+#endif /* MAIN_LOOP_CONTEXT_H_ */
diff --git a/src/CommonAPI/Runtime.cpp b/src/CommonAPI/Runtime.cpp
index 2ab8bf7..d7185df 100644
--- a/src/CommonAPI/Runtime.cpp
+++ b/src/CommonAPI/Runtime.cpp
@@ -53,4 +53,9 @@ std::shared_ptr<Runtime> Runtime::load(const std::string& middlewareName) {
}
+std::shared_ptr<MainLoopContext> Runtime::getNewMainLoopContext() const {
+ return std::make_shared<MainLoopContext>();
}
+
+
+} // namespace CommonAPI
diff --git a/src/CommonAPI/Runtime.h b/src/CommonAPI/Runtime.h
index 154cb67..e52f740 100644
--- a/src/CommonAPI/Runtime.h
+++ b/src/CommonAPI/Runtime.h
@@ -10,6 +10,7 @@
#include "MiddlewareInfo.h"
#include "Factory.h"
+#include "MainLoopContext.h"
#include <memory>
#include <fstream>
@@ -25,6 +26,7 @@ namespace CommonAPI {
class Factory;
class Runtime;
+class MainLoopContext;
/**
* \brief Represents the CommonAPI runtime bindings available.
@@ -58,6 +60,17 @@ class Runtime {
static void registerRuntimeLoader(std::string middlewareName, MiddlewareRuntimeLoadFunction middlewareRuntimeLoadFunction);
virtual ~Runtime() {}
+
+ /**
+ * \brief Returns new MainLoopContext
+ *
+ * Creates and returns a new MainLoopContext object. This context can be used to take
+ * complete control over the order and time of execution of the abstract middleware
+ * dispatching mechanism.
+ *
+ * @return A new MainLoopContext object
+ */
+ std::shared_ptr<MainLoopContext> getNewMainLoopContext() const;
/**
* \brief Create a factory for the loaded runtime
*
@@ -65,7 +78,7 @@ class Runtime {
*
* @return Factory object for the loaded runtime
*/
- virtual std::shared_ptr<Factory> createFactory() = 0;
+ virtual std::shared_ptr<Factory> createFactory(std::shared_ptr<MainLoopContext> = std::shared_ptr<MainLoopContext>(NULL)) = 0;
};