summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGENIVI Audio Manager Maintainer <genivi-maint-audiomanager@smtp1.genivi.org>2017-08-22 14:50:37 +0200
committerGitHub <noreply@github.com>2017-08-22 14:50:37 +0200
commitf620be8a774f966fbd76ca8892a39ce28037a213 (patch)
tree9baabfbf751e85d0980f74e55e8332f6e20c379f
parent8f2387e42641c7c2b967553a4c578f0e87549fb6 (diff)
parentbe63615585049aa4045f13e91291d64b0a9ed5a3 (diff)
downloadaudiomanager-f620be8a774f966fbd76ca8892a39ce28037a213.tar.gz
Merge pull request #16 from GENIVI/utility_updates
Utility updates
-rw-r--r--AudioManagerCore/include/CAmCommandSender.h2
-rw-r--r--AudioManagerCore/src/CAmCommandReceiver.cpp2
-rw-r--r--AudioManagerCore/src/CAmCommandSender.cpp44
-rw-r--r--AudioManagerCore/src/CAmDatabaseHandlerMap.cpp16
-rw-r--r--AudioManagerCore/test/AmControlInterfaceTest/CMakeLists.txt1
-rw-r--r--AudioManagerCore/test/AmMapHandlerTest/CAmMapHandlerTest.cpp2
-rw-r--r--AudioManagerCore/test/AmMapHandlerTest/CAmMapHandlerTest.h3
-rw-r--r--AudioManagerCore/test/AmMapHandlerTest/CMakeLists.txt1
-rw-r--r--AudioManagerCore/test/AmRouterMapTest/CMakeLists.txt1
-rw-r--r--AudioManagerCore/test/AmRouterTest/CMakeLists.txt1
-rw-r--r--AudioManagerCore/test/AmRoutingInterfaceTest/CMakeLists.txt1
-rwxr-xr-xAudioManagerDaemon/src/main.cpp57
-rw-r--r--AudioManagerUtilities/include/CAmSerializer.h1923
-rw-r--r--AudioManagerUtilities/include/CAmSocketHandler.h632
-rw-r--r--AudioManagerUtilities/src/CAmSocketHandler.cpp925
-rw-r--r--AudioManagerUtilities/test/AmSerializerTest/CAmSerializerTest.cpp207
-rw-r--r--AudioManagerUtilities/test/AmSerializerTest/CAmSerializerTest.h99
-rw-r--r--AudioManagerUtilities/test/AmSerializerTest/CMakeLists.txt48
-rw-r--r--AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp544
-rw-r--r--AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h200
-rw-r--r--AudioManagerUtilities/test/AmSocketHandlerTest/CMakeLists.txt1
-rw-r--r--AudioManagerUtilities/test/CMakeLists.txt4
-rwxr-xr-xCMakeLists.txt7
-rw-r--r--cmake/AudioManagerUtilitiesConfig.cmake.in1
-rw-r--r--cmake/config.cmake.in1
-rw-r--r--docs/main_8cpp_source.html2
26 files changed, 3215 insertions, 1510 deletions
diff --git a/AudioManagerCore/include/CAmCommandSender.h b/AudioManagerCore/include/CAmCommandSender.h
index caa72ad..2f7daec 100644
--- a/AudioManagerCore/include/CAmCommandSender.h
+++ b/AudioManagerCore/include/CAmCommandSender.h
@@ -88,7 +88,7 @@ private:
std::vector<std::string> mListLibraryNames; //!< list of all library names. This information is used for getListPlugins.
CAmCommandReceiver *mCommandReceiver;
- CAmSerializer mSerializer;
+ V2::CAmSerializer mSerializer;
};
diff --git a/AudioManagerCore/src/CAmCommandReceiver.cpp b/AudioManagerCore/src/CAmCommandReceiver.cpp
index 0c6338a..ccf9612 100644
--- a/AudioManagerCore/src/CAmCommandReceiver.cpp
+++ b/AudioManagerCore/src/CAmCommandReceiver.cpp
@@ -120,7 +120,7 @@ am_Error_e CAmCommandReceiver::setMainSourceSoundProperty(const am_MainSoundProp
am_Error_e CAmCommandReceiver::setSystemProperty(const am_SystemProperty_s & property)
{
- logInfo(__METHOD_NAME__,"type=", property.type, "soundPropertyValue=", property.value);
+ logInfo(__METHOD_NAME__,"type=", property.type, "systemPropertyValue=", property.value);
return (mControlSender->hookUserSetSystemProperty(property));
}
diff --git a/AudioManagerCore/src/CAmCommandSender.cpp b/AudioManagerCore/src/CAmCommandSender.cpp
index ea0d749..6626bdb 100644
--- a/AudioManagerCore/src/CAmCommandSender.cpp
+++ b/AudioManagerCore/src/CAmCommandSender.cpp
@@ -163,10 +163,10 @@ CAmCommandSender::CAmCommandSender(const std::vector<std::string>& listOfPluginD
}
dboNewMainConnection = [&](const am_MainConnectionType_s& mainConnection) {
- mSerializer.asyncCall<CAmCommandSender, const am_MainConnectionType_s>(this, &CAmCommandSender::cbNewMainConnection, mainConnection);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbNewMainConnection, mainConnection);
};
dboRemovedMainConnection = [&](const am_mainConnectionID_t mainConnection) {
- mSerializer.asyncCall<CAmCommandSender, const am_mainConnectionID_t>(this, &CAmCommandSender::cbRemovedMainConnection, mainConnection);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbRemovedMainConnection, mainConnection);
};
dboNewSink = [&](const am_Sink_s& sink) {
if (sink.visible)
@@ -178,7 +178,8 @@ CAmCommandSender::CAmCommandSender(const std::vector<std::string>& listOfPluginD
s.sinkClassID = sink.sinkClassID;
s.sinkID = sink.sinkID;
s.volume = sink.mainVolume;
- mSerializer.asyncCall<CAmCommandSender, const am_SinkType_s>(this, &CAmCommandSender::cbNewSink, s);
+ typedef void(CAmCommandSender::*TMeth)(am::am_SinkType_s) ;
+ mSerializer.asyncCall<CAmCommandSender, TMeth, am::am_SinkType_s>(this, &CAmCommandSender::cbNewSink, s);
}
};
dboNewSource = [&](const am_Source_s& source) {
@@ -189,64 +190,65 @@ CAmCommandSender::CAmCommandSender(const std::vector<std::string>& listOfPluginD
s.name = source.name;
s.sourceClassID = source.sourceClassID;
s.sourceID = source.sourceID;
- mSerializer.asyncCall<CAmCommandSender, const am_SourceType_s>(this, &CAmCommandSender::cbNewSource, s);
+ typedef void(CAmCommandSender::*TMeth)(am::am_SourceType_s) ;
+ mSerializer.asyncCall<CAmCommandSender, TMeth, am::am_SourceType_s>(this, &CAmCommandSender::cbNewSource, s);
}
};
dboRemovedSink = [&](const am_sinkID_t sinkID, const bool visible) {
if (visible)
- mSerializer.asyncCall<CAmCommandSender, const am_sinkID_t>(this, &CAmCommandSender::cbRemovedSink, sinkID);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbRemovedSink, sinkID);
};
dboRemovedSource = [&](const am_sourceID_t sourceID, const bool visible) {
if (visible)
- mSerializer.asyncCall<CAmCommandSender, const am_sourceID_t>(this, &CAmCommandSender::cbRemovedSource, sourceID);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbRemovedSource, sourceID);
};
dboNumberOfSinkClassesChanged = [&]() {
- mSerializer.asyncCall<CAmCommandSender>(this, &CAmCommandSender::cbNumberOfSinkClassesChanged);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbNumberOfSinkClassesChanged);
};
dboNumberOfSourceClassesChanged = [&]() {
- mSerializer.asyncCall<CAmCommandSender>(this, &CAmCommandSender::cbNumberOfSourceClassesChanged);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbNumberOfSourceClassesChanged);
};
dboMainConnectionStateChanged = [&](const am_mainConnectionID_t connectionID, const am_ConnectionState_e connectionState) {
- mSerializer.asyncCall<CAmCommandSender, const am_connectionID_t, const am_ConnectionState_e>(this, &CAmCommandSender::cbMainConnectionStateChanged, connectionID, connectionState);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbMainConnectionStateChanged, connectionID, connectionState);
};
dboMainSinkSoundPropertyChanged = [&](const am_sinkID_t sinkID, const am_MainSoundProperty_s& SoundProperty) {
- mSerializer.asyncCall<CAmCommandSender, const am_sinkID_t, const am_MainSoundProperty_s>(this, &CAmCommandSender::cbMainSinkSoundPropertyChanged, sinkID, SoundProperty);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbMainSinkSoundPropertyChanged, sinkID, SoundProperty);
};
dboMainSourceSoundPropertyChanged = [&](const am_sourceID_t sourceID, const am_MainSoundProperty_s& SoundProperty) {
- mSerializer.asyncCall<CAmCommandSender, const am_sourceID_t, const am_MainSoundProperty_s>(this, &CAmCommandSender::cbMainSourceSoundPropertyChanged, sourceID, SoundProperty);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbMainSourceSoundPropertyChanged, sourceID, SoundProperty);
};
dboSinkAvailabilityChanged = [&](const am_sinkID_t sinkID, const am_Availability_s & availability) {
- mSerializer.asyncCall<CAmCommandSender, const am_sinkID_t, const am_Availability_s>(this, &CAmCommandSender::cbSinkAvailabilityChanged, sinkID, availability);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbSinkAvailabilityChanged, sinkID, availability);
};
dboSourceAvailabilityChanged = [&](const am_sourceID_t sourceID, const am_Availability_s & availability) {
- mSerializer.asyncCall<CAmCommandSender, const am_sourceID_t, const am_Availability_s>(this, &CAmCommandSender::cbSourceAvailabilityChanged, sourceID, availability);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbSourceAvailabilityChanged, sourceID, availability);
};
dboVolumeChanged = [&](const am_sinkID_t sinkID, const am_mainVolume_t volume) {
- mSerializer.asyncCall<CAmCommandSender, const am_sinkID_t, const am_mainVolume_t>(this, &CAmCommandSender::cbVolumeChanged, sinkID, volume);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbVolumeChanged, sinkID, volume);
};
dboSinkMuteStateChanged = [&](const am_sinkID_t sinkID, const am_MuteState_e muteState) {
- mSerializer.asyncCall<CAmCommandSender, const am_sinkID_t, const am_MuteState_e>(this, &CAmCommandSender::cbSinkMuteStateChanged, sinkID, muteState);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbSinkMuteStateChanged, sinkID, muteState);
};
dboSystemPropertyChanged = [&](const am_SystemProperty_s& SystemProperty) {
- mSerializer.asyncCall<CAmCommandSender, const am_SystemProperty_s>(this, &CAmCommandSender::cbSystemPropertyChanged, SystemProperty);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbSystemPropertyChanged, SystemProperty);
};
dboTimingInformationChanged = [&](const am_mainConnectionID_t mainConnection, const am_timeSync_t time) {
- mSerializer.asyncCall<CAmCommandSender, const am_mainConnectionID_t, const am_timeSync_t>(this, &CAmCommandSender::cbTimingInformationChanged, mainConnection, time);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbTimingInformationChanged, mainConnection, time);
};
dboSinkUpdated = [&](const am_sinkID_t sinkID, const am_sinkClass_t sinkClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties, const bool visible) {
if (visible)
- mSerializer.asyncCall<CAmCommandSender, const am_sinkID_t, const am_sinkClass_t, const std::vector<am_MainSoundProperty_s> >(this, &CAmCommandSender::cbSinkUpdated, sinkID, sinkClassID, listMainSoundProperties);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbSinkUpdated, sinkID, sinkClassID, listMainSoundProperties);
};
dboSourceUpdated = [&](const am_sourceID_t sourceID, const am_sourceClass_t sourceClassID, const std::vector<am_MainSoundProperty_s>& listMainSoundProperties, const bool visible) {
if (visible)
- mSerializer.asyncCall<CAmCommandSender, const am_sourceID_t, const am_sourceClass_t, const std::vector<am_MainSoundProperty_s> >(this, &CAmCommandSender::cbSinkUpdated, sourceID, sourceClassID, listMainSoundProperties);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbSinkUpdated, sourceID, sourceClassID, listMainSoundProperties);
};
dboSinkMainNotificationConfigurationChanged = [&](const am_sinkID_t sinkID, const am_NotificationConfiguration_s mainNotificationConfiguration) {
- mSerializer.asyncCall<CAmCommandSender, const am_sinkID_t, const am_NotificationConfiguration_s> (this, &CAmCommandSender::cbSinkMainNotificationConfigurationChanged, sinkID, mainNotificationConfiguration);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbSinkMainNotificationConfigurationChanged, sinkID, mainNotificationConfiguration);
};
dboSourceMainNotificationConfigurationChanged = [&](const am_sourceID_t sourceID, const am_NotificationConfiguration_s mainNotificationConfiguration) {
- mSerializer.asyncCall<CAmCommandSender, const am_sourceID_t, const am_NotificationConfiguration_s>(this, &CAmCommandSender::cbSourceMainNotificationConfigurationChanged, sourceID, mainNotificationConfiguration);
+ mSerializer.asyncCall(this, &CAmCommandSender::cbSourceMainNotificationConfigurationChanged, sourceID, mainNotificationConfiguration);
};
}
diff --git a/AudioManagerCore/src/CAmDatabaseHandlerMap.cpp b/AudioManagerCore/src/CAmDatabaseHandlerMap.cpp
index 48ef37b..cc95d28 100644
--- a/AudioManagerCore/src/CAmDatabaseHandlerMap.cpp
+++ b/AudioManagerCore/src/CAmDatabaseHandlerMap.cpp
@@ -3393,22 +3393,20 @@ am_Error_e CAmDatabaseHandlerMap::enumerateConverters(std::function<void(const a
bool CAmDatabaseHandlerMap::registerObserver(IAmDatabaseObserver * iObserver) {
assert(iObserver!=NULL);
- if (std::find(mDatabaseObservers.begin(), mDatabaseObservers.end(),
- iObserver) == mDatabaseObservers.end()) {
- mDatabaseObservers.push_back(
- dynamic_cast<AmDatabaseObserverCallbacks*>(iObserver)), dynamic_cast<AmDatabaseObserverCallbacks*>(iObserver)->mpDatabaseHandler =
- nullptr;
+ if (std::find(mDatabaseObservers.begin(), mDatabaseObservers.end(), iObserver) == mDatabaseObservers.end())
+ {
+ mDatabaseObservers.push_back(static_cast<AmDatabaseObserverCallbacks*>(iObserver));
+ static_cast<AmDatabaseObserverCallbacks*>(iObserver)->mpDatabaseHandler = this;
return true;
}
return false;
}
bool CAmDatabaseHandlerMap::unregisterObserver(IAmDatabaseObserver * iObserver) {
assert(iObserver!=NULL);
- auto it = std::find(mDatabaseObservers.begin(), mDatabaseObservers.end(),
- iObserver);
+ auto it = std::find(mDatabaseObservers.begin(), mDatabaseObservers.end(), iObserver);
if (it != mDatabaseObservers.end()) {
- mDatabaseObservers.erase(it), dynamic_cast<AmDatabaseObserverCallbacks*>(iObserver)->mpDatabaseHandler =
- nullptr;
+ mDatabaseObservers.erase(it);
+ static_cast<AmDatabaseObserverCallbacks*>(iObserver)->mpDatabaseHandler = nullptr;
return true;
}
return false;
diff --git a/AudioManagerCore/test/AmControlInterfaceTest/CMakeLists.txt b/AudioManagerCore/test/AmControlInterfaceTest/CMakeLists.txt
index f2636a8..b1a0dae 100644
--- a/AudioManagerCore/test/AmControlInterfaceTest/CMakeLists.txt
+++ b/AudioManagerCore/test/AmControlInterfaceTest/CMakeLists.txt
@@ -37,6 +37,7 @@ add_executable(AmControlInterfaceTest ${CONTROL_INTERFACE_SRCS_CXX})
TARGET_LINK_LIBRARIES(AmControlInterfaceTest
${GTEST_LIBRARIES}
${GMOCK_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT}
AudioManagerCore
)
diff --git a/AudioManagerCore/test/AmMapHandlerTest/CAmMapHandlerTest.cpp b/AudioManagerCore/test/AmMapHandlerTest/CAmMapHandlerTest.cpp
index fe2f68a..7b11af1 100644
--- a/AudioManagerCore/test/AmMapHandlerTest/CAmMapHandlerTest.cpp
+++ b/AudioManagerCore/test/AmMapHandlerTest/CAmMapHandlerTest.cpp
@@ -47,10 +47,10 @@ TCLAP::SwitchArg enableDebug ("V","logDlt","print DLT logs to stdout or dlt-daem
CAmMapBasicTest::CAmMapBasicTest() :
+ pSocketHandler(),//
pDatabaseHandler(), //
plistRoutingPluginDirs(), //
plistCommandPluginDirs(), //
- pSocketHandler(),//
pRoutingSender(plistRoutingPluginDirs,dynamic_cast<IAmDatabaseHandler*>( &pDatabaseHandler )), //
pCommandSender(plistCommandPluginDirs, &pSocketHandler), //
pRoutingInterfaceBackdoor(), //
diff --git a/AudioManagerCore/test/AmMapHandlerTest/CAmMapHandlerTest.h b/AudioManagerCore/test/AmMapHandlerTest/CAmMapHandlerTest.h
index 32add3d..fc4b023 100644
--- a/AudioManagerCore/test/AmMapHandlerTest/CAmMapHandlerTest.h
+++ b/AudioManagerCore/test/AmMapHandlerTest/CAmMapHandlerTest.h
@@ -54,13 +54,14 @@ public:
CAmMapBasicTest();
~CAmMapBasicTest();
CAmSocketHandler pSocketHandler;
+ CAmDatabaseHandlerMap pDatabaseHandler;
std::vector<std::string> plistRoutingPluginDirs;
std::vector<std::string> plistCommandPluginDirs;
CAmRoutingSender pRoutingSender;
CAmCommandSender pCommandSender;
IAmRoutingBackdoor pRoutingInterfaceBackdoor;
IAmCommandBackdoor pCommandInterfaceBackdoor;
- CAmDatabaseHandlerMap pDatabaseHandler;
+
CAmControlSender pControlSender;
CAmRouter pRouter;
CAmControlReceiver pControlReceiver;
diff --git a/AudioManagerCore/test/AmMapHandlerTest/CMakeLists.txt b/AudioManagerCore/test/AmMapHandlerTest/CMakeLists.txt
index 41c62c7..5a74cba 100644
--- a/AudioManagerCore/test/AmMapHandlerTest/CMakeLists.txt
+++ b/AudioManagerCore/test/AmMapHandlerTest/CMakeLists.txt
@@ -36,6 +36,7 @@ ADD_EXECUTABLE( AmMapHandlerTest ${DATABASE_SRCS_CXX})
TARGET_LINK_LIBRARIES( AmMapHandlerTest
${GTEST_LIBRARIES}
${GMOCK_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT}
AudioManagerCore
)
diff --git a/AudioManagerCore/test/AmRouterMapTest/CMakeLists.txt b/AudioManagerCore/test/AmRouterMapTest/CMakeLists.txt
index dc2732c..c4a5968 100644
--- a/AudioManagerCore/test/AmRouterMapTest/CMakeLists.txt
+++ b/AudioManagerCore/test/AmRouterMapTest/CMakeLists.txt
@@ -34,6 +34,7 @@ ADD_EXECUTABLE( AmRouterMapTest ${ROUTINGMAP_SRCS_CXX})
TARGET_LINK_LIBRARIES(AmRouterMapTest
${GTEST_LIBRARIES}
${GMOCK_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT}
AudioManagerCore
)
diff --git a/AudioManagerCore/test/AmRouterTest/CMakeLists.txt b/AudioManagerCore/test/AmRouterTest/CMakeLists.txt
index 89094c8..d866032 100644
--- a/AudioManagerCore/test/AmRouterTest/CMakeLists.txt
+++ b/AudioManagerCore/test/AmRouterTest/CMakeLists.txt
@@ -35,6 +35,7 @@ ADD_EXECUTABLE( AmRouterTest ${ROUTING_SRCS_CXX})
TARGET_LINK_LIBRARIES(AmRouterTest
${GTEST_LIBRARIES}
${GMOCK_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT}
AudioManagerCore
)
diff --git a/AudioManagerCore/test/AmRoutingInterfaceTest/CMakeLists.txt b/AudioManagerCore/test/AmRoutingInterfaceTest/CMakeLists.txt
index 6d47c15..369c536 100644
--- a/AudioManagerCore/test/AmRoutingInterfaceTest/CMakeLists.txt
+++ b/AudioManagerCore/test/AmRoutingInterfaceTest/CMakeLists.txt
@@ -38,6 +38,7 @@ ADD_TEST(AmRoutingInterfaceTest AmRoutingInterfaceTest)
TARGET_LINK_LIBRARIES(AmRoutingInterfaceTest
${GTEST_LIBRARIES}
${GMOCK_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT}
AudioManagerCore
)
diff --git a/AudioManagerDaemon/src/main.cpp b/AudioManagerDaemon/src/main.cpp
index 26d7cea..5c0582e 100755
--- a/AudioManagerDaemon/src/main.cpp
+++ b/AudioManagerDaemon/src/main.cpp
@@ -195,7 +195,7 @@ static void signalHandler(int sig, siginfo_t *siginfo, void *context)
switch (sig)
{
/*ctl +c lets call direct controllerRundown, because we might be blocked at the moment.
- But there is the risk of interrupting something important */https://asc.bmwgroup.net/wiki/display/MGUROTO/Lastest+and+greatest
+ But there is the risk of interrupting something important */
case SIGINT:
CAmControlSender::CallsetControllerRundown(sig);
break;
@@ -204,21 +204,12 @@ static void signalHandler(int sig, siginfo_t *siginfo, void *context)
case SIGQUIT:
CAmControlSender::CallsetControllerRundown(sig);
break;
-
- /* more friendly here assuming systemd wants to stop us, so we can use the mainloop */
- case SIGTERM:
- CAmControlSender::CallsetControllerRundownSafe(sig);
- break;
-
- /* looks friendly, too, so lets take the long run */
- case SIGHUP:
- CAmControlSender::CallsetControllerRundownSafe(sig);
- break;
default:
break;
}
}
+
void mainProgram(int argc, char *argv[])
{
@@ -255,6 +246,39 @@ void mainProgram(int argc, char *argv[])
//Instantiate all classes. Keep in same order !
CAmSocketHandler iSocketHandler;
+ if(iSocketHandler.fatalErrorOccurred())
+ {
+ throw std::runtime_error(std::string("CAmSocketHandler: Could not create pipe or file descriptor is invalid."));
+ }
+
+ if( E_OK!=iSocketHandler.listenToSignals({SIGHUP, SIGTERM, SIGCHLD}) )
+ {
+ logWarning("CAmSocketHandler failed to register itself as signal handler.");
+ }
+ //Register signal handler
+ sh_pollHandle_t signalHandler;
+ iSocketHandler.addSignalHandler([&](const sh_pollHandle_t handle, const signalfd_siginfo & info, void* userData){
+
+ unsigned sig = info.ssi_signo;
+ unsigned user = info.ssi_uid;
+
+ logInfo("signal handler was called from user", user, "with signal ",sig);
+
+ switch (sig)
+ {
+ /* more friendly here assuming systemd wants to stop us, so we can use the mainloop */
+ case SIGTERM:
+ CAmControlSender::CallsetControllerRundownSafe(sig);
+ break;
+
+ /* looks friendly, too, so lets take the long run */
+ case SIGHUP:
+ CAmControlSender::CallsetControllerRundownSafe(sig);
+ break;
+ default:
+ break;
+ }
+ },signalHandler,NULL);
if(commandPluginDir.isSet())
{
@@ -364,21 +388,14 @@ int main(int argc, char *argv[], char** envp)
listCommandPluginDirs.push_back(std::string(DEFAULT_PLUGIN_COMMAND_DIR));
listRoutingPluginDirs.push_back(std::string(DEFAULT_PLUGIN_ROUTING_DIR));
- //now the signal handler:
+ //critical signals are registered here:
struct sigaction signalAction;
memset(&signalAction, '\0', sizeof(signalAction));
signalAction.sa_sigaction = &signalHandler;
signalAction.sa_flags = SA_SIGINFO;
sigaction(SIGINT, &signalAction, NULL);
sigaction(SIGQUIT, &signalAction, NULL);
- sigaction(SIGTERM, &signalAction, NULL);
- sigaction(SIGHUP, &signalAction, NULL);
-
- struct sigaction signalChildAction;
- memset(&signalChildAction, '\0', sizeof(signalChildAction));
- signalChildAction.sa_flags = SA_NOCLDWAIT;
- sigaction(SIGCHLD, &signalChildAction, NULL);
-
+
//register new out of memory handler
std::set_new_handler(&OutOfMemoryHandler);
diff --git a/AudioManagerUtilities/include/CAmSerializer.h b/AudioManagerUtilities/include/CAmSerializer.h
index b0cd70e..6bd6143 100644
--- a/AudioManagerUtilities/include/CAmSerializer.h
+++ b/AudioManagerUtilities/include/CAmSerializer.h
@@ -1,10 +1,10 @@
/**
* SPDX license identifier: MPL-2.0
*
- * Copyright (C) 2012, BMW AG
+ * Copyright (C) 2012-2017, BMW AG
*
* \author Christian Linke, christian.linke@bmw.de BMW 2011,2012
- * \author Alesksandar Donchev, aleksander.donchev@partner.bmw.de BMW 2015
+ * \author Alesksandar Donchev, aleksander.donchev@partner.bmw.de BMW 2015, 2017
*
* \copyright
* This Source Code Form is subject to the terms of the
@@ -27,779 +27,1192 @@
#include "CAmDltWrapper.h"
#include "CAmSocketHandler.h"
-/**
- * todo: performance improvement we could implement a memory pool that is more efficient here and avoids
- * allocation and deallocation times.
+/*!
+ * \brief Helper structures used within std::bind for automatically identification of all placeholders.
*/
-
-namespace am
+template<std::size_t ... Is>
+struct indices
{
-/**
- * magic class that does the serialization of functions calls
- * The constructor must be called within the main threadcontext, after that using the
- * overloaded template function call will serialize all calls and call them within the
- * main thread context.\n
- * More details can be found here: \ref util
- * \warning asynchronous calls may be used in the mainthread context, but if you want to use synchronous calls make sure that you use one
- * instance of this class per thread otherwise you could be lost in never returning calls.\n
- * Examples of the usage can be found in IAmCommandReceiverShadow of the ControlPlugin or IAmRoutingReceiverShadow of the
- * PluginRoutingInterfaceAsync.
- *
- */
-class CAmSerializer
-{
-private:
-
- /**
- * Prototype for a delegate
- */
- class CAmDelegate
- {
- public:
-
- typedef enum:bool {
- SyncCallType = false,
- AsyncCallType = true
- } CallType;
-
- virtual ~CAmDelegate()
- {};
- virtual CallType call(int* pipe)=0;
-
- };
-
- /**
- * Prototype for a delegate with variadic template arguments in conjunction with the following class.
- */
- template <class Class, typename Method, typename Tuple, bool Done, int Total, int... N>
- class CAmDelegateAsyncImpl : public CAmDelegate
- {
- Class mInstance;
- Method mMethod;
- Tuple mArguments;
- public:
- friend class CAmSerializer;
- static void call(Class instance, Method method, Tuple && arguments)
- {
- CAmDelegateAsyncImpl<Class, Method, Tuple, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(instance, method, std::forward<Tuple>(arguments));
- }
-
- CAmDelegateAsyncImpl(Class instance, Method method, Tuple && arguments)
- {
- mInstance = instance;
- mMethod = method;
- mArguments = std::move(arguments);
- }
-
- CallType call(int* pipe)
- {
- (void) pipe;
- call(mInstance, mMethod, std::forward<Tuple>(mArguments));
- return (AsyncCallType);
- };
- };
-
- /**
- * Prototype for a delegate with variadic template arguments.
- */
- template <class Class, typename Method, typename Tuple, int Total, int... N>
- class CAmDelegateAsyncImpl<Class, Method, Tuple, true, Total, N...> : public CAmDelegate
- {
- Class mInstance;
- Method mMethod;
- Tuple mArguments;
- public:
- friend class CAmSerializer;
- static void call(Class instance, Method method, Tuple && t)
- {
- (*instance.*method)(std::get<N>(std::forward<Tuple>(t))...);
- }
-
- CAmDelegateAsyncImpl(Class instance, Method method, Tuple && arguments)
- {
- mInstance = instance;
- mMethod = method;
- mArguments = std::move(arguments);
- }
-
- CallType call(int* pipe)
- {
- (void) pipe;
- call(mInstance, mMethod, std::forward<Tuple>(mArguments));
- return (AsyncCallType);
- };
- };
-
- /**
- * Prototype for a delegate with variadic template arguments in conjunction with the following class.
- */
- template <class Class, typename Method, typename Return, typename Tuple, bool Done, int Total, int... N>
- class CAmDelegateSyncImpl : public CAmDelegate
- {
- Class mInstance;
- Method mMethod;
- Tuple mArguments;
- Return mReturn;
- public:
- friend class CAmSerializer;
- static void call(Class instance,Method method, Return & result, Tuple && arguments)
- {
- CAmDelegateSyncImpl<Class, Method, Return, Tuple, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(instance, method, result, std::forward<Tuple>(arguments));
- }
-
- CAmDelegateSyncImpl(Class instance, Method method, Tuple && arguments)
- {
- mInstance = instance;
- mMethod = method;
- mArguments = std::move(arguments);
- }
-
- CallType call(int* pipe)
- {
- call(mInstance, mMethod, mReturn, std::forward<Tuple>(mArguments));
- ssize_t result(-1);
- result = write(pipe[1], this, sizeof(this));
- if (result == -1)
- logError("CAmSerializer: Problem writing into pipe! Error No:",errno);
- return (SyncCallType);
- };
- };
-
- /**
- * Prototype for a delegate with variadic template arguments.
- */
- template <class Class, typename Method, typename Return, typename Tuple, int Total, int... N>
- class CAmDelegateSyncImpl<Class, Method, Return, Tuple, true, Total, N...> : public CAmDelegate
- {
- Class mInstance;
- Method mMethod;
- Tuple mArguments;
- Return mReturn;
- public:
- friend class CAmSerializer;
- static void call(Class instance, Method method, Return & result, Tuple && t)
- {
- result = (*instance.*method)(std::get<N>(t)...);
- }
-
- CAmDelegateSyncImpl(Class instance, Method method, Tuple && arguments)
- {
- mInstance = instance;
- mMethod = method;
- mArguments = std::move(arguments);
- }
-
- CallType call(int* pipe)
- {
- call(mInstance, mMethod, mReturn, std::forward<Tuple>(mArguments));
- ssize_t result(-1);
- result = write(pipe[1], this, sizeof(this));
- if (result == -1)
- logError("CAmSerializer: Problem writing into pipe! Error No:",errno);
- return (SyncCallType);
- };
- };
-
- typedef CAmDelegate* CAmDelegagePtr; //!< pointer to a delegate
-
-public:
- /**
- * instantiates a async delegate with given arguments and sends the delegate pointer over the pipe
- */
- template <typename Class, typename Method, typename Tuple>
- void doAsyncCall(Class intsance, Method method, Tuple & arguments)
- {
- typedef typename std::decay<Tuple>::type ttype;
- typedef CAmDelegateAsyncImpl<Class, Method, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value> AsyncDelegate;
- AsyncDelegate *pImp = new AsyncDelegate(intsance, method, std::forward<Tuple>(arguments));
- send(pImp);
- //Do not delete the pointer. It will be deleted automatically later.
- }
-
- /**
- * instantiates a sync delegate with given arguments and sends the delegate pointer over the pipe
- */
- template <typename Class, typename Method, typename Return, typename Tuple>
- void doSyncCall(Class intsance, Method method, Return & result, Tuple & arguments)
- {
- typedef typename std::decay<Tuple>::type ttype;
- typedef CAmDelegateSyncImpl<Class, Method, Return, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value> SyncDelegate;
- SyncDelegate *pImp = new SyncDelegate(intsance, method, std::forward<Tuple>(arguments));
- send(pImp);
- int numReads;
- SyncDelegate *p = NULL;
- if ((numReads = read(mReturnPipe[0], &p, sizeof(p))) == -1)
- {
- logError("CAmSerializer::doSyncCall could not read pipe!");
- throw std::runtime_error("CAmSerializer Could not read pipe!");
- }
- result = std::move(pImp->mReturn);
- arguments = std::move(pImp->mArguments);
- //Delete the pointer.
- delete pImp;
- }
-private:
-
- /**
- * rings the line of the pipe and adds the delegate pointer to the queue
- * @param p delegate pointer
- */
- inline void send(CAmDelegagePtr p)
- {
- if (write(mPipe[1], &p, sizeof(p)) == -1)
- {
- throw std::runtime_error("could not write to pipe !");
- }
- }
-
- int mPipe[2]; //!< the pipe
- int mReturnPipe[2]; //!< pipe handling returns
- sh_pollHandle_t mHandle;
- CAmSocketHandler* mpSocketHandler;
- std::deque<CAmDelegagePtr> mListDelegatePoiters; //!< intermediate queue to store the pipe results
-
-public:
-
- /**
- * get the size of delegate pointers
- */
- int getListDelegatePoiters()
- {
- return mListDelegatePoiters.size();
- }
-
- /**
- * calls a function with variadic arguments threadsafe
- * @param instance the instance of the class that shall be called
- * @param function the function that shall be called as member function pointer.
- * @param output variable.
- * @tparam TClass the type of the Class to be called
- * @tparam TRet the type of the result
- * @tparam TArgs argument list
- * \section ex Example:
- * @code
- * class MyGreatClass
- * {
- * public:
- * int AGreatMethod(int x);
- * }
- * CAmSerializer serial(&Sockethandler);
- * MyGreatClass anInstance;
- * int result;
- * serial.syncCall<MyGreatClass, int, int>(&anInstance,&MyGreatClass::AGreatMethod, result, 100);
- * @endcode
- */
- template<class TClass, class TRet, class ... TArgs>
- void syncCall(TClass* instance, TRet (TClass::*method)(TArgs ...), TRet & result, TArgs & ... arguments)
- {
- auto t = std::make_tuple(arguments...);
- doSyncCall(instance, method, result, t);
- std::tie(arguments...) = t;
- }
-
- /**
- * calls a function with variadic arguments threadsafe
- * @param instance the instance of the class that shall be called
- * @param function the function that shall be called as member function pointer.
- * @tparam TClass the type of the Class to be called
- * @tparam TRet the type of the result
- * @tparam TArgs argument list
- * \section ex Example:
- * @code
- * class MyGreatClass
- * {
- * public:
- * int AGreatMethod(int x);
- * }
- * CAmSerializer serial(&Sockethandler);
- * MyGreatClass anInstance;
- * serial.asyncCall<MyGreatClass, void, int>(&anInstance,&MyGreatClass::AGreatMethod, 100);
- * @endcode
- */
- template<class TClass, class TRet, class ... TArgs>
- void asyncCall(TClass* instance, TRet (TClass::*method)(TArgs ...), TArgs & ... arguments)
- {
- auto t = std::make_tuple(arguments...);
- doAsyncCall(instance, method, t);
- }
-
- /**
- * calls a function with no arguments threadsafe
- * @param instance the instance of the class that shall be called
- * @param function the function that shall be called as memberfunction pointer.
- * @tparam TClass1 the type of the Class to be called
- * \section ex Example:
- * @code
- * class myClass
- * {
- * public:
- * void myfunction();
- * }
- * CAmSerializer serial(&Sockethandler);
- * myClass instanceMyClass;
- * serial<CommandSender>(&instanceMyClass,&myClass::myfunction);
- * @endcode
- */
- template<class TClass>
- void asyncCall(TClass* instance, void (TClass::*function)())
- {
- auto t = std::make_tuple();
- doAsyncCall(instance, function, t);
- }
-
- /**
- * calls a function with one arguments asynchronously threadsafe
- * @param instance the instance of the class that shall be called
- * @param function the function that shall be called as memberfunction pointer.
- * @param argument the argument
- * @tparam TClass1 the type of the Class to be called
- * @tparam Targ the type of the argument to be called
- * \section ex Example:
- * @code
- * class myClass
- * {
- * public:
- * void myfunction(int k);
- * }
- * CAmSerializer serial(&Sockethandler);
- * myClass instanceMyClass;
- * serial<CommandSender,int>(&instanceMyClass,&myClass::myfunction,k);
- * @endcode
- *
- */
- template<class TClass1, class Targ>
- void asyncCall(TClass1* instance, void (TClass1::*function)(Targ), Targ argument)
- {
- auto t = std::make_tuple(argument);
- doAsyncCall(instance, function, t);
- }
-
- /**
- * calls a function with one argument called by reference asynchronously threadsafe
- * @param instance the instance of the class that shall be called
- * @param function the function that shall be called as memberfunction pointer.
- * @param argument the argument
- * @tparam TClass1 the type of the Class to be called
- * @tparam Targ the type of the argument to be called
- * \section ex Example:
- * @code
- * class myClass
- * {
- * public:
- * void myfunction(int k);
- * }
- * CAmSerializer serial(&Sockethandler);
- * myClass instanceMyClass;
- * serial<CommandSender,int>(&instanceMyClass,&myClass::myfunction,k);
- * @endcode
- *
- */
- template<class TClass1, class Targ>
- void asyncCall(TClass1* instance, void (TClass1::*function)(Targ&), Targ& argument)
- {
- auto t = std::make_tuple(argument);
- doAsyncCall(instance, function, t);
- }
-
- /**
- * calls a function with two arguments asynchronously threadsafe. for more see asyncCall with one argument
- * @param instance pointer to the instance of the class
- * @param function memberfunction poitner
- * @param argument the first argument
- * @param argument1 the second argument
- * @tparam TClass1 the type of the Class to be called
- * @tparam Targ the type of the argument to be called
- * @tparam Targ1 the type of the first argument to be called
- */
- template<class TClass1, class Targ, class Targ1>
- void asyncCall(TClass1* instance, void (TClass1::*function)(Targ argument, Targ1 argument1), Targ argument, Targ1 argument1)
- {
- auto t = std::make_tuple(argument,argument1);
- doAsyncCall(instance, function, t);
- }
-
- /**
- * calls a function with two arguments asynchronously threadsafe, first argument is a reference. for more see asyncCall with one argument
- * @param instance pointer to the instance of the class
- * @param function memberfunction poitner
- * @param argument the first argument
- * @param argument1 the second argument
- * @tparam TClass1 the type of the Class to be called
- * @tparam Targ the type of the argument to be called
- * @tparam Targ1 the type of the first argument to be called
- */
- template<class TClass1, class Targ, class Targ1>
- void asyncCall(TClass1* instance, void (TClass1::*function)(Targ& argument, Targ1 argument1), Targ& argument, Targ1 argument1)
- {
- auto t = std::make_tuple(argument,argument1);
- doAsyncCall(instance, function, t);
- }
-
- /**
- * calls a function with two arguments asynchronously threadsafe, second argument is a reference. for more see asyncCall with one argument
- * @param instance pointer to the instance of the class
- * @param function memberfunction poitner
- * @param argument the first argument
- * @param argument1 the second argument
- * @tparam TClass1 the type of the Class to be called
- * @tparam Targ the type of the argument to be called
- * @tparam Targ1 the type of the first argument to be called
- */
- template<class TClass1, class Targ, class Targ1>
- void asyncCall(TClass1* instance, void (TClass1::*function)(Targ argument, Targ1& argument1), Targ argument, Targ1& argument1)
- {
- auto t = std::make_tuple(argument,argument1);
- doAsyncCall(instance, function, t);
- }
-
- /**
- * calls a function with two arguments asynchronously threadsafe, both arguments are references. for more see asyncCall with one argument
- * @param instance pointer to the instance of the class
- * @param function memberfunction poitner
- * @param argument the first argument
- * @param argument1 the second argument
- * @tparam TClass1 the type of the Class to be called
- * @tparam Targ the type of the argument to be called
- * @tparam Targ1 the type of the first argument to be called
- */
- template<class TClass1, class Targ, class Targ1>
- void asyncCall(TClass1* instance, void (TClass1::*function)(Targ& argument, Targ1& argument1), Targ& argument, Targ1& argument1)
- {
- auto t = std::make_tuple(argument,argument1);
- doAsyncCall(instance, function, t);
- }
-
- /**
- * calls a function with three arguments asynchronously threadsafe. for more see other asycCall
- */
- template<class TClass1, class Targ, class Targ1, class Targ2>
- void asyncCall(TClass1* instance, void (TClass1::*function)(Targ argument, Targ1 argument1, Targ2 argument2), Targ argument, Targ1 argument1, Targ2 argument2)
- {
- auto t = std::make_tuple(argument,argument1, argument2);
- doAsyncCall(instance, function, t);
- }
-
- /**
- * calls a function with three arguments asynchronously threadsafe. for more see other asycCall
- */
- template<class TClass1, class Targ, class Targ1, class Targ2>
- void asyncCall(TClass1* instance, void (TClass1::*function)(Targ& argument, Targ1 argument1, Targ2 argument2), Targ& argument, Targ1 argument1, Targ2 argument2)
- {
- auto t = std::make_tuple(argument,argument1, argument2);
- doAsyncCall(instance, function, t);
- }
-
-
- /**
- * calls a function with three arguments asynchronously threadsafe. for more see other asycCall
- */
- template<class TClass1, class Targ, class Targ1, class Targ2>
- void asyncCall(TClass1* instance, void (TClass1::*function)(Targ argument, Targ1& argument1, Targ2 argument2), Targ argument, Targ1& argument1, Targ2 argument2)
- {
- auto t = std::make_tuple(argument,argument1, argument2);
- doAsyncCall(instance, function, t);
- }
-
- /**
- * calls a function with three arguments asynchronously threadsafe. for more see other asycCall
- */
- template<class TClass1, class Targ, class Targ1, class Targ2>
- void asyncCall(TClass1* instance, void (TClass1::*function)(Targ argument, Targ1 argument1, Targ2& argument2), Targ argument, Targ1 argument1, Targ2& argument2)
- {
- auto t = std::make_tuple(argument,argument1, argument2);
- doAsyncCall(instance, function, t);
- }
+};
- /**
- * calls a function with three arguments asynchronously threadsafe. for more see other asycCall
- */
- template<class TClass1, class Targ, class Targ1, class Targ2>
- void asyncCall(TClass1* instance, void (TClass1::*function)(Targ argument, Targ1& argument1, Targ2& argument2), Targ argument, Targ1& argument1, Targ2& argument2)
- {
- auto t = std::make_tuple(argument,argument1, argument2);
- doAsyncCall(instance, function, t);
- }
+template<std::size_t N, std::size_t ... Is>
+struct build_indices: build_indices<N - 1, N - 1, Is...>
+{
+};
- /**
- * calls a function with three arguments asynchronously threadsafe. for more see other asycCall
- */
- template<class TClass1, class Targ, class Targ1, class Targ2>
- void asyncCall(TClass1* instance, void (TClass1::*function)(Targ& argument, Targ1& argument1, Targ2& argument2), Targ& argument, Targ1& argument1, Targ2& argument2)
- {
- auto t = std::make_tuple(argument,argument1, argument2);
- doAsyncCall(instance, function, t);
- }
+template<std::size_t ... Is>
+struct build_indices<0, Is...> : indices<Is...>
+{
+};
- /**
- * calls a function with three arguments asynchronously threadsafe. for more see other asycCall
- */
- template<class TClass1, class Targ, class Targ1, class Targ2>
- void asyncCall(TClass1* instance, void (TClass1::*function)(Targ& argument, Targ1& argument1, Targ2 argument2), Targ& argument, Targ1& argument1, Targ2 argument2)
- {
- auto t = std::make_tuple(argument,argument1, argument2);
- doAsyncCall(instance, function, t);
- }
+template<int I> struct placeholder
+{
+};
- /**
- * calls a function with three arguments asynchronously threadsafe. for more see other asycCall
- */
- template<class TClass1, class Targ, class Targ1, class Targ2>
- void asyncCall(TClass1* instance, void (TClass1::*function)(Targ& argument, Targ1 argument1, Targ2& argument2), Targ& argument, Targ1 argument1, Targ2& argument2)
+namespace std
+{
+ template<int I>
+ struct is_placeholder<::placeholder<I>> : std::integral_constant<int, I>
{
- auto t = std::make_tuple(argument,argument1, argument2);
- doAsyncCall(instance, function, t);
- }
+ };
+}
- /**
- * calls a function with four arguments asynchronously threadsafe. for more see other asycCall
- */
- template<class TClass1, class Targ, class Targ1, class Targ2, class Targ3>
- void asyncCall(TClass1* instance, void (TClass1::*function)(Targ argument, Targ1 argument1, Targ2 argument2, Targ3 argument3), Targ argument, Targ1 argument1, Targ2 argument2, Targ3 argument3)
- {
- auto t = std::make_tuple(argument,argument1, argument2,argument3);
- doAsyncCall(instance, function, t);
- }
+#if defined(__GNUC__)
+# define DEPRECATED(MSG) __attribute__ ((__deprecated__((#MSG))))
+#else
+# define DEPRECATED(MSG)
+#endif
+namespace am
+{
/**
- * calls a synchronous function with no arguments threadsafe
- * @param instance the instance of the class that shall be called
- * @param function the function that shall be called as memberfunction pointer.
- * @param retVal the return parameter, no const allowed !
- * @tparam TClass1 the type of the class to be called
- * @tparam TretVal the type of the return parameter
- * \section ex Example:
- * @code
- * class myClass
- * {
- * public:
- * am_Error_e myfunction();
- * }
- * CAmSerializer serial(&Sockethandler);
- * myClass instanceMyClass;
- * am_Error_e error;
- * serial<CommandSender,am_Error_e>(&instanceMyClass,&myClass::myfunction, error);
- * @endcode
- * All arguments given to synchronous functions must be non-const since the results of the operations will be written back to the arguments.
+ * magic class that does the serialization of functions calls
+ * The constructor must be called within the main threadcontext, after that using the
+ * overloaded template function call will serialize all calls and call them within the
+ * main thread context.\n
+ * More details can be found here: \ref util
+ * \warning asynchronous calls may be used in the mainthread context, but if you want to use synchronous calls make sure that you use one
+ * instance of this class per thread otherwise you could be lost in never returning calls.\n
+ * Examples of the usage can be found in IAmCommandReceiverShadow of the ControlPlugin or IAmRoutingReceiverShadow of the
+ * PluginRoutingInterfaceAsync.
*
*/
- template<class TClass1, class TretVal>
- void syncCall(TClass1* instance, TretVal (TClass1::*function)(), TretVal& retVal)
- {
- auto t = std::make_tuple();
- doSyncCall(instance, function, retVal, t);
- }
-
- /**
- * calls a function with one argument synchronous threadsafe
- * @param instance the instance of the class that shall be called
- * @param function the function that shall be called as memberfunction pointer.
- * @param retVal the return parameter, no const allowed !
- * @param argument the argument, no const allowed !
- * @tparam TClass1 the type of the class to be called
- * @tparam TretVal the type of the return parameter
- * @tparam TargCall the type of the argument like in the function to be called. here all references and const must be
- * respected!
- * @tparam Targ the type of the argument, here no const and no references allowed !
- * \section ex Example:
- * @code
- * class myClass
- * {
- * public:
- * am_Error_e myfunction(int k);
- * }
- * CAmSerializer serial(&Sockethandler);
- * myClass instanceMyClass;
- * am_Error_e error;
- * int l;
- * serial<CommandSender,am_Error_e,int>(&instanceMyClass,&myClass::myfunction,error,l);
- * @endcode
- * All arguments given to synchronous functions must be non-const since the results of the operations will be written back to the arguments.
- */
- template<class TClass1, class TretVal, class TargCall, class Targ>
- void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall), TretVal& retVal, Targ& argument)
- {
- auto t = std::make_tuple(argument);
- doSyncCall(instance, function, retVal, t);
- std::tie(argument) = t;
- }
-
- /**
- * calls a function with one argument synchronous threadsafe for const functions. For more see syncCall with one argument
- */
- template<class TClass1, class TretVal, class TargCall, class Targ>
- void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall) const, TretVal& retVal, Targ& argument)
- {
- auto t = std::make_tuple(argument);
- doSyncCall(instance, function, retVal, t);
- std::tie(argument) = t;
- }
-
- /**
- * calls a function with two arguments synchronously threadsafe. For more see syncCall with one argument
- */
- template<class TClass1, class TretVal, class TargCall, class Targ1Call, class Targ, class Targ1>
- void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall, Targ1Call), TretVal& retVal, Targ& argument, Targ1& argument1)
- {
- auto t = std::make_tuple(argument, argument1);
- doSyncCall(instance, function, retVal, t);
- std::tie(argument, argument1) = t;
- }
- /**
- * calls a function with two arguments synchronously threadsafe const. For more see syncCall with one argument
- */
- template<class TClass1, class TretVal, class TargCall, class Targ1Call, class Targ, class Targ1>
- void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall, Targ1Call) const, TretVal& retVal, Targ& argument, Targ1& argument1)
- {
- auto t = std::make_tuple(argument, argument1);
- doSyncCall(instance, function, retVal, t);
- std::tie(argument, argument1) = t;
- }
-
- /**
- * calls a function with three arguments synchronously threadsafe. for more see syncCall with one argument
- */
- template<class TClass1, class TretVal, class TargCall, class TargCall1, class TargCall2, class Targ, class Targ1, class Targ2>
- void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall, TargCall1, TargCall2), TretVal& retVal, Targ& argument, Targ1& argument1, Targ2& argument2)
- {
- auto t = std::make_tuple(argument, argument1, argument2);
- doSyncCall(instance, function, retVal, t);
- std::tie(argument, argument1,argument2) = t;
- }
-
- /**
- * calls a const function with three arguments synchronously threadsafe. for more see syncCall with one argument
- */
- template<class TClass1, class TretVal, class TargCall, class TargCall1, class TargCall2, class Targ, class Targ1, class Targ2>
- void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall, TargCall1, TargCall2) const, TretVal& retVal, Targ& argument, Targ1& argument1, Targ2& argument2)
- {
- auto t = std::make_tuple(argument, argument1, argument2);
- doSyncCall(instance, function, retVal, t);
- std::tie(argument, argument1,argument2) = t;
- }
-
- /**
- * calls a function with four arguments synchronously threadsafe. for more see syncCall with one argument
- */
- template<class TClass1, class TretVal, class TargCall, class TargCall1, class TargCall2, class TargCall3, class Targ, class Targ1, class Targ2, class Targ3>
- void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall, TargCall1, TargCall2, TargCall3), TretVal& retVal, Targ& argument, Targ1& argument1, Targ2& argument2, Targ3& argument3)
- {
- auto t = std::make_tuple(argument, argument1, argument2, argument3);
- doSyncCall(instance, function, retVal, t);
- std::tie(argument, argument1,argument2, argument3) = t;
- }
/**
- * calls a function with five arguments synchronously threadsafe. for more see syncCall with one argument
+ * \defgroup Deprecated Obsolete class!
+ * @{
*/
- template<class TClass1, class TretVal, class TargCall, class TargCall1, class TargCall2, class TargCall3, class TargCall4, class Targ, class Targ1, class Targ2, class Targ3, class Targ4>
- void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall, TargCall1, TargCall2, TargCall3, TargCall4), TretVal& retVal, Targ& argument, Targ1& argument1, Targ2& argument2, Targ3& argument3, Targ4& argument4)
- {
- auto t = std::make_tuple(argument, argument1, argument2, argument3, argument4);
- doSyncCall(instance, function, retVal, t);
- std::tie(argument, argument1,argument2, argument3, argument4) = t;
- }
- /**
- * calls a function with six arguments synchronously threadsafe. for more see syncCall with one argument
- */
- template<class TClass1, class TretVal, class TargCall, class TargCall1, class TargCall2, class TargCall3, class TargCall4, class TargCall5, class Targ, class Targ1, class Targ2, class Targ3, class Targ4, class Targ5>
- void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall, TargCall1, TargCall2, TargCall3, TargCall4, TargCall5), TretVal& retVal, Targ& argument, Targ1& argument1, Targ2& argument2, Targ3& argument3, Targ4& argument4, Targ5& argument5)
- {
- auto t = std::make_tuple(argument, argument1, argument2, argument3, argument4, argument5);
- doSyncCall(instance, function, retVal, t);
- std::tie(argument, argument1,argument2, argument3, argument4, argument5) = t;
- }
-
- /**
- * receiver callback for sockethandling, for more, see CAmSocketHandler
- */
- void receiverCallback(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
+ namespace V1
{
- (void) handle;
- (void) userData;
- int numReads;
- CAmDelegagePtr listPointers[3];
- if ((numReads = read(pollfd.fd, &listPointers, sizeof(listPointers))) == -1)
+ class CAmSerializer
{
- logError("CAmSerializer::receiverCallback could not read pipe!");
- throw std::runtime_error("CAmSerializer Could not read pipe!");
- }
- mListDelegatePoiters.assign(listPointers, listPointers + (numReads / sizeof(CAmDelegagePtr)));
- }
-
- /**
- * checker callback for sockethandling, for more, see CAmSocketHandler
- */
- bool checkerCallback(const sh_pollHandle_t handle, void* userData)
+ private:
+
+ /**
+ * Prototype for a delegate
+ */
+ class CAmDelegate
+ {
+ public:
+
+ typedef enum
+ :bool
+ {
+ SyncCallType = false, AsyncCallType = true
+ } CallType;
+
+ virtual ~CAmDelegate()
+ {
+ }
+ ;
+ virtual CallType call(int* pipe)=0;
+
+ };
+
+ /**
+ * Prototype for a delegate with variadic template arguments in conjunction with the following class.
+ */
+ template<class Class, typename Method, typename Tuple, bool Done, int Total, int ... N>
+ class CAmDelegateAsyncImpl: public CAmDelegate
+ {
+ Class mInstance;
+ Method mMethod;
+ Tuple mArguments;
+ public:
+ friend class CAmSerializer;
+ static void call(Class instance, Method method, Tuple && arguments)
+ {
+ CAmDelegateAsyncImpl<Class, Method, Tuple, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(instance, method, std::forward<Tuple>(arguments));
+ }
+
+ CAmDelegateAsyncImpl(Class instance, Method method, Tuple && arguments)
+ {
+ mInstance = instance;
+ mMethod = method;
+ mArguments = std::move(arguments);
+ }
+
+ CallType call(int* pipe)
+ {
+ (void) pipe;
+ call(mInstance, mMethod, std::forward<Tuple>(mArguments));
+ return (AsyncCallType);
+ }
+ ;
+ };
+
+ /**
+ * Prototype for a delegate with variadic template arguments.
+ */
+ template<class Class, typename Method, typename Tuple, int Total, int ... N>
+ class CAmDelegateAsyncImpl<Class, Method, Tuple, true, Total, N...> : public CAmDelegate
+ {
+ Class mInstance;
+ Method mMethod;
+ Tuple mArguments;
+ public:
+ friend class CAmSerializer;
+ static void call(Class instance, Method method, Tuple && t)
+ {
+ (*instance.*method)(std::get<N>(std::forward<Tuple>(t))...);
+ }
+
+ CAmDelegateAsyncImpl(Class instance, Method method, Tuple && arguments)
+ {
+ mInstance = instance;
+ mMethod = method;
+ mArguments = std::move(arguments);
+ }
+
+ CallType call(int* pipe)
+ {
+ (void) pipe;
+ call(mInstance, mMethod, std::forward<Tuple>(mArguments));
+ return (AsyncCallType);
+ }
+ ;
+ };
+
+ /**
+ * Prototype for a delegate with variadic template arguments in conjunction with the following class.
+ */
+ template<class Class, typename Method, typename Return, typename Tuple, bool Done, int Total, int ... N>
+ class CAmDelegateSyncImpl: public CAmDelegate
+ {
+ Class mInstance;
+ Method mMethod;
+ Tuple mArguments;
+ Return mReturn;
+ public:
+ friend class CAmSerializer;
+ static void call(Class instance, Method method, Return & result, Tuple && arguments)
+ {
+ CAmDelegateSyncImpl<Class, Method, Return, Tuple, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(instance, method, result, std::forward<Tuple>(arguments));
+ }
+
+ CAmDelegateSyncImpl(Class instance, Method method, Tuple && arguments)
+ {
+ mInstance = instance;
+ mMethod = method;
+ mArguments = std::move(arguments);
+ }
+
+ CallType call(int* pipe)
+ {
+ call(mInstance, mMethod, mReturn, std::forward<Tuple>(mArguments));
+ ssize_t result(-1);
+ result = write(pipe[1], this, sizeof(this));
+ if (result == -1)
+ logError("CAmSerializer: Problem writing into pipe! Error No:", errno);
+ return (SyncCallType);
+ }
+ ;
+ };
+
+ /**
+ * Prototype for a delegate with variadic template arguments.
+ */
+ template<class Class, typename Method, typename Return, typename Tuple, int Total, int ... N>
+ class CAmDelegateSyncImpl<Class, Method, Return, Tuple, true, Total, N...> : public CAmDelegate
+ {
+ Class mInstance;
+ Method mMethod;
+ Tuple mArguments;
+ Return mReturn;
+ public:
+ friend class CAmSerializer;
+ static void call(Class instance, Method method, Return & result, Tuple && t)
+ {
+ result = (*instance.*method)(std::get<N>(t)...);
+ }
+
+ CAmDelegateSyncImpl(Class instance, Method method, Tuple && arguments)
+ {
+ mInstance = instance;
+ mMethod = method;
+ mArguments = std::move(arguments);
+ }
+
+ CallType call(int* pipe)
+ {
+ call(mInstance, mMethod, mReturn, std::forward<Tuple>(mArguments));
+ ssize_t result(-1);
+ result = write(pipe[1], this, sizeof(this));
+ if (result == -1)
+ logError("CAmSerializer: Problem writing into pipe! Error No:", errno);
+ return (SyncCallType);
+ }
+ ;
+ };
+
+ typedef CAmDelegate* CAmDelegagePtr; //!< pointer to a delegate
+
+ public:
+ /**
+ * instantiates a async delegate with given arguments and sends the delegate pointer over the pipe
+ */
+ template<typename Class, typename Method, typename Tuple>
+ void doAsyncCall(Class intsance, Method method, Tuple & arguments)
+ {
+ typedef typename std::decay<Tuple>::type ttype;
+ typedef CAmDelegateAsyncImpl<Class, Method, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value> AsyncDelegate;
+ AsyncDelegate *pImp = new AsyncDelegate(intsance, method, std::forward<Tuple>(arguments));
+ send(pImp);
+ //Do not delete the pointer. It will be deleted automatically later.
+ }
+
+ /**
+ * instantiates a sync delegate with given arguments and sends the delegate pointer over the pipe
+ */
+ template<typename Class, typename Method, typename Return, typename Tuple>
+ void doSyncCall(Class intsance, Method method, Return & result, Tuple & arguments)
+ {
+ typedef typename std::decay<Tuple>::type ttype;
+ typedef CAmDelegateSyncImpl<Class, Method, Return, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value> SyncDelegate;
+ SyncDelegate *pImp = new SyncDelegate(intsance, method, std::forward<Tuple>(arguments));
+ send(pImp);
+ int numReads;
+ SyncDelegate *p = NULL;
+ if ((numReads = read(mReturnPipe[0], &p, sizeof(p))) == -1)
+ {
+ logError("CAmSerializer::doSyncCall could not read pipe!");
+ throw std::runtime_error("CAmSerializer Could not read pipe!");
+ }
+ result = std::move(pImp->mReturn);
+ arguments = std::move(pImp->mArguments);
+ //Delete the pointer.
+ delete pImp;
+ }
+ private:
+
+ /**
+ * rings the line of the pipe and adds the delegate pointer to the queue
+ * @param p delegate pointer
+ */
+ inline void send(CAmDelegagePtr p)
+ {
+ if (write(mPipe[1], &p, sizeof(p)) == -1)
+ {
+ throw std::runtime_error("could not write to pipe !");
+ }
+ }
+
+ int mPipe[2]; //!< the pipe
+ int mReturnPipe[2]; //!< pipe handling returns
+ sh_pollHandle_t mHandle;
+ CAmSocketHandler* mpSocketHandler;
+ std::deque<CAmDelegagePtr> mListDelegatePoiters; //!< intermediate queue to store the pipe results
+
+ public:
+
+ /**
+ * get the size of delegate pointers
+ */
+ int getListDelegatePoiters()
+ {
+ return mListDelegatePoiters.size();
+ }
+
+ /**
+ * calls a function with variadic arguments threadsafe
+ * @param instance the instance of the class that shall be called
+ * @param function the function that shall be called as member function pointer.
+ * @param output variable.
+ * @tparam TClass the type of the Class to be called
+ * @tparam TRet the type of the result
+ * @tparam TArgs argument list
+ * \section ex Example:
+ * @code
+ * class MyGreatClass
+ * {
+ * public:
+ * int AGreatMethod(int x);
+ * }
+ * CAmSerializer serial(&Sockethandler);
+ * MyGreatClass anInstance;
+ * int result;
+ * serial.syncCall<MyGreatClass, int, int>(&anInstance,&MyGreatClass::AGreatMethod, result, 100);
+ * @endcode
+ */
+ template<class TClass, class TRet, class ... TArgs>
+ void syncCall(TClass* instance, TRet (TClass::*method)(TArgs ...), TRet & result, TArgs & ... arguments)
+ {
+ auto t = std::make_tuple(arguments...);
+ doSyncCall(instance, method, result, t);
+ std::tie(arguments...) = t;
+ }
+
+ /**
+ * calls a function with variadic arguments threadsafe
+ * @param instance the instance of the class that shall be called
+ * @param function the function that shall be called as member function pointer.
+ * @tparam TClass the type of the Class to be called
+ * @tparam TRet the type of the result
+ * @tparam TArgs argument list
+ * \section ex Example:
+ * @code
+ * class MyGreatClass
+ * {
+ * public:
+ * int AGreatMethod(int x);
+ * }
+ * CAmSerializer serial(&Sockethandler);
+ * MyGreatClass anInstance;
+ * serial.asyncCall<MyGreatClass, void, int>(&anInstance,&MyGreatClass::AGreatMethod, 100);
+ * @endcode
+ */
+ template<class TClass, class TRet, class ... TArgs>
+ void asyncCall(TClass* instance, TRet (TClass::*method)(TArgs ...), TArgs & ... arguments)
+ {
+ auto t = std::make_tuple(arguments...);
+ doAsyncCall(instance, method, t);
+ }
+
+ /**
+ * calls a function with no arguments threadsafe
+ * @param instance the instance of the class that shall be called
+ * @param function the function that shall be called as memberfunction pointer.
+ * @tparam TClass1 the type of the Class to be called
+ * \section ex Example:
+ * @code
+ * class myClass
+ * {
+ * public:
+ * void myfunction();
+ * }
+ * CAmSerializer serial(&Sockethandler);
+ * myClass instanceMyClass;
+ * serial<CommandSender>(&instanceMyClass,&myClass::myfunction);
+ * @endcode
+ */
+ template<class TClass>
+ void asyncCall(TClass* instance, void (TClass::*function)())
+ {
+ auto t = std::make_tuple();
+ doAsyncCall(instance, function, t);
+ }
+
+ /**
+ * calls a function with one arguments asynchronously threadsafe
+ * @param instance the instance of the class that shall be called
+ * @param function the function that shall be called as memberfunction pointer.
+ * @param argument the argument
+ * @tparam TClass1 the type of the Class to be called
+ * @tparam Targ the type of the argument to be called
+ * \section ex Example:
+ * @code
+ * class myClass
+ * {
+ * public:
+ * void myfunction(int k);
+ * }
+ * CAmSerializer serial(&Sockethandler);
+ * myClass instanceMyClass;
+ * serial<CommandSender,int>(&instanceMyClass,&myClass::myfunction,k);
+ * @endcode
+ *
+ */
+ template<class TClass1, class Targ>
+ void asyncCall(TClass1* instance, void (TClass1::*function)(Targ), Targ argument)
+ {
+ auto t = std::make_tuple(argument);
+ doAsyncCall(instance, function, t);
+ }
+
+ /**
+ * calls a function with one argument called by reference asynchronously threadsafe
+ * @param instance the instance of the class that shall be called
+ * @param function the function that shall be called as memberfunction pointer.
+ * @param argument the argument
+ * @tparam TClass1 the type of the Class to be called
+ * @tparam Targ the type of the argument to be called
+ * \section ex Example:
+ * @code
+ * class myClass
+ * {
+ * public:
+ * void myfunction(int k);
+ * }
+ * CAmSerializer serial(&Sockethandler);
+ * myClass instanceMyClass;
+ * serial<CommandSender,int>(&instanceMyClass,&myClass::myfunction,k);
+ * @endcode
+ *
+ */
+ template<class TClass1, class Targ>
+ void asyncCall(TClass1* instance, void (TClass1::*function)(Targ&), Targ& argument)
+ {
+ auto t = std::make_tuple(argument);
+ doAsyncCall(instance, function, t);
+ }
+
+ /**
+ * calls a function with two arguments asynchronously threadsafe. for more see asyncCall with one argument
+ * @param instance pointer to the instance of the class
+ * @param function memberfunction poitner
+ * @param argument the first argument
+ * @param argument1 the second argument
+ * @tparam TClass1 the type of the Class to be called
+ * @tparam Targ the type of the argument to be called
+ * @tparam Targ1 the type of the first argument to be called
+ */
+ template<class TClass1, class Targ, class Targ1>
+ void asyncCall(TClass1* instance, void (TClass1::*function)(Targ argument, Targ1 argument1), Targ argument, Targ1 argument1)
+ {
+ auto t = std::make_tuple(argument, argument1);
+ doAsyncCall(instance, function, t);
+ }
+
+ /**
+ * calls a function with two arguments asynchronously threadsafe, first argument is a reference. for more see asyncCall with one argument
+ * @param instance pointer to the instance of the class
+ * @param function memberfunction poitner
+ * @param argument the first argument
+ * @param argument1 the second argument
+ * @tparam TClass1 the type of the Class to be called
+ * @tparam Targ the type of the argument to be called
+ * @tparam Targ1 the type of the first argument to be called
+ */
+ template<class TClass1, class Targ, class Targ1>
+ void asyncCall(TClass1* instance, void (TClass1::*function)(Targ& argument, Targ1 argument1), Targ& argument, Targ1 argument1)
+ {
+ auto t = std::make_tuple(argument, argument1);
+ doAsyncCall(instance, function, t);
+ }
+
+ /**
+ * calls a function with two arguments asynchronously threadsafe, second argument is a reference. for more see asyncCall with one argument
+ * @param instance pointer to the instance of the class
+ * @param function memberfunction poitner
+ * @param argument the first argument
+ * @param argument1 the second argument
+ * @tparam TClass1 the type of the Class to be called
+ * @tparam Targ the type of the argument to be called
+ * @tparam Targ1 the type of the first argument to be called
+ */
+ template<class TClass1, class Targ, class Targ1>
+ void asyncCall(TClass1* instance, void (TClass1::*function)(Targ argument, Targ1& argument1), Targ argument, Targ1& argument1)
+ {
+ auto t = std::make_tuple(argument, argument1);
+ doAsyncCall(instance, function, t);
+ }
+
+ /**
+ * calls a function with two arguments asynchronously threadsafe, both arguments are references. for more see asyncCall with one argument
+ * @param instance pointer to the instance of the class
+ * @param function memberfunction poitner
+ * @param argument the first argument
+ * @param argument1 the second argument
+ * @tparam TClass1 the type of the Class to be called
+ * @tparam Targ the type of the argument to be called
+ * @tparam Targ1 the type of the first argument to be called
+ */
+ template<class TClass1, class Targ, class Targ1>
+ void asyncCall(TClass1* instance, void (TClass1::*function)(Targ& argument, Targ1& argument1), Targ& argument, Targ1& argument1)
+ {
+ auto t = std::make_tuple(argument, argument1);
+ doAsyncCall(instance, function, t);
+ }
+
+ /**
+ * calls a function with three arguments asynchronously threadsafe. for more see other asycCall
+ */
+ template<class TClass1, class Targ, class Targ1, class Targ2>
+ void asyncCall(TClass1* instance, void (TClass1::*function)(Targ argument, Targ1 argument1, Targ2 argument2), Targ argument, Targ1 argument1, Targ2 argument2)
+ {
+ auto t = std::make_tuple(argument, argument1, argument2);
+ doAsyncCall(instance, function, t);
+ }
+
+ /**
+ * calls a function with three arguments asynchronously threadsafe. for more see other asycCall
+ */
+ template<class TClass1, class Targ, class Targ1, class Targ2>
+ void asyncCall(TClass1* instance, void (TClass1::*function)(Targ& argument, Targ1 argument1, Targ2 argument2), Targ& argument, Targ1 argument1, Targ2 argument2)
+ {
+ auto t = std::make_tuple(argument, argument1, argument2);
+ doAsyncCall(instance, function, t);
+ }
+
+ /**
+ * calls a function with three arguments asynchronously threadsafe. for more see other asycCall
+ */
+ template<class TClass1, class Targ, class Targ1, class Targ2>
+ void asyncCall(TClass1* instance, void (TClass1::*function)(Targ argument, Targ1& argument1, Targ2 argument2), Targ argument, Targ1& argument1, Targ2 argument2)
+ {
+ auto t = std::make_tuple(argument, argument1, argument2);
+ doAsyncCall(instance, function, t);
+ }
+
+ /**
+ * calls a function with three arguments asynchronously threadsafe. for more see other asycCall
+ */
+ template<class TClass1, class Targ, class Targ1, class Targ2>
+ void asyncCall(TClass1* instance, void (TClass1::*function)(Targ argument, Targ1 argument1, Targ2& argument2), Targ argument, Targ1 argument1, Targ2& argument2)
+ {
+ auto t = std::make_tuple(argument, argument1, argument2);
+ doAsyncCall(instance, function, t);
+ }
+
+ /**
+ * calls a function with three arguments asynchronously threadsafe. for more see other asycCall
+ */
+ template<class TClass1, class Targ, class Targ1, class Targ2>
+ void asyncCall(TClass1* instance, void (TClass1::*function)(Targ argument, Targ1& argument1, Targ2& argument2), Targ argument, Targ1& argument1, Targ2& argument2)
+ {
+ auto t = std::make_tuple(argument, argument1, argument2);
+ doAsyncCall(instance, function, t);
+ }
+
+ /**
+ * calls a function with three arguments asynchronously threadsafe. for more see other asycCall
+ */
+ template<class TClass1, class Targ, class Targ1, class Targ2>
+ void asyncCall(TClass1* instance, void (TClass1::*function)(Targ& argument, Targ1& argument1, Targ2& argument2), Targ& argument, Targ1& argument1, Targ2& argument2)
+ {
+ auto t = std::make_tuple(argument, argument1, argument2);
+ doAsyncCall(instance, function, t);
+ }
+
+ /**
+ * calls a function with three arguments asynchronously threadsafe. for more see other asycCall
+ */
+ template<class TClass1, class Targ, class Targ1, class Targ2>
+ void asyncCall(TClass1* instance, void (TClass1::*function)(Targ& argument, Targ1& argument1, Targ2 argument2), Targ& argument, Targ1& argument1, Targ2 argument2)
+ {
+ auto t = std::make_tuple(argument, argument1, argument2);
+ doAsyncCall(instance, function, t);
+ }
+
+ /**
+ * calls a function with three arguments asynchronously threadsafe. for more see other asycCall
+ */
+ template<class TClass1, class Targ, class Targ1, class Targ2>
+ void asyncCall(TClass1* instance, void (TClass1::*function)(Targ& argument, Targ1 argument1, Targ2& argument2), Targ& argument, Targ1 argument1, Targ2& argument2)
+ {
+ auto t = std::make_tuple(argument, argument1, argument2);
+ doAsyncCall(instance, function, t);
+ }
+
+ /**
+ * calls a function with four arguments asynchronously threadsafe. for more see other asycCall
+ */
+ template<class TClass1, class Targ, class Targ1, class Targ2, class Targ3>
+ void asyncCall(TClass1* instance, void (TClass1::*function)(Targ argument, Targ1 argument1, Targ2 argument2, Targ3 argument3), Targ argument, Targ1 argument1, Targ2 argument2, Targ3 argument3)
+ {
+ auto t = std::make_tuple(argument, argument1, argument2, argument3);
+ doAsyncCall(instance, function, t);
+ }
+
+ /**
+ * calls a synchronous function with no arguments threadsafe
+ * @param instance the instance of the class that shall be called
+ * @param function the function that shall be called as memberfunction pointer.
+ * @param retVal the return parameter, no const allowed !
+ * @tparam TClass1 the type of the class to be called
+ * @tparam TretVal the type of the return parameter
+ * \section ex Example:
+ * @code
+ * class myClass
+ * {
+ * public:
+ * am_Error_e myfunction();
+ * }
+ * CAmSerializer serial(&Sockethandler);
+ * myClass instanceMyClass;
+ * am_Error_e error;
+ * serial<CommandSender,am_Error_e>(&instanceMyClass,&myClass::myfunction, error);
+ * @endcode
+ * All arguments given to synchronous functions must be non-const since the results of the operations will be written back to the arguments.
+ *
+ */
+ template<class TClass1, class TretVal>
+ void syncCall(TClass1* instance, TretVal (TClass1::*function)(), TretVal& retVal)
+ {
+ auto t = std::make_tuple();
+ doSyncCall(instance, function, retVal, t);
+ }
+
+ /**
+ * calls a function with one argument synchronous threadsafe
+ * @param instance the instance of the class that shall be called
+ * @param function the function that shall be called as memberfunction pointer.
+ * @param retVal the return parameter, no const allowed !
+ * @param argument the argument, no const allowed !
+ * @tparam TClass1 the type of the class to be called
+ * @tparam TretVal the type of the return parameter
+ * @tparam TargCall the type of the argument like in the function to be called. here all references and const must be
+ * respected!
+ * @tparam Targ the type of the argument, here no const and no references allowed !
+ * \section ex Example:
+ * @code
+ * class myClass
+ * {
+ * public:
+ * am_Error_e myfunction(int k);
+ * }
+ * CAmSerializer serial(&Sockethandler);
+ * myClass instanceMyClass;
+ * am_Error_e error;
+ * int l;
+ * serial<CommandSender,am_Error_e,int>(&instanceMyClass,&myClass::myfunction,error,l);
+ * @endcode
+ * All arguments given to synchronous functions must be non-const since the results of the operations will be written back to the arguments.
+ */
+ template<class TClass1, class TretVal, class TargCall, class Targ>
+ void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall), TretVal& retVal, Targ& argument)
+ {
+ auto t = std::make_tuple(argument);
+ doSyncCall(instance, function, retVal, t);
+ std::tie(argument) = t;
+ }
+
+ /**
+ * calls a function with one argument synchronous threadsafe for const functions. For more see syncCall with one argument
+ */
+ template<class TClass1, class TretVal, class TargCall, class Targ>
+ void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall) const, TretVal& retVal, Targ& argument)
+ {
+ auto t = std::make_tuple(argument);
+ doSyncCall(instance, function, retVal, t);
+ std::tie(argument) = t;
+ }
+
+ /**
+ * calls a function with two arguments synchronously threadsafe. For more see syncCall with one argument
+ */
+ template<class TClass1, class TretVal, class TargCall, class Targ1Call, class Targ, class Targ1>
+ void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall, Targ1Call), TretVal& retVal, Targ& argument, Targ1& argument1)
+ {
+ auto t = std::make_tuple(argument, argument1);
+ doSyncCall(instance, function, retVal, t);
+ std::tie(argument, argument1) = t;
+ }
+ /**
+ * calls a function with two arguments synchronously threadsafe const. For more see syncCall with one argument
+ */
+ template<class TClass1, class TretVal, class TargCall, class Targ1Call, class Targ, class Targ1>
+ void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall, Targ1Call) const, TretVal& retVal, Targ& argument, Targ1& argument1)
+ {
+ auto t = std::make_tuple(argument, argument1);
+ doSyncCall(instance, function, retVal, t);
+ std::tie(argument, argument1) = t;
+ }
+
+ /**
+ * calls a function with three arguments synchronously threadsafe. for more see syncCall with one argument
+ */
+ template<class TClass1, class TretVal, class TargCall, class TargCall1, class TargCall2, class Targ, class Targ1, class Targ2>
+ void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall, TargCall1, TargCall2), TretVal& retVal, Targ& argument, Targ1& argument1, Targ2& argument2)
+ {
+ auto t = std::make_tuple(argument, argument1, argument2);
+ doSyncCall(instance, function, retVal, t);
+ std::tie(argument, argument1, argument2) = t;
+ }
+
+ /**
+ * calls a const function with three arguments synchronously threadsafe. for more see syncCall with one argument
+ */
+ template<class TClass1, class TretVal, class TargCall, class TargCall1, class TargCall2, class Targ, class Targ1, class Targ2>
+ void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall, TargCall1, TargCall2) const, TretVal& retVal, Targ& argument, Targ1& argument1, Targ2& argument2)
+ {
+ auto t = std::make_tuple(argument, argument1, argument2);
+ doSyncCall(instance, function, retVal, t);
+ std::tie(argument, argument1, argument2) = t;
+ }
+
+ /**
+ * calls a function with four arguments synchronously threadsafe. for more see syncCall with one argument
+ */
+ template<class TClass1, class TretVal, class TargCall, class TargCall1, class TargCall2, class TargCall3, class Targ, class Targ1, class Targ2, class Targ3>
+ void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall, TargCall1, TargCall2, TargCall3), TretVal& retVal, Targ& argument, Targ1& argument1, Targ2& argument2, Targ3& argument3)
+ {
+ auto t = std::make_tuple(argument, argument1, argument2, argument3);
+ doSyncCall(instance, function, retVal, t);
+ std::tie(argument, argument1, argument2, argument3) = t;
+ }
+
+ /**
+ * calls a function with five arguments synchronously threadsafe. for more see syncCall with one argument
+ */
+ template<class TClass1, class TretVal, class TargCall, class TargCall1, class TargCall2, class TargCall3, class TargCall4, class Targ, class Targ1, class Targ2, class Targ3, class Targ4>
+ void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall, TargCall1, TargCall2, TargCall3, TargCall4), TretVal& retVal, Targ& argument, Targ1& argument1, Targ2& argument2, Targ3& argument3, Targ4& argument4)
+ {
+ auto t = std::make_tuple(argument, argument1, argument2, argument3, argument4);
+ doSyncCall(instance, function, retVal, t);
+ std::tie(argument, argument1, argument2, argument3, argument4) = t;
+ }
+
+ /**
+ * calls a function with six arguments synchronously threadsafe. for more see syncCall with one argument
+ */
+ template<class TClass1, class TretVal, class TargCall, class TargCall1, class TargCall2, class TargCall3, class TargCall4, class TargCall5, class Targ, class Targ1, class Targ2, class Targ3, class Targ4, class Targ5>
+ void syncCall(TClass1* instance, TretVal (TClass1::*function)(TargCall, TargCall1, TargCall2, TargCall3, TargCall4, TargCall5), TretVal& retVal, Targ& argument, Targ1& argument1, Targ2& argument2, Targ3& argument3,
+ Targ4& argument4, Targ5& argument5)
+ {
+ auto t = std::make_tuple(argument, argument1, argument2, argument3, argument4, argument5);
+ doSyncCall(instance, function, retVal, t);
+ std::tie(argument, argument1, argument2, argument3, argument4, argument5) = t;
+ }
+
+ /**
+ * receiver callback for sockethandling, for more, see CAmSocketHandler
+ */
+ void receiverCallback(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
+ {
+ (void) handle;
+ (void) userData;
+ int numReads;
+ CAmDelegagePtr listPointers[3];
+ if ((numReads = read(pollfd.fd, &listPointers, sizeof(listPointers))) == -1)
+ {
+ logError("CAmSerializer::receiverCallback could not read pipe!");
+ throw std::runtime_error("CAmSerializer Could not read pipe!");
+ }
+ mListDelegatePoiters.assign(listPointers, listPointers + (numReads / sizeof(CAmDelegagePtr)));
+ }
+
+ /**
+ * checker callback for sockethandling, for more, see CAmSocketHandler
+ */
+ bool checkerCallback(const sh_pollHandle_t handle, void* userData)
+ {
+ (void) handle;
+ (void) userData;
+ if (mListDelegatePoiters.empty())
+ return (false);
+ return (true);
+ }
+
+ /**
+ * dispatcher callback for sockethandling, for more, see CAmSocketHandler
+ */
+ bool dispatcherCallback(const sh_pollHandle_t handle, void* userData)
+ {
+ (void) handle;
+ (void) userData;
+ CAmDelegagePtr delegatePoiter = mListDelegatePoiters.front();
+ mListDelegatePoiters.pop_front();
+ if (delegatePoiter->call(mReturnPipe))
+ delete delegatePoiter;
+ if (mListDelegatePoiters.empty())
+ return (false);
+ return (true);
+ }
+
+ TAmShPollFired<CAmSerializer> receiverCallbackT;
+ TAmShPollDispatch<CAmSerializer> dispatcherCallbackT;
+ TAmShPollCheck<CAmSerializer> checkerCallbackT;
+
+ /**
+ * The constructor must be called in the mainthread context !
+ * @param iSocketHandler pointer to the CAmSocketHandler
+ */
+ CAmSerializer(CAmSocketHandler *iSocketHandler) :
+ mPipe(), //
+ mReturnPipe(), //
+ mHandle(),
+ mpSocketHandler(iSocketHandler),
+ mListDelegatePoiters(), //
+ receiverCallbackT(this, &CAmSerializer::receiverCallback), //
+ dispatcherCallbackT(this, &CAmSerializer::dispatcherCallback), //
+ checkerCallbackT(this, &CAmSerializer::checkerCallback)
+ {
+ assert(NULL!=iSocketHandler);
+
+ if (pipe(mPipe) == -1)
+ {
+ logError("CAmSerializer could not create pipe!");
+ throw std::runtime_error("CAmSerializer Could not open pipe!");
+ }
+
+ if (pipe(mReturnPipe) == -1)
+ {
+ logError("CAmSerializer could not create mReturnPipe!");
+ throw std::runtime_error("CAmSerializer Could not open mReturnPipe!");
+ }
+
+ short event = 0;
+ event |= POLLIN;
+ mpSocketHandler->addFDPoll(mPipe[0], event, NULL, &receiverCallbackT, &checkerCallbackT, &dispatcherCallbackT, NULL, mHandle);
+ }
+
+ ~CAmSerializer()
+ {
+ mpSocketHandler->removeFDPoll(mHandle);
+ close(mPipe[0]);
+ close(mPipe[1]);
+ close(mReturnPipe[0]);
+ close(mReturnPipe[1]);
+ }
+ };
+
+ } /* namespace V1 */
+
+ /**@}*/
+
+ namespace V2
{
- (void) handle;
- (void) userData;
- if (mListDelegatePoiters.empty())
- return (false);
- return (true);
- }
-
- /**
- * dispatcher callback for sockethandling, for more, see CAmSocketHandler
- */
- bool dispatcherCallback(const sh_pollHandle_t handle, void* userData)
- {
- (void) handle;
- (void) userData;
- CAmDelegagePtr delegatePoiter = mListDelegatePoiters.front();
- mListDelegatePoiters.pop_front();
- if (delegatePoiter->call(mReturnPipe))
- delete delegatePoiter;
- if (mListDelegatePoiters.empty())
- return (false);
- return (true);
- }
-
- TAmShPollFired<CAmSerializer> receiverCallbackT;
- TAmShPollDispatch<CAmSerializer> dispatcherCallbackT;
- TAmShPollCheck<CAmSerializer> checkerCallbackT;
-
- /**
- * The constructor must be called in the mainthread context !
- * @param iSocketHandler pointer to the CAmSocketHandler
- */
- CAmSerializer(CAmSocketHandler *iSocketHandler) :
- mPipe(), //
- mReturnPipe(),//
- mHandle(),
- mpSocketHandler(iSocketHandler),
- mListDelegatePoiters(), //
- receiverCallbackT(this, &CAmSerializer::receiverCallback), //
- dispatcherCallbackT(this, &CAmSerializer::dispatcherCallback), //
- checkerCallbackT(this, &CAmSerializer::checkerCallback)
- {
- assert(NULL!=iSocketHandler);
-
- if (pipe(mPipe) == -1)
- {
- logError("CAmSerializer could not create pipe!");
- throw std::runtime_error("CAmSerializer Could not open pipe!");
- }
-
- if (pipe(mReturnPipe) == -1)
+ class CAmSerializer
{
- logError("CAmSerializer could not create mReturnPipe!");
- throw std::runtime_error("CAmSerializer Could not open mReturnPipe!");
- }
-
- short event = 0;
- event |= POLLIN;
- mpSocketHandler->addFDPoll(mPipe[0], event, NULL, &receiverCallbackT, &checkerCallbackT, &dispatcherCallbackT, NULL, mHandle);
- }
+ /**
+ * Prototype for a delegate
+ */
+ class CAmDelegate
+ {
+ public:
+ typedef enum
+ :bool
+ {
+ SyncCallType = false, AsyncCallType = true
+ } CallType;
+
+ virtual ~CAmDelegate()
+ {
+ }
+ ;
+ virtual CallType call(int* pipe)=0;
+ };
+
+ /**
+ * Prototype for a delegate with variadic template arguments.
+ */
+ template<class TInvocation>
+ class CAmDelegateAsyncImpl: public CAmDelegate
+ {
+ TInvocation mInvocation;
+ public:
+ friend class CAmSerializer;
+ CAmDelegateAsyncImpl(TInvocation && invocation) :
+ mInvocation(std::move(invocation))
+ {
+ }
+
+ CallType call(int* pipe)
+ {
+ (void) pipe;
+ mInvocation();
+ return (AsyncCallType);
+ }
+ ;
+ };
+
+ template<class TInvocation, class TRet>
+ class CAmDelegateSyncImpl: public CAmDelegate
+ {
+ TInvocation mInvocation;
+ TRet & mReturn;
+ public:
+ friend class CAmSerializer;
+ CAmDelegateSyncImpl(TInvocation && invocation, TRet && ret) :
+ mInvocation(std::move(invocation)), mReturn(ret)
+ {
+ }
+
+ CallType call(int* pipe)
+ {
+ mReturn = mInvocation();
+ ssize_t result(-1);
+ result = write(pipe[1], this, sizeof(this));
+ if (result == -1)
+ logError("CAmSerializer: Problem writing into pipe! Error No:", errno);
+ return (SyncCallType);
+ }
+ ;
+ };
+
+ template<class TInvocation>
+ class CAmDelegateSyncVoidImpl: public CAmDelegate
+ {
+ TInvocation mInvocation;
+ public:
+ friend class CAmSerializer;
+ CAmDelegateSyncVoidImpl(TInvocation && invocation) :
+ mInvocation(std::move(invocation))
+ {
+ }
+
+ CallType call(int* pipe)
+ {
+ mInvocation();
+ ssize_t result(-1);
+ result = write(pipe[1], this, sizeof(this));
+ if (result == -1)
+ logError("CAmSerializer: Problem writing into pipe! Error No:", errno);
+ return (SyncCallType);
+ }
+ ;
+ };
+
+ typedef CAmDelegate* CAmDelegagePtr; //!< pointer to a delegate
+
+ void sendSync(CAmDelegagePtr pDelegate)
+ {
+ send(pDelegate);
+ int numReads;
+ CAmDelegagePtr *p = NULL;
+ if ((numReads = read(mReturnPipe[0], &p, sizeof(p))) == -1)
+ {
+ logError("CAmSerializer::doSyncCall could not read pipe!");
+ throw std::runtime_error("CAmSerializer Could not read pipe!");
+ }
+ }
+
+ /**
+ * rings the line of the pipe and adds the delegate pointer to the queue
+ * @param p delegate pointer
+ */
+ inline void send(CAmDelegagePtr p)
+ {
+ if (write(mPipe[1], &p, sizeof(p)) == -1)
+ {
+ throw std::runtime_error("could not write to pipe !");
+ }
+ }
+
+ int mPipe[2]; //!< the pipe
+ int mReturnPipe[2]; //!< pipe handling returns
+ sh_pollHandle_t mHandle;
+ CAmSocketHandler* mpSocketHandler;
+ std::deque<CAmDelegagePtr> mListDelegatePointers; //!< intermediate queue to store the pipe results
+
+ public:
+
+ /**
+ * get the size of delegate pointers
+ */
+ size_t getListDelegatePointers()
+ {
+ return mListDelegatePointers.size();
+ }
+
+ /**
+ * calls a function with variadic arguments threadsafe
+ * @param invocation is a type is produced by std::bind
+ * \section ex Example:
+ * @code
+ * CAmSerializer serial(&Sockethandler);
+ * serial.asyncInvocation(std::bind([]()->bool{return true;}));
+ * @endcode
+ */
+ template<class TFunc>
+ void asyncInvocation(TFunc invocation)
+ {
+ static_assert(std::is_bind_expression<TFunc>::value,"The type is not produced by std::bind");
+ typedef CAmDelegateAsyncImpl<TFunc> AsyncDelegate;
+ AsyncDelegate *pImp = new AsyncDelegate(std::forward<TFunc>(invocation));
+ send(pImp);
+ //Do not delete the pointer. It will be deleted automatically later.
+ }
+
+ /**
+ * calls a function with variadic arguments threadsafe
+ * @param instance the instance of the class that shall be called
+ * @param function the function that shall be called as member function pointer.
+ * @tparam TClass the type of the Class to be called
+ * @tparam TRet the type of the result
+ * @tparam TArgs argument list
+ * \section ex Example:
+ * @code
+ * class AClass
+ * {
+ * public:
+ * void instanceMethod(int x);
+ * }
+ * CAmSerializer serial(&Sockethandler);
+ * AClass anInstance;
+ * serial.asyncCall(&anInstance,&AClass::instanceMethod, 100);
+ * @endcode
+ */
+ template<class TClass, class TMeth, class TRet, class ... TArgs>
+ void asyncCall(TClass* instance, TMeth method, TArgs && ... arguments)
+ {
+ auto invocation = std::bind(method, instance, std::forward<TArgs>(arguments)...);
+ asyncInvocation(invocation);
+ }
+
+ template<class TClass, class TMeth, class ... TArgs>
+ void asyncCall(TClass* instance, TMeth method, TArgs && ... arguments)
+ {
+ auto invocation = std::bind(method, instance, std::forward<TArgs>(arguments)...);
+ asyncInvocation(invocation);
+ }
+
+ /**
+ * calls a function with variadic arguments threadsafe
+ * @param invocation is a type is produced by std::bind
+ * @param result from type TRet
+ * \section ex Example:
+ * @code
+ * CAmSerializer serial(&Sockethandler);
+ * bool result;
+ * serial.syncCall(std::bind([]()->bool{return true;}), result);
+ * @endcode
+ */
+ template<class TFunc, class TRet>
+ void syncInvocation(TFunc invocation, TRet && result)
+ {
+ static_assert(std::is_bind_expression<TFunc>::value,"The type is not produced by std::bind");
+
+ typedef CAmDelegateSyncImpl<TFunc, TRet> SyncDelegate;
+
+ SyncDelegate *pImp = new SyncDelegate(std::forward<TFunc>(invocation), std::forward<TRet>(result));
+ sendSync(pImp);
+ //Delete the pointer.
+ delete pImp;
+ }
+
+ /**
+ * calls a function with variadic arguments threadsafe
+ * @param invocation is a type produced by std::bind
+ * \section ex Example:
+ * @code
+ * CAmSerializer serial(&Sockethandler);
+ * serial.syncCall(std::bind([]()->bool{return true;}));
+ * @endcode
+ */
+ template<class TFunc>
+ void syncInvocation(TFunc invocation)
+ {
+ static_assert(std::is_bind_expression<TFunc>::value,"The type is not produced by std::bind");
+
+ typedef CAmDelegateSyncVoidImpl<TFunc> SyncDelegate;
+
+ SyncDelegate *pImp = new SyncDelegate(std::forward<TFunc>(invocation));
+ sendSync(pImp);
+ //Delete the pointer.
+ delete pImp;
+ }
+ /**
+ * calls a function with variadic arguments threadsafe
+ * @param instance the instance of the class that shall be called
+ * @param function the function that shall be called as member function pointer.
+ * @param output variable.
+ * @tparam TClass the type of the Class to be called
+ * @tparam TRet the type of the result
+ * @tparam TArgs argument list
+ * \section ex Example:
+ * @code
+ * class AClass
+ * {
+ * public:
+ * int instanceMethod(int x);
+ * }
+ * CAmSerializer serial(&Sockethandler);
+ * AClass anInstance;
+ * int result;
+ * serial.syncCall(&anInstance,&AClass::instanceMethod, result, 100);
+ * @endcode
+ */
+ template<class TClass, class TMeth, class TRet, class ... TArgs>
+ void syncCall(TClass* instance, TMeth method, TRet & result, TArgs && ... arguments)
+ {
+ auto invocation = std::bind(method, instance, std::ref(arguments)...);
+ syncInvocation(invocation, result);
+ }
+
+ template<class TClass, class TMeth, class ... TArgs>
+ void syncCall(TClass* instance, TMeth method, TArgs && ... arguments)
+ {
+ auto invocation = std::bind(method, instance, std::ref(arguments)...);
+ syncInvocation(invocation);
+ }
+
+ /**
+ * receiver callback for sockethandling, for more, see CAmSocketHandler
+ */
+ void receiverCallback(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
+ {
+ (void) handle;
+ (void) userData;
+ int numReads;
+ CAmDelegagePtr listPointers[3];
+ if ((numReads = read(pollfd.fd, &listPointers, sizeof(listPointers))) == -1)
+ {
+ logError("CAmSerializer::receiverCallback could not read pipe!");
+ throw std::runtime_error("CAmSerializer Could not read pipe!");
+ }
+ mListDelegatePointers.assign(listPointers, listPointers + (numReads / sizeof(CAmDelegagePtr)));
+ }
+
+ /**
+ * checker callback for sockethandling, for more, see CAmSocketHandler
+ */
+ bool checkerCallback(const sh_pollHandle_t handle, void* userData)
+ {
+ (void) handle;
+ (void) userData;
+ if (mListDelegatePointers.empty())
+ return (false);
+ return (true);
+ }
+
+ /**
+ * dispatcher callback for sockethandling, for more, see CAmSocketHandler
+ */
+ bool dispatcherCallback(const sh_pollHandle_t handle, void* userData)
+ {
+ (void) handle;
+ (void) userData;
+ CAmDelegagePtr delegatePoiter = mListDelegatePointers.front();
+ mListDelegatePointers.pop_front();
+ if (delegatePoiter->call(mReturnPipe))
+ delete delegatePoiter;
+ if (mListDelegatePointers.empty())
+ return (false);
+ return (true);
+ }
+
+ TAmShPollFired<CAmSerializer> receiverCallbackT;
+ TAmShPollDispatch<CAmSerializer> dispatcherCallbackT;
+ TAmShPollCheck<CAmSerializer> checkerCallbackT;
+
+ /**
+ * The constructor must be called in the mainthread context !
+ * @param iSocketHandler pointer to the CAmSocketHandler
+ */
+ CAmSerializer(CAmSocketHandler *iSocketHandler) :
+ mPipe(), //
+ mReturnPipe(), //
+ mHandle(),
+ mpSocketHandler(iSocketHandler),
+ mListDelegatePointers(), //
+ receiverCallbackT(this, &CAmSerializer::receiverCallback), //
+ dispatcherCallbackT(this, &CAmSerializer::dispatcherCallback), //
+ checkerCallbackT(this, &CAmSerializer::checkerCallback)
+ {
+ assert(NULL!=iSocketHandler);
+
+ if (pipe(mPipe) == -1)
+ {
+ logError("CAmSerializer could not create pipe!");
+ throw std::runtime_error("CAmSerializer Could not open pipe!");
+ }
+
+ if (pipe(mReturnPipe) == -1)
+ {
+ logError("CAmSerializer could not create mReturnPipe!");
+ throw std::runtime_error("CAmSerializer Could not open mReturnPipe!");
+ }
+
+ short event = 0;
+ event |= POLLIN;
+ mpSocketHandler->addFDPoll(mPipe[0], event, NULL, &receiverCallbackT, &checkerCallbackT, &dispatcherCallbackT, NULL, mHandle);
+ }
+
+ ~CAmSerializer()
+ {
+ mpSocketHandler->removeFDPoll(mHandle);
+ close(mPipe[0]);
+ close(mPipe[1]);
+ close(mReturnPipe[0]);
+ close(mReturnPipe[1]);
+ }
+ };
+ } /* namespace V2 */
+
+ typedef V1::CAmSerializer CAmSerializer DEPRECATED("You should use V2::CAmSerializer instead!");
- ~CAmSerializer()
- {
- mpSocketHandler->removeFDPoll(mHandle);
- close(mPipe[0]);
- close(mPipe[1]);
- close(mReturnPipe[0]);
- close(mReturnPipe[1]);
- }
-};
} /* namespace am */
#endif /* CAMSERIALIZER_H_ */
diff --git a/AudioManagerUtilities/include/CAmSocketHandler.h b/AudioManagerUtilities/include/CAmSocketHandler.h
index 5c3c5ba..717f792 100644
--- a/AudioManagerUtilities/include/CAmSocketHandler.h
+++ b/AudioManagerUtilities/include/CAmSocketHandler.h
@@ -4,6 +4,7 @@
* Copyright (C) 2012, BMW AG
*
* \author Christian Linke, christian.linke@bmw.de BMW 2011,2012
+ * \author Aleksandar Donchev, aleksander.donchev@partner.bmw.de BMW 2017
*
* \copyright
* This Source Code Form is subject to the terms of the
@@ -17,7 +18,6 @@
#ifndef SOCKETHANDLER_H_
#define SOCKETHANDLER_H_
-#include "audiomanagertypes.h"
#include <sys/socket.h>
#include <stdint.h>
#include <sys/poll.h>
@@ -25,190 +25,309 @@
#include <map>
#include <set>
#include <signal.h>
+#include <vector>
+#include <functional>
+#include <sys/signalfd.h>
+#include <audiomanagerconfig.h>
+#include "audiomanagertypes.h"
+
+#ifdef WITH_TIMERFD
+
+#include <stdio.h>
+#include <string>
+#include <stdexcept>
+#include <unistd.h>
+#include <fcntl.h>
+
+#endif
namespace am
{
#define MAX_NS 1000000000L
-#define MAX_TIMERHANDLE INT16_MAX
-#define MAX_POLLHANDLE INT16_MAX
+#define MAX_TIMERHANDLE UINT16_MAX
+#define MAX_POLLHANDLE UINT16_MAX
-typedef uint16_t sh_timerHandle_t; //!<this is a handle for a timer to be used with the SocketHandler
typedef uint16_t sh_pollHandle_t; //!<this is a handle for a filedescriptor to be used with the SocketHandler
+typedef sh_pollHandle_t sh_timerHandle_t; //!<this is a handle for a timer to be used with the SocketHandler
/**
- * prototype for poll prepared callback
- */
+ * prototype for poll prepared callback
+ */
class IAmShPollPrepare
{
public:
virtual void Call(const sh_pollHandle_t handle, void* userData) = 0;
- virtual ~IAmShPollPrepare() {};
+ virtual ~IAmShPollPrepare() {}
};
/**
- * prototype for poll fired callback
- */
+ * prototype for poll fired callback
+ */
class IAmShPollFired
{
public:
virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData) = 0;
- virtual ~ IAmShPollFired() {};
+ virtual ~ IAmShPollFired() {}
};
/**
- * prototype for poll check callback
- */
+ * prototype for poll check callback
+ */
class IAmShPollCheck
{
public:
virtual bool Call(const sh_pollHandle_t handle, void* userData) = 0;
- virtual ~ IAmShPollCheck() {};
+ virtual ~ IAmShPollCheck() {}
};
/**
- * prototype for dispatch callback
- */
+ * prototype for dispatch callback
+ */
class IAmShPollDispatch
{
public:
virtual bool Call(const sh_pollHandle_t handle, void* userData) = 0;
- virtual ~ IAmShPollDispatch() {};
+ virtual ~ IAmShPollDispatch() {}
};
/**
- * prototype for the timer callback
- */
+ * prototype for the timer callback
+ */
class IAmShTimerCallBack
{
public:
+ IAmShTimerCallBack(){};
virtual void Call(const sh_timerHandle_t handle, void* userData) = 0;
- virtual ~IAmShTimerCallBack() {};
+ virtual ~IAmShTimerCallBack(){}
};
-/**
- * The am::CAmSocketHandler implements a mainloop for the AudioManager. Plugins and different parts of the AudioManager add their filedescriptors to the handler
- * to get called on communication of the filedescriptors.\n
- * More information can be found here : \ref mainl
- */
-class CAmSocketHandler
+/**make private, not public
+ * template for a callback
+ */
+template<class TClass> class TAmShPollFired: public IAmShPollFired
{
+private:
+ TClass* mInstance;
+ void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
+
public:
- template<class TClass> class TAmShPollFired: public IAmShPollFired
+ TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) :
+ mInstance(instance), //
+ mFunction(function)
+ {}
+
+ virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
{
- private:
- TClass* mInstance;
- void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
+ (*mInstance.*mFunction)(pollfd, handle, userData);
+ }
+};
- public:
- TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) :
- mInstance(instance), //
- mFunction(function) {};
+/**
+ * template for a callback
+ */
+template<class TClass> class TAmShPollCheck: public IAmShPollCheck
+{
+private:
+ TClass* mInstance;
+ bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
- virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
- {
- (*mInstance.*mFunction)(pollfd, handle, userData);
- };
- };
+public:
+ TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
+ mInstance(instance), //
+ mFunction(function)
+ {}
- template<class TClass> class TAmShPollCheck: public IAmShPollCheck
+ virtual bool Call(const sh_pollHandle_t handle, void* userData)
{
- private:
- TClass* mInstance;
- bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
+ return ((*mInstance.*mFunction)(handle, userData));
+ }
+};
- public:
- TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
- mInstance(instance), //
- mFunction(function) {};
+/**
+ * template for a callback
+ */
+template<class TClass> class TAmShPollDispatch: public IAmShPollDispatch
+{
+private:
+ TClass* mInstance;
+ bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
- virtual bool Call(const sh_pollHandle_t handle, void* userData)
- {
- return ((*mInstance.*mFunction)(handle, userData));
- };
- };
+public:
+ TAmShPollDispatch(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
+ mInstance(instance), //
+ mFunction(function)
+ {}
- CAmSocketHandler();
- ~CAmSocketHandler();
+ virtual bool Call(const sh_pollHandle_t handle, void* userData)
+ {
+ return ((*mInstance.*mFunction)(handle, userData));
+ }
+};
- am_Error_e addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void* userData, sh_pollHandle_t& handle);
- am_Error_e removeFDPoll(const sh_pollHandle_t handle);
- am_Error_e updateEventFlags(const sh_pollHandle_t handle, const short events);
- am_Error_e addTimer(const timespec timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void* userData);
- am_Error_e removeTimer(const sh_timerHandle_t handle);
- am_Error_e restartTimer(const sh_timerHandle_t handle);
- am_Error_e updateTimer(const sh_timerHandle_t handle, const timespec timeouts);
- am_Error_e stopTimer(const sh_timerHandle_t handle);
- void start_listenting();
- void stop_listening();
- void exit_mainloop();
- void receiverCallback(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
- {
- (void) pollfd;
- (void) handle;
- (void) userData;
- };
- bool checkerCallback(const sh_pollHandle_t handle, void* userData)
- {
- (void) handle;
- (void) userData;
- return (false);
- };
+/**
+ * template to create the functor for a class
+ */
+template<class TClass> class TAmShTimerCallBack: public IAmShTimerCallBack
+{
+private:
+ TClass* mInstance;
+ void (TClass::*mFunction)(sh_timerHandle_t handle, void* userData);
- TAmShPollFired<CAmSocketHandler> receiverCallbackT;
- TAmShPollCheck<CAmSocketHandler> checkerCallbackT;
+public:
+ TAmShTimerCallBack(TClass* instance, void (TClass::*function)(sh_timerHandle_t handle, void* userData)) :
+ IAmShTimerCallBack(), mInstance(instance), //
+ mFunction(function)
+ {}
+
+ virtual void Call(sh_timerHandle_t handle, void* userData)
+ {
+ (*mInstance.*mFunction)(handle, userData);
+ }
+};
+/**
+ * template for a callback
+ */
+
+template<class TClass> class TAmShPollPrepare: public IAmShPollPrepare
+{
private:
+ TClass* mInstance;
+ void (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
+
+public:
+ TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
+ mInstance(instance), //
+ mFunction(function)
+ {}
+
+ virtual void Call(const sh_pollHandle_t handle, void* userData)
+ {
+ (*mInstance.*mFunction)(handle, userData);
+ }
+};
+
+/**
+ * The am::CAmSocketHandler implements a mainloop for the AudioManager. Plugins and different parts of the AudioManager add their filedescriptors to the handler
+ * to get called on communication of the filedescriptors.\n
+ * More information can be found here : \ref mainl
+ */
+class CAmSocketHandler
+{
+ struct sh_poll_s //!<struct that holds information about polls
+ {
+ sh_pollHandle_t handle; //!<handle to uniquely adress a filedesriptor
+ pollfd pollfdValue; //!<the array for polling the filedescriptors
+ std::function<void(const sh_pollHandle_t handle, void* userData)> prepareCB; //preperation callback
+ std::function<void(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)> firedCB; //fired callback
+ std::function<bool(const sh_pollHandle_t handle, void* userData)> checkCB; //check callback
+ std::function<bool(const sh_pollHandle_t handle, void* userData)> dispatchCB; //dispatch callback
+ void* userData;
+
+ sh_poll_s() :
+ handle(0), pollfdValue(), prepareCB(), firedCB(), checkCB(), dispatchCB(), userData(0)
+ {}
+ };
- static CAmSocketHandler* mInstance;
- int mPipe[2];
- int mDispatchDone; //this starts / stops the mainloop
struct sh_timer_s //!<struct that holds information of timers
{
- sh_timerHandle_t handle; //!<the handle of the timer
+ sh_timerHandle_t handle; //!<the handle of the timer
+#ifdef WITH_TIMERFD
+ int fd;
+ itimerspec countdown; //!<the countdown, this value is decreased every time the timer is up
+#else
timespec countdown; //!<the countdown, this value is decreased every time the timer is up
- IAmShTimerCallBack* callback; //!<the callbackfunction
- void * userData; //!<saves a void pointer together with the rest.
+#endif
+ std::function<void(const sh_timerHandle_t handle, void* userData)> callback; //timer callback
+ void* userData;
+ sh_timer_s() :
+ handle(0)
+#ifdef WITH_TIMERFD
+ , fd(0)
+#endif
+ , countdown(), callback(), userData(0)
+ {}
};
- typedef std::reverse_iterator<sh_timer_s> rListTimerIter; //!<typedef for reverseiterator on timer lists
-
- struct sh_poll_s //!<struct that holds information about polls
+ struct sh_signal_s
{
sh_pollHandle_t handle; //!<handle to uniquely adress a filedesriptor
- IAmShPollPrepare *prepareCB; //!<pointer to preperation callback
- IAmShPollFired *firedCB; //!<pointer to fired callback
- IAmShPollCheck *checkCB; //!< pointer to check callback
- IAmShPollDispatch *dispatchCB; //!<pointer to dispatch callback
- pollfd pollfdValue; //!<the array for polling the filedescriptors
- void *userData; //!<userdata saved together with the callback.
+ std::function<void(const sh_pollHandle_t handle, const signalfd_siginfo & info, void* userData)> callback;
+ void* userData;
+ sh_signal_s() :
+ handle(0), callback(), userData(0)
+ {}
+ };
+
+ struct sh_identifier_s
+ {
+ std::set<sh_pollHandle_t> pollHandles;
+ uint16_t limit;
+ uint16_t lastUsedID;
+ sh_identifier_s(const uint16_t pollLimit = UINT16_MAX) :
+ pollHandles(), limit(pollLimit), lastUsedID(0)
+ {}
};
- typedef std::vector<pollfd> mListPollfd_t; //!<vector of filedescriptors
- typedef std::vector<sh_poll_s> mListPoll_t; //!<list for the callbacks
+ typedef std::reverse_iterator<sh_timer_s> rListTimerIter; //!<typedef for reverseiterator on timer lists
+ typedef std::vector<pollfd> VectorListPollfd_t; //!<vector of filedescriptors
+ typedef std::vector<sh_poll_s> VectorListPoll_t; //!<list for the callbacks
+ typedef std::vector<sh_signal_s> VectorSignalHandlers_t; //!<list for the callbacks
+
+ typedef enum:uint8_t
+ {
+ NO_ERROR = 0u, // OK
+ PIPE_ERROR = 1u, // Pipe error
+ FD_ERROR = 2u, // Invalid file descriptor
+ SFD_ERROR = 4u,
+ } internal_codes_e;
+ typedef uint8_t internal_codes_t;
+ int mPipe[2];
+ bool mDispatchDone; //this starts / stops the mainloop
+
+ sh_identifier_s mSetPollKeys; //!A set of all used ppoll keys
+ VectorListPoll_t mListPoll; //!<list that holds all information for the ppoll
+ sh_identifier_s mSetTimerKeys; //!A set of all used timer keys
+ std::list<sh_timer_s> mListTimer; //!<list of all timers
+ std::list<sh_timer_s> mListActiveTimer; //!<list of all currently active timers
+ sh_identifier_s mSetSignalhandlerKeys; //!A set of all used signal handler keys
+ VectorSignalHandlers_t mSignalHandlers;
+ bool mRecreatePollfds; //!<when this is true, the poll list needs to be recreated
+ internal_codes_t mInternalCodes;
+ sh_pollHandle_t mSignalFdHandle;
+#ifndef WITH_TIMERFD
+ timespec mStartTime; //!<here the actual time is saved for timecorrection
+#endif
+private:
bool fdIsValid(const int fd) const;
+
+ timespec* insertTime(timespec& buffertime);
+#ifdef WITH_TIMERFD
+ am_Error_e createTimeFD(const itimerspec & timeouts, int & fd);
+
+#else
void timerUp();
void timerCorrection();
- timespec* insertTime(timespec& buffertime);
/**
- * compares countdown values
- * @param a
- * @param b
- * @return true if b greater a
- */
+ * compares countdown values
+ * @param a
+ * @param b
+ * @return true if b greater a
+ */
inline static bool compareCountdown(const sh_timer_s& a, const sh_timer_s& b)
{
return ((a.countdown.tv_sec == b.countdown.tv_sec) ? (a.countdown.tv_nsec < b.countdown.tv_nsec) : (a.countdown.tv_sec < b.countdown.tv_sec));
}
/**
- * Subtracts b from a
- * @param a
- * @param b
- * @return subtracted value
- */
+ * Subtracts b from a
+ * @param a
+ * @param b
+ * @return subtracted value
+ */
inline static timespec timespecSub(const timespec& a, const timespec& b)
{
timespec result;
@@ -234,11 +353,11 @@ private:
}
/**
- * adds timespec values
- * @param a
- * @param b
- * @return the added values
- */
+ * adds timespec values
+ * @param a
+ * @param b
+ * @return the added values
+ */
inline timespec timespecAdd(const timespec& a, const timespec& b)
{
timespec result;
@@ -253,234 +372,123 @@ private:
}
/**
- * comapares timespec values
- * @param a
- * @param b
- * @return
- */
+ * comapares timespec values
+ * @param a
+ * @param b
+ * @return
+ */
inline int timespecCompare(const timespec& a, const timespec& b)
{
//less
if (a.tv_sec < b.tv_sec)
- return (-1);
+ return (-1);
//greater
else if (a.tv_sec > b.tv_sec)
- return (1);
+ return (1);
//less
else if (a.tv_nsec < b.tv_nsec)
- return (-1);
+ return (-1);
//greater
else if (a.tv_nsec > b.tv_nsec)
- return (1);
+ return (1);
//equal
return (0);
}
+#endif
/**
- * functor to return all fired events
- * @param a
- * @return
- */
- inline static bool eventFired(const pollfd& a)
- {
- return (a.revents == 0 ? false : true);
- }
+ * functor to prepare all fire events
+ * @param a
+ * @return
+ */
+ inline static void prepare(sh_poll_s& row);
/**
- * functor to help find the items that do not need dispatching
- * @param a
- * @return
- */
- inline static bool noDispatching(const sh_poll_s& a)
- {
- //remove from list of there is no checkCB
- if (!a.checkCB)
- return (true);
- return (!a.checkCB->Call(a.handle, a.userData));
- }
+ * functor to return all fired events
+ * @param a
+ * @return
+ */
+ inline static void fire(sh_poll_s& a);
/**
- * checks if dispatching is already finished
- * @param a
- * @return
- */
- inline static bool dispatchingFinished(const sh_poll_s& a)
- {
- //remove from list of there is no dispatchCB
- if (!a.dispatchCB)
- return (true);
- return (!a.dispatchCB->Call(a.handle, a.userData));
- }
-
- class CAmShCopyPollfd //!< functor to copy filedescriptors into the poll array
- {
- private:
- mListPollfd_t& mArray;
- public:
- CAmShCopyPollfd(mListPollfd_t& dest) : mArray(dest) {}
- void operator()(const sh_poll_s& row);
- };
-
- class CAmShCallFire //!< functor to call the firecallbacks
- {
- public:
- CAmShCallFire() {};
- void operator()(sh_poll_s& row);
- };
-
- class CAmShCallPrep //!< functor to call the preparation callbacks
- {
- public:
- CAmShCallPrep() {};
- void operator()(sh_poll_s& row);
- };
-
- class CAmShCallTimer //!<functor to call a timer
- {
- public:
- CAmShCallTimer() {};
- void operator()(sh_timer_s& row);
- };
-
- class CAmShCountdownUp //!<functor that checks if a timer is up
- {
- private:
- timespec mDiffTime;
- public:
- CAmShCountdownUp(const timespec& differenceTime) : mDiffTime(differenceTime) {};
- bool operator()(const sh_timer_s& row);
- };
-
- class CAmShCountdownZero //!<functor that checks if a timer is zero
- {
- public:
- CAmShCountdownZero() {};
- bool operator()(const sh_timer_s& row);
- };
-
- class CAmShSubstractTime //!<functor to easy substract from each countdown value
- {
- private:
- timespec param;
- public:
- CAmShSubstractTime(timespec param) : param(param) {}
- inline void operator()(sh_timer_s& t)
- {
- t.countdown = timespecSub(t.countdown, param);
- }
- };
-
- mListPollfd_t mfdPollingArray; //!<the polling array for ppoll
- std::set<sh_pollHandle_t> mSetPollKeys; //!A set of all used ppoll keys
- mListPoll_t mListPoll; //!<list that holds all information for the ppoll
- std::set<sh_timerHandle_t> mSetTimerKeys; //!A set of all used timer keys
- std::list<sh_timer_s> mListTimer; //!<list of all timers
- std::list<sh_timer_s> mListActiveTimer; //!<list of all currently active timers
- sh_timerHandle_t mLastInsertedHandle; //!<keeps track of the last inserted timer handle
- sh_pollHandle_t mLastInsertedPollHandle; //!<keeps track of the last inserted poll handle
- bool mRecreatePollfds; //!<when this is true, the poll list needs to be recreated
- timespec mStartTime; //!<here the actual time is saved for timecorrection
-
-};
-
-/**
- * template to create the functor for a class
- */
-template<class TClass> class TAmShTimerCallBack: public IAmShTimerCallBack
-{
-private:
- TClass* mInstance;
- void (TClass::*mFunction)(sh_timerHandle_t handle, void* userData);
-
-public:
- TAmShTimerCallBack(TClass* instance, void (TClass::*function)(sh_timerHandle_t handle, void* userData)) :
- mInstance(instance), //
- mFunction(function) {};
+ * functor to return all fired events
+ * @param a
+ * @return
+ */
+ inline static bool eventFired(const pollfd& a);
- virtual void Call(sh_timerHandle_t handle, void* userData)
- {
- (*mInstance.*mFunction)(handle, userData);
- }
-};
-
-/**
- * template for a callback
- */
-template<class TClass> class TAmShPollPrepare: public IAmShPollPrepare
-{
-private:
- TClass* mInstance;
- void (TClass::*mFunction)(const sh_timerHandle_t handle, void* userData);
-
-public:
- TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_timerHandle_t handle, void* userData)) :
- mInstance(instance), //
- mFunction(function) {};
+ /**
+ * functor to help find the items that do not need dispatching
+ * @param a
+ * @return
+ */
+ inline static bool noDispatching(const sh_poll_s& a);
- virtual void Call(const sh_timerHandle_t handle, void* userData)
- {
- (*mInstance.*mFunction)(handle, userData);
- };
-};
+ /**
+ * checks if dispatching is already finished
+ * @param a
+ * @return
+ */
+ inline static bool dispatchingFinished(const sh_poll_s& a);
-/**make private, not public
- * template for a callback
- */
-template<class TClass> class TAmShPollFired: public IAmShPollFired
-{
-private:
- TClass* mInstance;
- void (TClass::*mFunction)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
+ /**
+ * timer fire callback
+ * @param a
+ * @return
+ */
+ inline static void callTimer(sh_timer_s& a);
+ /**
+ * next handle id
+ * @param std::set handles
+ * @return handle
+ */
+ bool nextHandle(sh_identifier_s & handle);
+
+ am_Error_e getFDPollData(const sh_pollHandle_t handle, sh_poll_s & outPollData);
+
public:
- TAmShPollFired(TClass* instance, void (TClass::*function)(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)) :
- mInstance(instance), //
- mFunction(function) {};
- virtual void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
- {
- (*mInstance.*mFunction)(pollfd, handle, userData);
- };
-};
-
-/**
- * template for a callback
- */
-template<class TClass> class TAmShPollCheck: public IAmShPollCheck
-{
-private:
- TClass* mInstance;
- bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
-
-public:
- TAmShPollCheck(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
- mInstance(instance), //
- mFunction(function) {};
+ CAmSocketHandler();
+ ~CAmSocketHandler();
+
+ /**
+ * install the signal fd
+ */
+ am_Error_e listenToSignals(const std::vector<uint8_t> & listSignals);
+
+ am_Error_e addFDPoll(const int fd, const short event, std::function<void(const sh_pollHandle_t handle, void* userData)> prepare, std::function<void(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)> fired,
+ std::function<bool(const sh_pollHandle_t handle, void* userData)> check, std::function<bool(const sh_pollHandle_t handle, void* userData)> dispatch, void* userData, sh_pollHandle_t& handle);
- virtual bool Call(const sh_pollHandle_t handle, void* userData)
- {
- return ((*mInstance.*mFunction)(handle, userData));
- };
+ am_Error_e addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void* userData, sh_pollHandle_t& handle);
+ am_Error_e removeFDPoll(const sh_pollHandle_t handle);
+ am_Error_e updateEventFlags(const sh_pollHandle_t handle, const short events);
+ am_Error_e addSignalHandler(std::function<void(const sh_pollHandle_t handle, const signalfd_siginfo & info, void* userData)> callback, sh_pollHandle_t& handle, void * userData);
+ am_Error_e removeSignalHandler(const sh_pollHandle_t handle);
+ am_Error_e addTimer(const timespec & timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void * userData,
+#ifndef WITH_TIMERFD
+ const bool __attribute__((__unused__)) repeats = false
+#else
+ const bool repeats = false
+#endif
+ );
+ am_Error_e addTimer(const timespec & timeouts, std::function<void(const sh_timerHandle_t handle, void* userData)> callback, sh_timerHandle_t& handle, void* userData,
+#ifndef WITH_TIMERFD
+ const bool __attribute__((__unused__)) repeats = false
+#else
+ const bool repeats = false
+#endif
+ );
+ am_Error_e removeTimer(const sh_timerHandle_t handle);
+ am_Error_e restartTimer(const sh_timerHandle_t handle);
+ am_Error_e updateTimer(const sh_timerHandle_t handle, const timespec & timeouts);
+ am_Error_e stopTimer(const sh_timerHandle_t handle);
+ void start_listenting();
+ void stop_listening();
+ void exit_mainloop();
+
+ bool fatalErrorOccurred();
};
-/**
- * template for a callback
- */
-template<class TClass> class TAmShPollDispatch: public IAmShPollDispatch
-{
-private:
- TClass* mInstance;
- bool (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
-
-public:
- TAmShPollDispatch(TClass* instance, bool (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
- mInstance(instance), //
- mFunction(function) {};
-
- virtual bool Call(const sh_pollHandle_t handle, void* userData)
- {
- return ((*mInstance.*mFunction)(handle, userData));
- };
-};
} /* namespace am */
#endif /* SOCKETHANDLER_H_ */
diff --git a/AudioManagerUtilities/src/CAmSocketHandler.cpp b/AudioManagerUtilities/src/CAmSocketHandler.cpp
index 1092198..7b0fc5d 100644
--- a/AudioManagerUtilities/src/CAmSocketHandler.cpp
+++ b/AudioManagerUtilities/src/CAmSocketHandler.cpp
@@ -15,13 +15,13 @@
*
*
* \author Christian Linke, christian.linke@bmw.de BMW 2011,2012
+ * \author Aleksandar Donchev, aleksander.donchev@partner.bmw.de BMW 2017
*
* \file CAmSocketHandler.cpp
* For further information see http://www.genivi.org/.
*
*/
-#include "CAmSocketHandler.h"
#include <cassert>
#include <sys/fcntl.h>
#include <sys/errno.h>
@@ -31,80 +31,111 @@
#include <features.h>
#include <csignal>
#include <unistd.h>
+
#include "CAmDltWrapper.h"
+#include "CAmSocketHandler.h"
+
+#ifdef WITH_TIMERFD
+#include <sys/timerfd.h>
+#endif
namespace am
{
CAmSocketHandler::CAmSocketHandler() :
- receiverCallbackT(this, &CAmSocketHandler::receiverCallback),//
- checkerCallbackT(this, &CAmSocketHandler::checkerCallback),//
mPipe(), //
- mDispatchDone(1),//
- mListPoll(), //
- mListTimer(), //
- mListActiveTimer(), //
- mLastInsertedHandle(0), //
- mLastInsertedPollHandle(0), //
- mRecreatePollfds(true), //
- mStartTime() //
+ mDispatchDone(true), //
+ mSetPollKeys(MAX_POLLHANDLE), //
+ mListPoll(), //
+ mSetTimerKeys(MAX_TIMERHANDLE),
+ mListTimer(), //
+ mListActiveTimer(), //
+ mSetSignalhandlerKeys(MAX_POLLHANDLE), //
+ mSignalHandlers(), //
+ mRecreatePollfds(true),
+ mInternalCodes(internal_codes_e::NO_ERROR),
+ mSignalFdHandle(0)
+#ifndef WITH_TIMERFD
+,mStartTime() //
+#endif
{
if (pipe(mPipe) == -1)
{
+ mInternalCodes = internal_codes_e::PIPE_ERROR;
logError("Sockethandler could not create pipe!");
}
- //add the pipe to the poll - nothing needs to be proccessed here we just need the pipe to trigger the ppoll
+ //add the pipe to the poll - nothing needs to be processed here we just need the pipe to trigger the ppoll
short event = 0;
sh_pollHandle_t handle;
event |= POLLIN;
- addFDPoll(mPipe[0], event, NULL, &receiverCallbackT, &checkerCallbackT, NULL, NULL, handle);
+ if (addFDPoll(mPipe[0], event, NULL, [](const pollfd pollfd, const sh_pollHandle_t, void*)
+ {}, [](const sh_pollHandle_t, void*)
+ { return (false);}, NULL, NULL, handle) != E_OK)
+ mInternalCodes |= internal_codes_e::FD_ERROR;
}
CAmSocketHandler::~CAmSocketHandler()
{
- close(mPipe[0]);
- close(mPipe[1]);
+ for (auto it : mListPoll)
+ {
+ close(it.pollfdValue.fd);
+ }
+ close(mPipe[0]);
+ close(mPipe[1]);
}
//todo: maybe have some: give me more time returned?
/**
- * start the block listening for filedescriptors. This is the mainloop.
- */
+ * start the block listening for filedescriptors. This is the mainloop.
+ */
void CAmSocketHandler::start_listenting()
{
- mDispatchDone = 0;
+ mDispatchDone = false;
int16_t pollStatus;
- //prepare the signalmask
- sigset_t sigmask;
- sigemptyset(&sigmask);
- sigaddset(&sigmask, SIGINT);
- sigaddset(&sigmask, SIGQUIT);
- sigaddset(&sigmask, SIGTERM);
- sigaddset(&sigmask, SIGHUP);
- sigaddset(&sigmask, SIGQUIT);
-
+#ifndef WITH_TIMERFD
clock_gettime(CLOCK_MONOTONIC, &mStartTime);
- while (!mDispatchDone)
+#endif
+ timespec buffertime;
+
+ std::list<sh_poll_s> listPoll;
+ VectorListPoll_t cloneListPoll;
+ VectorListPoll_t::iterator listmPollIt;
+ VectorListPollfd_t::iterator itMfdPollingArray;
+ VectorListPollfd_t fdPollingArray; //!<the polling array for ppoll
+
+ auto preparePollfd = [&](const sh_poll_s& row)
{
- //first we go through the registered filedescriptors and check if someone needs preparation:
- std::for_each(mListPoll.begin(), mListPoll.end(), CAmShCallPrep());
+ CAmSocketHandler::prepare((sh_poll_s&)row);
+ pollfd temp = row.pollfdValue;
+ temp.revents = 0;
+ fdPollingArray.push_back(temp);
+ };
+ while (!mDispatchDone)
+ {
if (mRecreatePollfds)
{
- mfdPollingArray.clear();
+ fdPollingArray.clear();
+ //freeze mListPoll by copying it - otherwise we get problems when we want to manipulate it during the next lines
+ cloneListPoll = mListPoll;
//there was a change in the setup, so we need to recreate the fdarray from the list
- std::for_each(mListPoll.begin(), mListPoll.end(), CAmShCopyPollfd(mfdPollingArray));
+ std::for_each(cloneListPoll.begin(), cloneListPoll.end(), preparePollfd);
mRecreatePollfds = false;
}
+ else
+ {
+ //first we go through the registered filedescriptors and check if someone needs preparation:
+ std::for_each(cloneListPoll.begin(), cloneListPoll.end(), CAmSocketHandler::prepare);
+ }
+#ifndef WITH_TIMERFD
timerCorrection();
-
+#endif
//block until something is on a filedescriptor
- timespec buffertime;
- if ((pollStatus = ppoll(&mfdPollingArray[0], mfdPollingArray.size(), insertTime(buffertime), &sigmask)) < 0)
+ if ((pollStatus = ppoll(&fdPollingArray[0], fdPollingArray.size(), insertTime(buffertime), NULL)) < 0)
{
if (errno == EINTR)
{
@@ -121,112 +152,223 @@ void CAmSocketHandler::start_listenting()
if (pollStatus != 0) //only check filedescriptors if there was a change
{
//todo: here could be a timer that makes sure naughty plugins return!
-
- //freeze mListPoll by copying it - otherwise we get problems when we want to manipulate it during the next lines
- std::list<sh_poll_s> listPoll;
- mListPoll_t::iterator listmPollIt;
-
- //remove all filedescriptors who did not fire
- std::vector<pollfd>::iterator it = mfdPollingArray.begin();
- do
+ listPoll.clear();
+ //stage 0+1, call firedCB
+ for (itMfdPollingArray = fdPollingArray.begin(); itMfdPollingArray != fdPollingArray.end(); itMfdPollingArray++)
{
- it = std::find_if(it, mfdPollingArray.end(), eventFired);
- if (it != mfdPollingArray.end())
- {
- listmPollIt = mListPoll.begin();
- std::advance(listmPollIt, std::distance(mfdPollingArray.begin(), it));
+ if (CAmSocketHandler::eventFired(*itMfdPollingArray))
+ {
+ listmPollIt = cloneListPoll.begin();
+ std::advance(listmPollIt, std::distance(fdPollingArray.begin(), itMfdPollingArray));
+
listPoll.push_back(*listmPollIt);
- listPoll.back().pollfdValue = *it;
- it++;
+ CAmSocketHandler::fire(*listmPollIt);
}
- } while (it != mfdPollingArray.end());
-
- //stage 1, call firedCB
- std::for_each(listPoll.begin(), listPoll.end(), CAmShCallFire());
-
+ }
+
//stage 2, lets ask around if some dispatching is necessary, the ones who need stay on the list
- listPoll.remove_if(noDispatching);
+ listPoll.remove_if(CAmSocketHandler::noDispatching);
//stage 3, the ones left need to dispatch, we do this as long as there is something to dispatch..
do
{
- listPoll.remove_if(dispatchingFinished);
+ listPoll.remove_if(CAmSocketHandler::dispatchingFinished);
} while (!listPoll.empty());
}
+#ifndef WITH_TIMERFD
else //Timerevent
{
//this was a timer event, we need to take care about the timers
+ //find out the timedifference to starttime
timerUp();
}
+#endif
}
}
/**
- * exits the loop
- */
+ * exits the loop
+ */
void CAmSocketHandler::stop_listening()
{
- mDispatchDone = 1;
-
+ mDispatchDone = true;
+#ifndef WITH_TIMERFD
//this is for all running timers only - we need to handle the additional offset here
if (!mListActiveTimer.empty())
{
timespec currentTime, correctionTime;
clock_gettime(CLOCK_MONOTONIC, &currentTime);
correctionTime = timespecSub(currentTime, mStartTime);
- std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), CAmShSubstractTime(correctionTime));
+ std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), [&correctionTime](sh_timer_s& t)
+ { t.countdown = timespecSub(t.countdown, correctionTime);});
}
+#endif
+}
+
+void CAmSocketHandler::exit_mainloop()
+{
+ //end the while loop
+ stop_listening();
+
+ //fire the ending filedescriptor
+ int p(1);
+ ssize_t result = write(mPipe[1], &p, sizeof(p));
+}
+bool CAmSocketHandler::fatalErrorOccurred()
+{
+ return ((mInternalCodes&internal_codes_e::PIPE_ERROR)>0)||((mInternalCodes&internal_codes_e::FD_ERROR)>0);
+}
+
+am_Error_e CAmSocketHandler::getFDPollData(const sh_pollHandle_t handle, sh_poll_s & outPollData)
+{
+ VectorListPoll_t::iterator iterator = mListPoll.begin();
+ for (; iterator != mListPoll.end(); ++iterator)
+ {
+ if (iterator->handle == handle)
+ {
+ outPollData = *iterator;
+ return (E_OK);
+ }
+ }
+ return (E_UNKNOWN);
}
/**
- * Adds a filedescriptor to the polling loop
- * @param fd the filedescriptor
- * @param event the event flags
- * @param prepare a callback that is called before the loop is entered
- * @param fired a callback that is called when the filedescriptor needs to be read
- * @param check a callback that is called to check if further actions are neccessary
- * @param dispatch a callback that is called to dispatch the received data
- * @param userData a pointer to userdata that is always passed around
- * @param handle the handle of this poll
- * @return E_OK if the descriptor was added, E_NON_EXISTENT if the fd is not valid
- */
-am_Error_e CAmSocketHandler::addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void *userData, sh_pollHandle_t & handle)
+ * Adds a signal handler filedescriptor to the polling loop
+ *
+ */
+am_Error_e CAmSocketHandler::listenToSignals(const std::vector<uint8_t> & listSignals)
+{
+ int fdErr;
+ uint8_t addedSignals = 0;
+ sigset_t sigset;
+
+ if(0==listSignals.size())
+ {
+ logWarning("Empty signal list!");
+ return (E_NOT_POSSIBLE);
+ }
+
+ /* Create a sigset of all the signals that we're interested in */
+ fdErr = sigemptyset(&sigset);
+ if (fdErr != 0)
+ {
+ logError("Could not create sigset!");
+ return (E_NOT_POSSIBLE);
+ }
+
+ for(uint8_t itSignal : listSignals)
+ {
+ fdErr = sigaddset(&sigset, itSignal);
+ if (fdErr != 0)
+ logWarning("Could not add", itSignal);
+ else
+ addedSignals++;
+ }
+
+ if(0==addedSignals)
+ {
+ logWarning("None of the signals were added!");
+ return (E_NOT_POSSIBLE);
+ }
+
+ /* We must block the signals in order for signalfd to receive them */
+ fdErr = sigprocmask(SIG_BLOCK, &sigset, NULL);
+ if (fdErr != 0)
+ {
+ logError("Could not block signals! They must be blocked in order to receive them!");
+ return (E_NOT_POSSIBLE);
+ }
+
+ int signalHandlerFd;
+ if(mSignalFdHandle)
+ {
+ sh_poll_s sgPollData;
+ if(E_OK!=getFDPollData(mSignalFdHandle, sgPollData))
+ {
+ removeFDPoll(mSignalFdHandle);
+ mSignalFdHandle = 0;
+ }
+ else
+ {
+ int signalHandlerFd = signalfd(sgPollData.pollfdValue.fd, &sigset, 0);
+ if (signalHandlerFd == -1)
+ {
+ logError("Could not update signal fd!");
+ return (E_NOT_POSSIBLE);
+ }
+ return E_OK;
+ }
+ }
+
+ if(0==mSignalFdHandle)
+ {
+ /* Create the signalfd */
+ signalHandlerFd = signalfd(-1, &sigset, 0);
+ if (signalHandlerFd == -1)
+ {
+ logError("Could not open signal fd!");
+ return (E_NOT_POSSIBLE);
+ }
+
+ auto actionPoll = [this](const pollfd pollfd, const sh_pollHandle_t, void*)
+ {
+ const VectorSignalHandlers_t & signalHandlers = mSignalHandlers;
+ /* We have a valid signal, read the info from the fd */
+ struct signalfd_siginfo info;
+ ssize_t bytes = read(pollfd.fd, &info, sizeof(info));
+ assert(bytes == sizeof(info));
+
+ /* Notify all listeners */
+ for(auto it: signalHandlers)
+ it.callback(it.handle, info, it.userData);
+ };
+ /* We're going to add the signal fd through addFDPoll. At this point we don't have any signal listeners. */
+ am_Error_e shFdError = addFDPoll(signalHandlerFd, POLLIN | POLLERR | POLLHUP, NULL, actionPoll, [](const sh_pollHandle_t, void*)
+ { return (false);}, NULL, NULL, mSignalFdHandle);
+ return shFdError;
+ }
+}
+
+/**
+ * Adds a filedescriptor to the polling loop
+ * @param fd the filedescriptor
+ * @param event the event flags
+ * @param prepare a std::function that is called before the loop is entered
+ * @param fired a std::function that is called when the filedescriptor needs to be read
+ * @param check a std::function that is called to check if further actions are neccessary
+ * @param dispatch a std::function that is called to dispatch the received data
+ * @param userData a pointer to userdata that is always passed around
+ * @param handle the handle of this poll
+ * @return E_OK if the descriptor was added, E_NON_EXISTENT if the fd is not valid
+ */
+
+am_Error_e CAmSocketHandler::addFDPoll(const int fd, const short event, std::function<void(const sh_pollHandle_t handle, void* userData)> prepare,
+ std::function<void(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)> fired, std::function<bool(const sh_pollHandle_t handle, void* userData)> check,
+ std::function<bool(const sh_pollHandle_t handle, void* userData)> dispatch, void* userData, sh_pollHandle_t& handle)
{
if (!fdIsValid(fd))
return (E_NON_EXISTENT);
-
- //create a new handle for the poll
- sh_pollHandle_t lastHandle(mLastInsertedPollHandle);
- do
+
+ //create a new handle for the poll
+ if (!nextHandle(mSetPollKeys))
{
- ++mLastInsertedPollHandle;
- if (mLastInsertedPollHandle == MAX_POLLHANDLE)
- {
- mLastInsertedPollHandle = 1;
- }
- if (mLastInsertedPollHandle==lastHandle)
- {
- logError(__func__,"Could not create new polls, too many open!");
- return (am_Error_e::E_NOT_POSSIBLE);
- }
-
- } while (mSetPollKeys.find(mLastInsertedPollHandle) != mSetPollKeys.end());
-
- mSetPollKeys.insert(mLastInsertedPollHandle);
+ logError("Could not create new polls, too many open!");
+ return (E_NOT_POSSIBLE);
+ }
sh_poll_s pollData;
pollData.pollfdValue.fd = fd;
- pollData.handle = mLastInsertedPollHandle;
+ pollData.handle = mSetPollKeys.lastUsedID;
pollData.pollfdValue.events = event;
pollData.pollfdValue.revents = 0;
- pollData.userData = userData;
pollData.prepareCB = prepare;
pollData.firedCB = fired;
pollData.checkCB = check;
pollData.dispatchCB = dispatch;
-
+ pollData.userData = userData;
//add new data to the list
mListPoll.push_back(pollData);
@@ -234,23 +376,56 @@ am_Error_e CAmSocketHandler::addFDPoll(const int fd, const short event, IAmShPol
handle = pollData.handle;
return (E_OK);
+
}
/**
- * removes a filedescriptor from the poll loop
- * @param handle
- * @return
- */
+ * Adds a filedescriptor to the polling loop
+ * @param fd the filedescriptor
+ * @param event the event flags
+ * @param prepare a callback that is called before the loop is entered
+ * @param fired a callback that is called when the filedescriptor needs to be read
+ * @param check a callback that is called to check if further actions are neccessary
+ * @param dispatch a callback that is called to dispatch the received data
+ * @param userData a pointer to userdata that is always passed around
+ * @param handle the handle of this poll
+ * @return E_OK if the descriptor was added, E_NON_EXISTENT if the fd is not valid
+ */
+am::am_Error_e CAmSocketHandler::addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void *userData, sh_pollHandle_t & handle)
+{
+
+ std::function<void(const sh_pollHandle_t handle, void* userData)> prepareCB; //preperation callback
+ std::function<void(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)> firedCB; //fired callback
+ std::function<bool(const sh_pollHandle_t handle, void* userData)> checkCB; //check callback
+ std::function<bool(const sh_pollHandle_t handle, void* userData)> dispatchCB; //check callback
+
+ if (prepare)
+ prepareCB = std::bind(&IAmShPollPrepare::Call, prepare, std::placeholders::_1, std::placeholders::_2);
+ if (fired)
+ firedCB = std::bind(&IAmShPollFired::Call, fired, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
+ if (check)
+ checkCB = std::bind(&IAmShPollCheck::Call, check, std::placeholders::_1, std::placeholders::_2);
+ if (dispatch)
+ dispatchCB = std::bind(&IAmShPollDispatch::Call, dispatch, std::placeholders::_1, std::placeholders::_2);
+
+ return addFDPoll(fd, event, prepareCB, firedCB, checkCB, dispatchCB, userData, handle);
+}
+
+/**
+ * removes a filedescriptor from the poll loop
+ * @param handle
+ * @return
+ */
am_Error_e CAmSocketHandler::removeFDPoll(const sh_pollHandle_t handle)
{
- mListPoll_t::iterator iterator = mListPoll.begin();
+ VectorListPoll_t::iterator iterator = mListPoll.begin();
for (; iterator != mListPoll.end(); ++iterator)
{
if (iterator->handle == handle)
{
iterator = mListPoll.erase(iterator);
- mSetPollKeys.erase(handle);
+ mSetPollKeys.pollHandles.erase(handle);
mRecreatePollfds = true;
return (E_OK);
}
@@ -259,93 +434,232 @@ am_Error_e CAmSocketHandler::removeFDPoll(const sh_pollHandle_t handle)
}
/**
- * adds a timer to the list of timers. The callback will be fired when the timer is up.
- * This is not a high precise timer, it is very coarse. It is meant to be used for timeouts when waiting
- * for an answer via a filedescriptor.
- * One time timer. If you need again a timer, you need to add a new timer in the callback of the old one.
- * @param timeouts timeouts time until the callback is fired
- * @param callback callback the callback
- * @param handle handle the handle that is created for the timer is returned. Can be used to remove the timer
- * @param userData pointer always passed with the call
- * @return E_OK in case of success
- */
-am_Error_e CAmSocketHandler::addTimer(const timespec timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void * userData)
+ * Adds a callback for any signals
+ * @param callback
+ * @param handle the handle of this poll
+ * @param userData a pointer to userdata that is always passed around
+ * @return E_OK if the descriptor was added, E_NON_EXISTENT if the fd is not valid
+ */
+am_Error_e CAmSocketHandler::addSignalHandler(std::function<void(const sh_pollHandle_t handle, const signalfd_siginfo & info, void* userData)> callback, sh_pollHandle_t& handle, void * userData)
+{
+ if (!nextHandle(mSetSignalhandlerKeys))
+ {
+ logError("Could not create new polls, too many open!");
+ return (E_NOT_POSSIBLE);
+ }
+
+ mSignalHandlers.emplace_back();
+ mSignalHandlers.back().callback = callback;
+ mSignalHandlers.back().handle = mSetSignalhandlerKeys.lastUsedID;
+ mSignalHandlers.back().userData = userData;
+ handle = mSetSignalhandlerKeys.lastUsedID;
+
+ return E_OK;
+}
+
+/**
+ * removes a signal handler from the list
+ * @param handle is signal handler id
+ * @return E_OK in case of success, E_UNKNOWN if the handler was not found.
+ */
+am_Error_e CAmSocketHandler::removeSignalHandler(const sh_pollHandle_t handle)
+{
+ VectorSignalHandlers_t::iterator it(mSignalHandlers.begin());
+ for (; it != mSignalHandlers.end(); ++it)
+ {
+ if (it->handle == handle)
+ {
+ it = mSignalHandlers.erase(it);
+ mSetSignalhandlerKeys.pollHandles.erase(handle);
+ return (E_OK);
+ }
+ }
+ return (E_UNKNOWN);
+}
+
+/**
+ * adds a timer to the list of timers. The callback will be fired when the timer is up.
+ * This is not a high precise timer, it is very coarse. It is meant to be used for timeouts when waiting
+ * for an answer via a filedescriptor.
+ * One time timer. If you need again a timer, you need to add a new timer in the callback of the old one.
+ * @param timeouts timeouts time until the callback is fired
+ * @param callback callback the callback
+ * @param handle handle the handle that is created for the timer is returned. Can be used to remove the timer
+ * @param userData pointer always passed with the call
+ * @return E_OK in case of success
+ */
+
+am_Error_e CAmSocketHandler::addTimer(const timespec & timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void * userData, const bool repeats)
{
- assert(!((timeouts.tv_sec==0) && (timeouts.tv_nsec==0)));
assert(callback!=NULL);
- sh_timer_s timerItem;
+ std::function<void(const sh_timerHandle_t handle, void* userData)> callbackFunc;
+ callbackFunc = std::bind(&IAmShTimerCallBack::Call, callback, std::placeholders::_1, std::placeholders::_2);
+ return addTimer(timeouts, callbackFunc, handle, userData, repeats);
+}
+
+am_Error_e CAmSocketHandler::addTimer(const timespec & timeouts, std::function<void(const sh_timerHandle_t handle, void* userData)> callback, sh_timerHandle_t& handle, void * userData, const bool repeats)
+{
+ assert(!((timeouts.tv_sec == 0) && (timeouts.tv_nsec == 0)));
+
+ mListTimer.emplace_back();
+ sh_timer_s & timerItem = mListTimer.back();
+
+#ifndef WITH_TIMERFD
//create a new handle for the timer
- sh_timerHandle_t lastTimerHandle(mLastInsertedHandle);
- do
+ if (!nextHandle(mSetTimerKeys))
{
- ++mLastInsertedHandle;
- if (mLastInsertedHandle == MAX_TIMERHANDLE)
- {
- mLastInsertedHandle = 1;
- }
- if (lastTimerHandle==mLastInsertedHandle)
- {
- logError(__func__,"Could not create new timers, too many open!");
- return (am_Error_e::E_NOT_POSSIBLE);
- }
-
- } while (mSetTimerKeys.find(mLastInsertedHandle) != mSetTimerKeys.end());
-
- mSetTimerKeys.insert(mLastInsertedHandle);
- handle=mLastInsertedHandle;
- timerItem.handle = handle;
+ logError("Could not create new timers, too many open!");
+ mListTimer.pop_back();
+ return (E_NOT_POSSIBLE);
+ }
+ //create a new handle for the timer
+ handle = mSetTimerKeys.lastUsedID;
+
timerItem.countdown = timeouts;
timerItem.callback = callback;
timerItem.userData = userData;
- mListTimer.push_back(timerItem);
+ timerItem.handle = handle;
//we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection
timespec currentTime;
clock_gettime(CLOCK_MONOTONIC, &currentTime);
- if (!mDispatchDone) //the mainloop is started
- timerItem.countdown = timespecAdd(timeouts, timespecSub(currentTime, mStartTime));
-
+ if (!mDispatchDone)//the mainloop is started
+ timerItem.countdown = timespecAdd(timeouts, timespecSub(currentTime, mStartTime));
+ mListTimer.push_back(timerItem);
mListActiveTimer.push_back(timerItem);
mListActiveTimer.sort(compareCountdown);
return (E_OK);
+
+#else
+ timerItem.countdown.it_value = timeouts;
+ if (repeats)
+ timerItem.countdown.it_interval = timeouts;
+ else
+ {
+ timespec zero;
+ zero.tv_sec = 0;
+ zero.tv_nsec = 0;
+ timerItem.countdown.it_interval = zero;
+ }
+
+ timerItem.fd = -1;
+ timerItem.userData = userData;
+ am_Error_e err = createTimeFD(timerItem.countdown, timerItem.fd);
+ if (err != E_OK)
+ {
+ mListTimer.pop_back();
+ return err;
+ }
+
+ static auto actionPoll = [](const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
+ {
+ uint64_t mExpirations;
+ if (read(pollfd.fd, &mExpirations, sizeof(uint64_t)) == -1)
+ {
+ //error received...try again
+ read(pollfd.fd, &mExpirations, sizeof(uint64_t));
+ }
+ };
+
+ err = addFDPoll(timerItem.fd, POLLIN, NULL, actionPoll, [callback](const sh_pollHandle_t handle, void* userData)->bool
+ {
+ callback(handle, userData);
+ return false;
+ },
+ NULL, userData, handle);
+ if (E_OK == err)
+ {
+ timerItem.handle = handle;
+ }
+ else
+ {
+ mListTimer.pop_back();
+ }
+ return err;
+#endif
+
}
/**
- * removes a timer from the list of timers
- * @param handle the handle to the timer
- * @return E_OK in case of success, E_UNKNOWN if timer was not found.
- */
+ * removes a timer from the list of timers
+ * @param handle the handle to the timer
+ * @return E_OK in case of success, E_UNKNOWN if timer was not found.
+ */
am_Error_e CAmSocketHandler::removeTimer(const sh_timerHandle_t handle)
{
- assert(handle!=0);
+ assert(handle != 0);
//stop the current timer
- stopTimer(handle);
+#ifdef WITH_TIMERFD
+ std::list<sh_timer_s>::iterator it = mListTimer.begin();
+ for (; it != mListTimer.end(); ++it)
+ {
+ if (it->handle == handle)
+ break;
+ }
+ if (it == mListTimer.end())
+ return (E_NON_EXISTENT);
+ close(it->fd);
+ mListTimer.erase(it);
+ return removeFDPoll(handle);
+#else
+ stopTimer(handle);
std::list<sh_timer_s>::iterator it(mListTimer.begin());
for (; it != mListTimer.end(); ++it)
{
if (it->handle == handle)
{
it = mListTimer.erase(it);
- mSetTimerKeys.erase(handle);
+ mSetTimerKeys.pollHandles.erase(handle);
return (E_OK);
}
}
return (E_UNKNOWN);
+#endif
}
/**
- * restarts a timer and updates with a new interva
- * @param handle handle to the timer
- * @param timeouts new timout time
- * @return E_OK on success, E_NON_EXISTENT if the handle was not found
- */
-am_Error_e CAmSocketHandler::updateTimer(const sh_timerHandle_t handle, const timespec timeouts)
+ * restarts a timer and updates with a new interva
+ * @param handle handle to the timer
+ * @param timeouts new timout time
+ * @return E_OK on success, E_NON_EXISTENT if the handle was not found
+ */
+am_Error_e CAmSocketHandler::updateTimer(const sh_timerHandle_t handle, const timespec & timeouts)
{
+#ifdef WITH_TIMERFD
+ std::list<sh_timer_s>::iterator it = mListTimer.begin();
+ for (; it != mListTimer.end(); ++it)
+ {
+ if (it->handle == handle)
+ break;
+ }
+ if (it == mListTimer.end())
+ return (E_NON_EXISTENT);
+
+ if (it->countdown.it_interval.tv_nsec != 0 || it->countdown.it_interval.tv_sec != 0)
+ it->countdown.it_interval = timeouts;
+ it->countdown.it_value = timeouts;
+
+ if (!fdIsValid(it->fd))
+ {
+ am_Error_e err = createTimeFD(it->countdown, it->fd);
+ if (err != E_OK)
+ return err;
+ }
+ else
+ {
+ if (timerfd_settime(it->fd, 0, &it->countdown, NULL))
+ {
+ logError("Failed to set timer duration");
+ return E_NOT_POSSIBLE;
+ }
+ }
+#else
+
//update the mList ....
sh_timer_s timerItem;
std::list<sh_timer_s>::iterator it(mListTimer.begin()), activeIt(mListActiveTimer.begin());
@@ -361,7 +675,7 @@ am_Error_e CAmSocketHandler::updateTimer(const sh_timerHandle_t handle, const ti
}
}
if (!found)
- return (E_NON_EXISTENT);
+ return (E_NON_EXISTENT);
found = false;
@@ -370,8 +684,8 @@ am_Error_e CAmSocketHandler::updateTimer(const sh_timerHandle_t handle, const ti
currentTime.tv_nsec=timeoutsCorrected.tv_nsec=0;
currentTime.tv_sec=timeoutsCorrected.tv_sec=0;
clock_gettime(CLOCK_MONOTONIC, &currentTime);
- if (!mDispatchDone) //the mainloop is started
- timeoutsCorrected = timespecAdd(timeouts, timespecSub(currentTime, mStartTime));
+ if (!mDispatchDone)//the mainloop is started
+ timeoutsCorrected = timespecAdd(timeouts, timespecSub(currentTime, mStartTime));
for (; activeIt != mListActiveTimer.end(); ++activeIt)
{
@@ -384,20 +698,48 @@ am_Error_e CAmSocketHandler::updateTimer(const sh_timerHandle_t handle, const ti
}
if (!found)
- timerItem.countdown = timeoutsCorrected;
+ timerItem.countdown = timeoutsCorrected;
mListActiveTimer.push_back(timerItem);
mListActiveTimer.sort(compareCountdown);
+
+#endif
return (E_OK);
}
/**
- * restarts a timer with the original value
- * @param handle
- * @return E_OK on success, E_NON_EXISTENT if the handle was not found
- */
+ * restarts a timer with the original value
+ * @param handle
+ * @return E_OK on success, E_NON_EXISTENT if the handle was not found
+ */
am_Error_e CAmSocketHandler::restartTimer(const sh_timerHandle_t handle)
{
+#ifdef WITH_TIMERFD
+ std::list<sh_timer_s>::iterator it = mListTimer.begin();
+ for (; it != mListTimer.end(); ++it)
+ {
+ if (it->handle == handle)
+ break;
+ }
+ if (it == mListTimer.end())
+ return (E_NON_EXISTENT);
+
+ if (!fdIsValid(it->fd))
+ {
+ am_Error_e err = createTimeFD(it->countdown, it->fd);
+ if (err != E_OK)
+ return err;
+ }
+ else
+ {
+ if (timerfd_settime(it->fd, 0, &it->countdown, NULL))
+ {
+ logError("Failed to set timer duration");
+ return E_NOT_POSSIBLE;
+ }
+ }
+#else
+
sh_timer_s timerItem; //!<the original timer value
//find the original value
std::list<sh_timer_s>::iterator it(mListTimer.begin()), activeIt(mListActiveTimer.begin());
@@ -412,14 +754,14 @@ am_Error_e CAmSocketHandler::restartTimer(const sh_timerHandle_t handle)
}
}
if (!found)
- return (E_NON_EXISTENT);
+ return (E_NON_EXISTENT);
found = false;
//we add here the time difference between startTime and currenttime, because this time will be substracted later on in timecorrection
timespec currentTime, timeoutsCorrected;
clock_gettime(CLOCK_MONOTONIC, &currentTime);
- if (!mDispatchDone) //the mainloop is started
+ if (!mDispatchDone)//the mainloop is started
{
timeoutsCorrected = timespecAdd(timerItem.countdown, timespecSub(currentTime, mStartTime));
timerItem.countdown = timeoutsCorrected;
@@ -436,20 +778,41 @@ am_Error_e CAmSocketHandler::restartTimer(const sh_timerHandle_t handle)
}
if (!found)
- mListActiveTimer.push_back(timerItem);
+ mListActiveTimer.push_back(timerItem);
mListActiveTimer.sort(compareCountdown);
-
+#endif
return (E_OK);
}
/**
- * stops a timer
- * @param handle
- * @return E_OK on success, E_NON_EXISTENT if the handle was not found
- */
+ * stops a timer
+ * @param handle
+ * @return E_OK on success, E_NON_EXISTENT if the handle was not found
+ */
am_Error_e CAmSocketHandler::stopTimer(const sh_timerHandle_t handle)
{
+#ifdef WITH_TIMERFD
+ std::list<sh_timer_s>::iterator it = mListTimer.begin();
+ for (; it != mListTimer.end(); ++it)
+ {
+ if (it->handle == handle)
+ break;
+ }
+ if (it == mListTimer.end())
+ return (E_NON_EXISTENT);
+
+ itimerspec countdown = it->countdown;
+ countdown.it_value.tv_nsec = 0;
+ countdown.it_value.tv_sec = 0;
+
+ if (timerfd_settime(it->fd, 0, &countdown, NULL))
+ {
+ logError("Failed to set timer duration");
+ return E_NOT_POSSIBLE;
+ }
+ return (E_OK);
+#else
//go through the list and remove the timer with the handle
std::list<sh_timer_s>::iterator it(mListActiveTimer.begin());
for (; it != mListActiveTimer.end(); ++it)
@@ -461,17 +824,18 @@ am_Error_e CAmSocketHandler::stopTimer(const sh_timerHandle_t handle)
}
}
return (E_NON_EXISTENT);
+#endif
}
/**
- * updates the eventFlags of a poll
- * @param handle
- * @param events
- * @return @return E_OK on succsess, E_NON_EXISTENT if fd was not found
- */
+ * updates the eventFlags of a poll
+ * @param handle
+ * @param events
+ * @return @return E_OK on succsess, E_NON_EXISTENT if fd was not found
+ */
am_Error_e CAmSocketHandler::updateEventFlags(const sh_pollHandle_t handle, const short events)
{
- mListPoll_t::iterator iterator = mListPoll.begin();
+ VectorListPoll_t::iterator iterator = mListPoll.begin();
for (; iterator != mListPoll.end(); ++iterator)
{
@@ -486,27 +850,36 @@ am_Error_e CAmSocketHandler::updateEventFlags(const sh_pollHandle_t handle, cons
}
/**
- * checks if a filedescriptor is validCAmShSubstractTime
- * @param fd the filedescriptor
- * @return true if the fd is valid
- */
+ * checks if a filedescriptor is validCAmShSubstractTime
+ * @param fd the filedescriptor
+ * @return true if the fd is valid
+ */
bool CAmSocketHandler::fdIsValid(const int fd) const
{
return (fcntl(fd, F_GETFL) != -1 || errno != EBADF);
}
+#ifndef WITH_TIMERFD
/**
- * timer is up.
- */
+ * timer is up.
+ */
void CAmSocketHandler::timerUp()
{
//find out the timedifference to starttime
- timespec currentTime, diffTime;
+ static timespec currentTime, diffTime;
clock_gettime(CLOCK_MONOTONIC, &currentTime);
diffTime = timespecSub(currentTime, mStartTime);
+ static auto countdownUp = [&](const sh_timer_s& row)->bool
+ {
+ timespec sub = timespecSub(row.countdown, diffTime);
+ if (sub.tv_nsec == 0 && sub.tv_sec == 0)
+ return (true);
+ return (false);
+ };
+
//now we need to substract the diffTime from all timers and see if they are up
- std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), CAmShCountdownUp(diffTime));
+ std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), countdownUp);
//copy all fired timers into a list
std::vector<sh_timer_s> tempList(overflowIter, mListActiveTimer.rend());
@@ -516,28 +889,40 @@ void CAmSocketHandler::timerUp()
mListActiveTimer.erase(mListActiveTimer.begin(), it);
//call the callbacks for the timers
- std::for_each(tempList.begin(), tempList.end(), CAmShCallTimer());
+ std::for_each(tempList.begin(), tempList.end(), CAmSocketHandler::callTimer);
}
/**
- * correct timers and fire the ones who are up
- */
+ * correct timers and fire the ones who are up
+ */
void CAmSocketHandler::timerCorrection()
{
//get the current time and calculate the correction value
- timespec currentTime, correctionTime;
+ static timespec currentTime, correctionTime;
clock_gettime(CLOCK_MONOTONIC, &currentTime);
correctionTime = timespecSub(currentTime, mStartTime);
mStartTime = currentTime;
+ static auto countdownZero = [](const sh_timer_s& row)->bool
+ {
+ if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0)
+ return (true);
+ return (false);
+ };
+
+ static auto substractTime = [&](sh_timer_s& t)
+ {
+ t.countdown = timespecSub(t.countdown, correctionTime);
+ };
+
if (!mListActiveTimer.empty())
{
//subtract the correction value from all items in the list
- std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), CAmShSubstractTime(correctionTime));
+ std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), substractTime);
//find the last occurrence of zero -> timer overflowed
- std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), CAmShCountdownZero());
+ std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), countdownZero);
//only if a timer overflowed
if (overflowIter != mListActiveTimer.rend())
@@ -550,100 +935,146 @@ void CAmSocketHandler::timerCorrection()
mListActiveTimer.erase(mListActiveTimer.begin(), it);
//call the callbacks for the timers
- std::for_each(tempList.begin(), tempList.end(), CAmShCallTimer());
+ std::for_each(tempList.begin(), tempList.end(), CAmSocketHandler::callTimer);
}
}
}
+#endif
-void CAmSocketHandler::exit_mainloop()
+/**
+ * prepare for poll
+ */
+void CAmSocketHandler::prepare(am::CAmSocketHandler::sh_poll_s& row)
{
- //end the while loop
- stop_listening();
+ if (row.prepareCB)
+ {
+ try
+ {
+ row.prepareCB(row.handle, row.userData);
+ } catch (std::exception& e)
+ {
+ logError("Sockethandler: Exception in Preparecallback,caught", e.what());
+ }
+ }
+}
- //fire the ending filedescriptor
- int p(1);
- ssize_t result = write(mPipe[1], &p, sizeof(p));
+/**
+ * fire callback
+ */
+void CAmSocketHandler::fire(sh_poll_s& a)
+{
+ try
+ {
+ a.firedCB(a.pollfdValue, a.handle, a.userData);
+ } catch (std::exception& e)
+ {
+ logError("Sockethandler: Exception in Preparecallback,caught", e.what());
+ }
}
/**
- * is used to set the pointer for the ppoll command
- * @param buffertime
- * @return
- */
+ * should disptach
+ */
+bool CAmSocketHandler::noDispatching(const sh_poll_s& a)
+{
+ //remove from list of there is no checkCB
+ if (nullptr == a.checkCB)
+ return (true);
+ return (!a.checkCB(a.handle, a.userData));
+}
+
+/**
+ * disptach
+ */
+bool CAmSocketHandler::dispatchingFinished(const sh_poll_s& a)
+{
+ //remove from list of there is no dispatchCB
+ if (nullptr == a.dispatchCB)
+ return (true);
+ return (!a.dispatchCB(a.handle, a.userData));
+}
+
+/**
+ * event triggered
+ */
+bool CAmSocketHandler::eventFired(const pollfd& a)
+{
+ return (a.revents == 0 ? false : true);
+}
+
+/**
+ * is used to set the pointer for the ppoll command
+ * @param buffertime
+ * @return
+ */
inline timespec* CAmSocketHandler::insertTime(timespec& buffertime)
{
+#ifndef WITH_TIMERFD
if (!mListActiveTimer.empty())
{
buffertime = mListActiveTimer.front().countdown;
return (&buffertime);
}
else
+#endif
{
return (NULL);
}
}
-void CAmSocketHandler::CAmShCallFire::operator()(sh_poll_s& row)
-{
- try
- {
- row.firedCB->Call(row.pollfdValue, row.handle, row.userData);
- }
- catch (std::exception& e)
- {
- logError("Sockethandler: Exception in FireCallback,caught",e.what());
- }
-}
-
-void CAmSocketHandler::CAmShCallPrep::operator()(sh_poll_s& row)
+#ifdef WITH_TIMERFD
+am_Error_e CAmSocketHandler::createTimeFD(const itimerspec & timeouts, int & fd)
{
- if (row.prepareCB)
- {
- try
- {
- row.prepareCB->Call(row.handle, row.userData);
- }
- catch (std::exception& e)
- {
- logError("Sockethandler: Exception in Preparecallback,caught",e.what());
- }
- }
-}
+ fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
+ if (fd <= 0)
+ {
+ logError("Failed to create timer");
+ return E_NOT_POSSIBLE;
+ }
-void CAmSocketHandler::CAmShCallTimer::operator()(sh_timer_s& row)
-{
- try
- {
- row.callback->Call(row.handle, row.userData);
- }
- catch (std::exception& e)
- {
- logError("Sockethandler: Exception in Timercallback,caught",e.what());
- }
+ if (timerfd_settime(fd, 0, &timeouts, NULL))
+ {
+ logError("Failed to set timer duration");
+ return E_NOT_POSSIBLE;
+ }
+ return E_OK;
}
+#endif
-void CAmSocketHandler::CAmShCopyPollfd::operator()(const sh_poll_s& row)
+void CAmSocketHandler::callTimer(sh_timer_s& a)
{
- pollfd temp = row.pollfdValue;
- temp.revents = 0;
- mArray.push_back(temp);
+ try
+ {
+ a.callback(a.handle, a.userData);
+ } catch (std::exception& e)
+ {
+ logError("Sockethandler: Exception in Timercallback,caught", e.what());
+ }
}
-bool CAmSocketHandler::CAmShCountdownUp::operator()(const sh_timer_s& row)
+bool CAmSocketHandler::nextHandle(sh_identifier_s & handle)
{
- timespec sub = timespecSub(row.countdown, mDiffTime);
- if (sub.tv_nsec == 0 && sub.tv_sec == 0)
- return (true);
- return (false);
-}
+ //create a new handle for the poll
+ const sh_pollHandle_t lastHandle(handle.lastUsedID);
+ do
+ {
+ ++handle.lastUsedID;
+ if (handle.lastUsedID == handle.limit)
+ {
+ handle.lastUsedID = 1;
+ }
+ if (handle.lastUsedID == lastHandle)
+ {
+ logError("Could not create new polls, too many open!");
+ return (false);
+ }
-bool CAmSocketHandler::CAmShCountdownZero::operator()(const sh_timer_s& row)
-{
- if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0)
- return (true);
- return (false);
-}
+ } while (handle.pollHandles.find(handle.lastUsedID) != handle.pollHandles.end());
+ handle.pollHandles.insert(handle.lastUsedID);
+
+ return (true);
+}
}
diff --git a/AudioManagerUtilities/test/AmSerializerTest/CAmSerializerTest.cpp b/AudioManagerUtilities/test/AmSerializerTest/CAmSerializerTest.cpp
new file mode 100644
index 0000000..49c6738
--- /dev/null
+++ b/AudioManagerUtilities/test/AmSerializerTest/CAmSerializerTest.cpp
@@ -0,0 +1,207 @@
+/**
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2012, BMW AG
+ *
+ * This file is part of GENIVI Project AudioManager.
+ *
+ * Contributions are licensed to the GENIVI Alliance under one or more
+ * Contribution License Agreements.
+ *
+ * \copyright
+ * 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/.
+ *
+ *
+ * \author Christian Linke, christian.linke@bmw.de BMW 2011,2012
+ *
+ * For further information see http://www.genivi.org/.
+ *
+ */
+
+#include <cstdio>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <sys/un.h>
+#include <sys/poll.h>
+
+#include "CAmSocketHandler.h"
+#include "CAmSerializer.h"
+#include "CAmSerializerTest.h"
+
+using namespace testing;
+using namespace am;
+
+CAmTimerSockethandlerController::CAmTimerSockethandlerController(CAmSocketHandler *myHandler, const timespec &timeout) :
+ MockIAmTimerCb(), mpSocketHandler(myHandler), mUpdateTimeout(timeout), pTimerCallback(this, &CAmTimerSockethandlerController::timerCallback)
+{
+}
+
+am::CAmTimerSockethandlerController::~CAmTimerSockethandlerController()
+{
+}
+
+void am::CAmTimerSockethandlerController::timerCallback(sh_timerHandle_t handle, void* userData)
+{
+ MockIAmTimerCb::timerCallback(handle, userData);
+ mpSocketHandler->stop_listening();
+}
+
+CAmSerializerTest::CAmSerializerTest()
+{
+}
+
+CAmSerializerTest::~CAmSerializerTest()
+{
+}
+
+void CAmSerializerTest::SetUp()
+{
+
+}
+
+void CAmSerializerTest::TearDown()
+{
+}
+
+struct SerializerData
+{
+
+ std::string testStr;
+ int result;
+ MockIAmSerializerCb *pSerCb;
+ CAmSocketHandler *pSocketHandler;
+ V2::CAmSerializer *pSerializer;
+};
+
+void* ptSerializerSync(void* data)
+{
+ SerializerData *pData = (SerializerData*) data;
+ std::string testStr(pData->testStr);
+ bool result = false;
+ int r = 0;
+ const uint32_t ten = 10;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ pData->pSerializer->syncCall(pData->pSerCb, &MockIAmSerializerCb::check);
+ pData->pSerializer->syncCall(pData->pSerCb, &MockIAmSerializerCb::checkInt, pData->result);
+ pData->pSerializer->syncCall(pData->pSerCb, &MockIAmSerializerCb::dispatchData, result, ten, pData->testStr);
+#pragma GCC diagnostic pop
+ return (NULL);
+}
+
+void* ptSerializerASync(void* data)
+{
+ SerializerData *pData = (SerializerData*) data;
+ std::string testStr;
+ bool result = false;
+ int r = 0;
+ const uint32_t ten = 10;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ for (uint32_t i = 0; i < 5; i++)
+ {
+ testStr = pData->testStr;
+ pData->pSerializer->asyncCall(pData->pSerCb, &MockIAmSerializerCb::dispatchData, i, testStr);
+ }
+ pData->testStr = testStr;
+ pData->pSerializer->asyncInvocation(std::bind([]()->bool
+ { return 1;}));
+ pData->pSerializer->asyncInvocation(std::bind([](const int i, int & result)
+ { result = i*10;}, 1, std::ref(r)));
+
+ pData->pSerializer->asyncCall(pData->pSerCb, &MockIAmSerializerCb::check);
+ pData->pSerializer->asyncCall(pData->pSerCb, &MockIAmSerializerCb::check);
+
+ pData->pSerializer->asyncCall(pData->pSerCb, &MockIAmSerializerCb::checkInt);
+
+#pragma GCC diagnostic pop
+ return (NULL);
+}
+
+ACTION(ActionDispatchData){
+arg1="DispatchData";
+}
+
+TEST(CAmSerializerTest, syncTest)
+{
+ pthread_t serThread;
+
+ MockIAmSerializerCb serCb;
+ CAmSocketHandler myHandler;
+ std::string testStr("testStr");
+ V2::CAmSerializer serializer(&myHandler);
+ sh_timerHandle_t handle;
+ timespec timeout4;
+ timeout4.tv_nsec = 0;
+ timeout4.tv_sec = 3;
+ CAmTimerSockethandlerController testCallback4(&myHandler, timeout4);
+ myHandler.addTimer(timeout4, &testCallback4.pTimerCallback, handle, NULL);
+ EXPECT_CALL(testCallback4,timerCallback(handle,NULL)).Times(1);
+
+ SerializerData serializerData;
+ serializerData.result = 0;
+ serializerData.testStr = testStr;
+ serializerData.pSerCb = &serCb;
+ serializerData.pSocketHandler = &myHandler;
+ serializerData.pSerializer = &serializer;
+ pthread_create(&serThread, NULL, ptSerializerSync, &serializerData);
+
+ EXPECT_CALL(serCb,check()).Times(1);
+ EXPECT_CALL(serCb,checkInt()).Times(1).WillRepeatedly(Return(100));
+ EXPECT_CALL(serCb,dispatchData(10,testStr)).Times(1).WillRepeatedly(DoAll(ActionDispatchData(), Return(true)));
+
+ myHandler.start_listenting();
+
+ pthread_join(serThread, NULL);
+ ASSERT_TRUE(serializerData.testStr == "DispatchData");
+ ASSERT_TRUE(serializerData.result == 100);
+}
+
+TEST(CAmSerializerTest, asyncTest)
+{
+ pthread_t serThread;
+
+ MockIAmSerializerCb serCb;
+ CAmSocketHandler myHandler;
+ std::string testStr("testStr");
+ V2::CAmSerializer serializer(&myHandler);
+ sh_timerHandle_t handle;
+ timespec timeout4;
+ timeout4.tv_nsec = 0;
+ timeout4.tv_sec = 3;
+ CAmTimerSockethandlerController testCallback4(&myHandler, timeout4);
+ myHandler.addTimer(timeout4, &testCallback4.pTimerCallback, handle, NULL);
+ EXPECT_CALL(testCallback4,timerCallback(handle,NULL)).Times(1);
+
+ SerializerData serializerData;
+ serializerData.result = 0;
+ serializerData.testStr = testStr;
+ serializerData.pSerCb = &serCb;
+ serializerData.pSocketHandler = &myHandler;
+ serializerData.pSerializer = &serializer;
+ pthread_create(&serThread, NULL, ptSerializerASync, &serializerData);
+
+ EXPECT_CALL(serCb,check()).Times(2);
+ EXPECT_CALL(serCb,checkInt()).Times(1).WillRepeatedly(Return(100));
+ for (int i = 0; i < 5; i++)
+ EXPECT_CALL(serCb,dispatchData(i,testStr)).WillOnce(DoAll(ActionDispatchData(), Return(true)));
+
+ myHandler.start_listenting();
+
+ pthread_join(serThread, NULL);
+}
+
+int main(int argc, char **argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+
diff --git a/AudioManagerUtilities/test/AmSerializerTest/CAmSerializerTest.h b/AudioManagerUtilities/test/AmSerializerTest/CAmSerializerTest.h
new file mode 100644
index 0000000..8ae3737
--- /dev/null
+++ b/AudioManagerUtilities/test/AmSerializerTest/CAmSerializerTest.h
@@ -0,0 +1,99 @@
+/**
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2012, BMW AG
+ *
+ * This file is part of GENIVI Project AudioManager.
+ *
+ * Contributions are licensed to the GENIVI Alliance under one or more
+ * Contribution License Agreements.
+ *
+ * \copyright
+ * 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/.
+ *
+ *
+ * \author Christian Linke, christian.linke@bmw.de BMW 2011,2012
+ *
+ * For further information see http://www.genivi.org/.
+ *
+ */
+
+#ifndef SERIALIZERTEST_H_
+#define SERIALIZERTEST_H_
+
+#define WITH_DLT
+
+#include <ctime>
+#include <chrono>
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+#include <queue>
+#include "CAmSocketHandler.h"
+
+namespace am
+{
+
+ class IAmSerializerCb
+ {
+ public:
+ virtual ~IAmSerializerCb()
+ {
+ }
+ virtual bool dispatchData(const uint32_t handle, std::string & outString)=0;
+ virtual void check()=0;
+ virtual int checkInt()=0;
+ };
+
+ class IAmTimerCb
+ {
+ public:
+ virtual ~IAmTimerCb()
+ {
+ }
+ virtual void timerCallback(sh_timerHandle_t handle, void * userData)=0;
+ };
+
+ class MockIAmTimerCb: public IAmTimerCb
+ {
+ public:
+ MOCK_CONST_METHOD2(timerCallback,
+ void(sh_timerHandle_t handle, void *userData));
+ };
+
+ class CAmTimerSockethandlerController: public MockIAmTimerCb
+ {
+ CAmSocketHandler *mpSocketHandler;
+ timespec mUpdateTimeout;
+ public:
+ explicit CAmTimerSockethandlerController(CAmSocketHandler *SocketHandler, const timespec &timeout);
+ virtual ~CAmTimerSockethandlerController();
+
+ void timerCallback(sh_timerHandle_t handle, void * userData);
+
+ TAmShTimerCallBack<CAmTimerSockethandlerController> pTimerCallback;
+ };
+
+ class MockIAmSerializerCb: public IAmSerializerCb
+ {
+ public:
+ MOCK_METHOD2(dispatchData,
+ bool(const uint32_t handle, std::string & outString));
+ MOCK_METHOD0(check,
+ void());
+ MOCK_METHOD0(checkInt,
+ int());
+ };
+
+ class CAmSerializerTest: public ::testing::Test
+ {
+ public:
+ CAmSerializerTest();
+ ~CAmSerializerTest();
+ void SetUp();
+ void TearDown();
+ };
+
+} /* namespace am */
+#endif /* SOCKETHANDLERTEST_H_ */
diff --git a/AudioManagerUtilities/test/AmSerializerTest/CMakeLists.txt b/AudioManagerUtilities/test/AmSerializerTest/CMakeLists.txt
new file mode 100644
index 0000000..e0d2287
--- /dev/null
+++ b/AudioManagerUtilities/test/AmSerializerTest/CMakeLists.txt
@@ -0,0 +1,48 @@
+# Copyright (C) 2012, BMW AG
+#
+# This file is part of GENIVI Project AudioManager.
+#
+# Contributions are licensed to the GENIVI Alliance under one or more
+# Contribution License Agreements.
+#
+# copyright
+# 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/.
+#
+# author Christian Linke, christian.linke@bmw.de BMW 2011,2012
+#
+# For further information see http://www.genivi.org/.
+#
+
+cmake_minimum_required(VERSION 3.0)
+
+project(AmSerializerTest LANGUAGES CXX VERSION ${DAEMONVERSION})
+
+INCLUDE_DIRECTORIES(
+ ${AUDIOMANAGER_UTILITIES_INCLUDE}
+ ${GMOCK_INCLUDE_DIRS}
+ ${GTEST_INCLUDE_DIRS})
+
+file(GLOB Socket_SRCS_CXX
+ "*.cpp"
+)
+
+ADD_EXECUTABLE(AmSerializerTest ${Socket_SRCS_CXX})
+
+TARGET_LINK_LIBRARIES(AmSerializerTest
+ ${GTEST_LIBRARIES}
+ ${GMOCK_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT}
+ AudioManagerUtilities
+)
+
+ADD_DEPENDENCIES(AmSerializerTest AudioManagerUtilities)
+
+INSTALL(TARGETS AmSerializerTest
+ DESTINATION ${TEST_EXECUTABLE_INSTALL_PATH}
+ PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ
+ COMPONENT tests
+)
+
+
diff --git a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp
index 50e2aa9..ecd38fe 100644
--- a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp
+++ b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp
@@ -30,6 +30,7 @@
#include <fcntl.h>
#include <sys/un.h>
#include <sys/poll.h>
+
#include "CAmSocketHandler.h"
//todo: expand test, implement more usecases
@@ -37,9 +38,32 @@
#define SOCK_PATH "/tmp/mysock"
+#define SOCKET_TEST_LOOPS_COUNT 1000
+
using namespace testing;
using namespace am;
+static const char * TEST_SOCKET_DATA = "Got It?";
+static const char * TEST_SOCKET_DATA_FINAL = "finish!";
+
+static const std::chrono::time_point<std::chrono::high_resolution_clock> TP_ZERO;
+
+
+MockIAmSignalHandler *pMockSignalHandler = NULL;
+static void signalHandler(int sig, siginfo_t *siginfo, void *context)
+{
+ (void) sig;
+ (void) siginfo;
+ (void) context;
+
+ if(pMockSignalHandler!=NULL)
+ pMockSignalHandler->signalHandler(sig, siginfo, context);
+
+#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT
+ std::cout<<"signal handler was called with signal " << sig << std::endl;
+#endif
+}
+
CAmSocketHandlerTest::CAmSocketHandlerTest()
{
}
@@ -48,106 +72,425 @@ CAmSocketHandlerTest::~CAmSocketHandlerTest()
{
}
-CAmTimerCb::CAmTimerCb(CAmSocketHandler *myHandler) :
- pTimer1Callback(this, &CAmTimerCb::timer1Callback), //
- pTimer2Callback(this, &CAmTimerCb::timer2Callback), //
- pTimer3Callback(this, &CAmTimerCb::timer3Callback), //
- pTimer4Callback(this, &CAmTimerCb::timer4Callback), //
- mSocketHandler(myHandler)
+void CAmSocketHandlerTest::SetUp()
+{
+
+}
+void CAmSocketHandlerTest::TearDown()
{
}
-am::CAmTimerCb::~CAmTimerCb()
+CAmTimerSockethandlerController::CAmTimerSockethandlerController(CAmSocketHandler *myHandler, const timespec &timeout) :
+ MockIAmTimerCb(), mpSocketHandler(myHandler), mUpdateTimeout(timeout), pTimerCallback(this, &CAmTimerSockethandlerController::timerCallback)
{
}
-void am::CAmTimerCb::timer1Callback(sh_timerHandle_t handle, void* userData)
+am::CAmTimerSockethandlerController::~CAmTimerSockethandlerController()
{
- (void) handle;
- (void) userData;
- std::cout << "callback1 called" << std::endl;
- timespec timeout;
- timeout.tv_nsec = 0;
- timeout.tv_sec = 1;
- mSocketHandler->updateTimer(handle,timeout);
}
-void am::CAmTimerCb::timer2Callback(sh_timerHandle_t handle, void* userData)
+void am::CAmTimerSockethandlerController::timerCallback(sh_timerHandle_t handle, void* userData)
{
- (void) handle;
- (void) userData;
- std::cout << "callback2 called" << std::endl;
- timespec timeout;
- timeout.tv_nsec = 011110000;
- timeout.tv_sec = 1;
- mSocketHandler->updateTimer(handle,timeout);
+ MockIAmTimerCb::timerCallback(handle, userData);
+ mpSocketHandler->stop_listening();
}
-void am::CAmTimerCb::timer3Callback(sh_timerHandle_t, void* userData)
+CAmTimerSignalHandler::CAmTimerSignalHandler(CAmSocketHandler *myHandler, const timespec &timeout, const std::set<unsigned> & signals) :
+ MockIAmTimerCb(), mIndex(0), mSignals(signals), mpSocketHandler(myHandler), mUpdateTimeout(timeout), pTimerCallback(this, &CAmTimerSignalHandler::timerCallback)
{
- (void) userData;
- std::cout << "callback3 called" << std::endl;
+
}
-void am::CAmTimerCb::timer4Callback(sh_timerHandle_t, void* userData)
+am::CAmTimerSignalHandler::~CAmTimerSignalHandler()
{
- (void) userData;
- std::cout << "callback4 called" << std::endl;
- mSocketHandler->stop_listening();
+}
+
+void am::CAmTimerSignalHandler::timerCallback(sh_timerHandle_t handle, void* userData)
+{
+ MockIAmTimerCb::timerCallback(handle, userData);
+ if(mIndex<mSignals.size())
+ {
+ std::set<unsigned>::iterator it = mSignals.begin();
+ std::advance(it, mIndex);
+ kill(getpid(), *it);
+ mIndex++;
+
+#ifndef WITH_TIMERFD
+ mpSocketHandler->updateTimer( handle, mUpdateTimeout);
+#endif
+ }
+ else
+ mpSocketHandler->stop_listening();
+
+}
+
+CAmTimer::CAmTimer(CAmSocketHandler *myHandler, const timespec &timeout, const int32_t repeats) :
+ MockIAmTimerCb(), mpSocketHandler(myHandler), mUpdateTimeout(timeout), pTimerCallback(this, &CAmTimer::timerCallback), mRepeats(repeats)
+{
+}
+
+am::CAmTimer::~CAmTimer()
+{
+}
+
+void am::CAmTimer::timerCallback(sh_timerHandle_t handle, void* userData)
+{
+ MockIAmTimerCb::timerCallback(handle, userData);
+ if (--mRepeats > 0)
+ {
+#ifndef WITH_TIMERFD
+ mpSocketHandler->updateTimer( handle, mUpdateTimeout);
+#endif
+ }
+ else
+ {
+ mpSocketHandler->stopTimer(handle);
+ }
+}
+
+CAmTimerMeasurment::CAmTimerMeasurment(CAmSocketHandler *myHandler, const timespec &timeout, const std::string & label, const int32_t repeats, void * userData) :
+ MockIAmTimerCb(), pTimerCallback(this, &CAmTimerMeasurment::timerCallback), //
+ mSocketHandler(myHandler), mUpdateTimeout(timeout), mUpdateTimePoint(std::chrono::seconds
+ { mUpdateTimeout.tv_sec } + std::chrono::nanoseconds
+ { mUpdateTimeout.tv_nsec }), mLastInvocationTime(), mExpected(mUpdateTimePoint - TP_ZERO), mRepeats(repeats), mpUserData(userData), mDebugText(label)
+{
+}
+
+am::CAmTimerMeasurment::~CAmTimerMeasurment()
+{
+}
+
+void am::CAmTimerMeasurment::timerCallback(sh_timerHandle_t handle, void* userData)
+{
+ MockIAmTimerCb::timerCallback(handle, userData);
+
+ std::chrono::time_point<std::chrono::high_resolution_clock> t_end = std::chrono::high_resolution_clock::now();
+ if (TP_ZERO != mLastInvocationTime)
+ {
+ auto durationLast = t_end - mLastInvocationTime;
+ double diff = (std::chrono::duration<double, std::milli>(mExpected - durationLast).count());
+
+#ifdef ENABLED_TIMERS_TEST_OUTPUT
+ std::cout << mDebugText <<
+ " [ expected:" <<std::chrono::duration<double, std::milli>(mExpected).count() << "ms"
+ " , current:" << std::chrono::duration<double, std::milli>(durationLast).count() << "ms"
+ ", diff:" << diff << "ms ] " <<
+ std::endl;
+#endif
+ if (diff > TIMERS_CB_TOLERANCE)
+ std::cout << mDebugText << " Warning [ expected:" << std::chrono::duration<double, std::milli>(mExpected).count() << "ms, current:" << std::chrono::duration<double, std::milli>(durationLast).count() << "ms ]" << std::endl;
+ if (diff < -TIMERS_CB_TOLERANCE)
+ std::cout << mDebugText << " Warning [ expected:" << std::chrono::duration<double, std::milli>(mExpected).count() << "ms, current:" << std::chrono::duration<double, std::milli>(durationLast).count() << "ms ]" << std::endl;
+
+ mLastInvocationTime = t_end;
+ if (--mRepeats > 0)
+ {
+#ifndef WITH_TIMERFD
+ mSocketHandler->updateTimer( handle, mUpdateTimeout);
+#endif
+ }
+ else
+ {
+ mSocketHandler->stopTimer(handle);
+ }
+ }
+ else
+ {
+#ifdef ENABLED_TIMERS_TEST_OUTPUT
+ std::cout << mDebugText << " Init measurment " << std::endl;
+#endif
+ mLastInvocationTime = t_end;
+ mSocketHandler->updateTimer(handle, mUpdateTimeout);
+ }
+
}
void* playWithSocketServer(void* data)
{
- (void) data;
- CAmSocketHandler myHandler;
- CAmSamplePlugin::sockType_e type = CAmSamplePlugin::INET;
- CAmSamplePlugin myplugin(&myHandler, type);
- myHandler.start_listenting();
+ CAmSocketHandler *pSockethandler = (CAmSocketHandler*) data;
+ pSockethandler->start_listenting();
return (NULL);
}
void* playWithUnixSocketServer(void* data)
{
- (void) data;
+ CAmSocketHandler *pSockethandler = (CAmSocketHandler*) data;
+ pSockethandler->start_listenting();
+ return (NULL);
+}
+
+TEST(CAmSocketHandlerTest, timersOneshot)
+{
CAmSocketHandler myHandler;
- CAmSamplePlugin::sockType_e type = CAmSamplePlugin::UNIX;
- CAmSamplePlugin myplugin(&myHandler, type);
+ ASSERT_FALSE(myHandler.fatalErrorOccurred());
+ timespec timeoutTime;
+ timeoutTime.tv_sec = 1;
+ timeoutTime.tv_nsec = 0;
+ CAmTimer testCallback1(&myHandler, timeoutTime);
+
+ struct TestUserData
+ {
+ int i;
+ float f;
+ };
+ TestUserData userData;
+ userData.i = 1;
+ userData.f = 1.f;
+
+ sh_timerHandle_t handle;
+ myHandler.addTimer(timeoutTime, &testCallback1.pTimerCallback, handle, &userData);
+#ifndef WITH_TIMERFD
+ ASSERT_EQ(handle, 1);
+#else
+ ASSERT_EQ(handle, 2);
+#endif
+ EXPECT_CALL(testCallback1,timerCallback(handle,&userData)).Times(1);
+
+ timespec timeout4;
+ timeout4.tv_nsec = 0;
+ timeout4.tv_sec = 3;
+ CAmTimerSockethandlerController testCallback4(&myHandler, timeout4);
+
+ myHandler.addTimer(timeout4, &testCallback4.pTimerCallback, handle, NULL);
+#ifndef WITH_TIMERFD
+ ASSERT_EQ(handle, 2);
+#else
+ ASSERT_EQ(handle, 3);
+#endif
+ EXPECT_CALL(testCallback4,timerCallback(handle,NULL)).Times(1);
+ myHandler.start_listenting();
+}
+
+TEST(CAmSocketHandlerTest, timersStop)
+{
+ CAmSocketHandler myHandler;
+ ASSERT_FALSE(myHandler.fatalErrorOccurred());
+ timespec timeoutTime;
+ timeoutTime.tv_sec = 1;
+ timeoutTime.tv_nsec = 0;
+ CAmTimer testCallback1(&myHandler, timeoutTime, 4);
+
+ struct TestUserData
+ {
+ int i;
+ float f;
+ };
+ TestUserData userData;
+ userData.i = 1;
+ userData.f = 1.f;
+
+ sh_timerHandle_t handle;
+ myHandler.addTimer(timeoutTime, &testCallback1.pTimerCallback, handle, &userData, true);
+#ifndef WITH_TIMERFD
+ ASSERT_EQ(handle, 1);
+#else
+ ASSERT_EQ(handle, 2);
+#endif
+ EXPECT_CALL(testCallback1,timerCallback(handle,&userData)).Times(4);
+
+ timespec timeout4;
+ timeout4.tv_nsec = 0;
+ timeout4.tv_sec = 6;
+ CAmTimerSockethandlerController testCallback4(&myHandler, timeout4);
+
+ myHandler.addTimer(timeout4, &testCallback4.pTimerCallback, handle, NULL);
+#ifndef WITH_TIMERFD
+ ASSERT_EQ(handle, 2);
+#else
+ ASSERT_EQ(handle, 3);
+#endif
+ EXPECT_CALL(testCallback4,timerCallback(handle,NULL)).Times(1);
+ myHandler.start_listenting();
+}
+
+TEST(CAmSocketHandlerTest, timersGeneral)
+{
+ CAmSocketHandler myHandler;
+ ASSERT_FALSE(myHandler.fatalErrorOccurred());
+
+ timespec timeoutTime;
+ timeoutTime.tv_sec = 1;
+ timeoutTime.tv_nsec = 0;
+ CAmTimer testCallback1(&myHandler, timeoutTime, 4);
+
+ struct TestUserData
+ {
+ int i;
+ float f;
+ };
+ TestUserData userData;
+ userData.i = 1;
+ userData.f = 1.f;
+
+ sh_timerHandle_t handle;
+ myHandler.addTimer(timeoutTime, &testCallback1.pTimerCallback, handle, &userData, true);
+#ifndef WITH_TIMERFD
+ ASSERT_EQ(handle, 1);
+#else
+ ASSERT_EQ(handle, 2);
+#endif
+ EXPECT_CALL(testCallback1,timerCallback(handle,&userData)).Times(4); //+1 because of measurment
+
+ timespec timeout4;
+ timeout4.tv_nsec = 0;
+ timeout4.tv_sec = 5;
+ CAmTimerSockethandlerController testCallback4(&myHandler, timeout4);
+
+ myHandler.addTimer(timeout4, &testCallback4.pTimerCallback, handle, NULL);
+#ifndef WITH_TIMERFD
+ ASSERT_EQ(handle, 2);
+#else
+ ASSERT_EQ(handle, 3);
+#endif
+ EXPECT_CALL(testCallback4,timerCallback(handle,NULL)).Times(1);
myHandler.start_listenting();
- return (NULL);
}
TEST(CAmSocketHandlerTest,playWithTimers)
{
CAmSocketHandler myHandler;
- CAmTimerCb testCallback(&myHandler);
+ ASSERT_FALSE(myHandler.fatalErrorOccurred());
timespec timeoutTime, timeout2, timeout3, timeout4;
timeoutTime.tv_sec = 1;
- timeoutTime.tv_nsec = 02223234;
- timeout2.tv_nsec = 333000;
+ timeoutTime.tv_nsec = 34000000;
+ CAmTimerMeasurment testCallback1(&myHandler, timeoutTime, "repeatedCallback 1", std::numeric_limits<int32_t>::max());
+
+ timeout2.tv_nsec = 2000000;
timeout2.tv_sec = 0;
- timeout3.tv_nsec = 333;
+ CAmTimerMeasurment testCallback2(&myHandler, timeout2, "repeatedCallback 2", std::numeric_limits<int32_t>::max());
+
+ timeout3.tv_nsec = 333000000;
timeout3.tv_sec = 3;
+ CAmTimerMeasurment testCallback3(&myHandler, timeout3, "oneshotCallback 3");
timeout4.tv_nsec = 0;
- timeout4.tv_sec = 20;
+ timeout4.tv_sec = 8;
+ CAmTimerSockethandlerController testCallback4(&myHandler, timeout4);
+
sh_timerHandle_t handle;
- myHandler.addTimer(timeoutTime, &testCallback.pTimer1Callback, handle, NULL);
- myHandler.addTimer(timeout2, &testCallback.pTimer2Callback, handle, NULL);
- myHandler.addTimer(timeout3, &testCallback.pTimer3Callback, handle, NULL);
- myHandler.addTimer(timeout4, &testCallback.pTimer4Callback, handle, NULL);
- myHandler.start_listenting();
+ myHandler.addTimer(timeoutTime, &testCallback1.pTimerCallback, handle, NULL, true);
+#ifndef WITH_TIMERFD
+ ASSERT_EQ(handle, 1);
+#else
+ ASSERT_EQ(handle, 2);
+#endif
+ EXPECT_CALL(testCallback1,timerCallback(handle,NULL)).Times(AnyNumber());
+
+ myHandler.addTimer(timeout2, &testCallback2.pTimerCallback, handle, NULL, true);
+#ifndef WITH_TIMERFD
+ ASSERT_EQ(handle, 2);
+#else
+ ASSERT_EQ(handle, 3);
+#endif
+ EXPECT_CALL(testCallback2,timerCallback(handle,NULL)).Times(AnyNumber());
+
+ myHandler.addTimer(timeout3, &testCallback3.pTimerCallback, handle, NULL);
+#ifndef WITH_TIMERFD
+ ASSERT_EQ(handle, 3);
+#else
+ ASSERT_EQ(handle, 4);
+#endif
+ EXPECT_CALL(testCallback3,timerCallback(handle,NULL)).Times(2); //+1 because of measurment
+
+ myHandler.addTimer(timeout4, &testCallback4.pTimerCallback, handle, NULL);
+#ifndef WITH_TIMERFD
+ ASSERT_EQ(handle, 4);
+#else
+ ASSERT_EQ(handle, 5);
+#endif
+ EXPECT_CALL(testCallback4,timerCallback(handle,NULL)).Times(1);
+ myHandler.start_listenting();
}
+
+TEST(CAmSocketHandlerTest, signalHandlerPrimaryPlusSecondary)
+{
+ pMockSignalHandler = new MockIAmSignalHandler;
+ CAmSocketHandler myHandler;
+ ASSERT_FALSE(myHandler.fatalErrorOccurred());
+ ASSERT_TRUE(myHandler.listenToSignals({SIGHUP})==E_OK);
+ ASSERT_TRUE(myHandler.listenToSignals({SIGHUP, SIGTERM, SIGCHLD})==E_OK);
+ sh_pollHandle_t signalHandler1, signalHandler2;
+
+ std::string userData = "User data";
+
+// critical signals are registered here:
+ struct sigaction signalAction;
+ memset(&signalAction, '\0', sizeof(signalAction));
+ signalAction.sa_sigaction = &signalHandler;
+ signalAction.sa_flags = SA_RESETHAND | SA_NODEFER| SA_SIGINFO;
+ sigaction(SIGINT, &signalAction, NULL);
+ sigaction(SIGQUIT, &signalAction, NULL);
+
+ myHandler.addSignalHandler([&](const sh_pollHandle_t handle, const signalfd_siginfo & info, void* userData)
+ {
+ unsigned sig = info.ssi_signo;
+ pMockSignalHandler->signalHandlerAction(handle, sig, userData);
+#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT
+ unsigned user = info.ssi_uid;
+ std::cout<<"signal handler was called from user "<< user << " with signal " << sig << std::endl;
+#endif
+ }, signalHandler1, &userData);
+ ASSERT_EQ(signalHandler1, 1);
+ myHandler.addSignalHandler([&](const sh_pollHandle_t handle, const signalfd_siginfo & info, void* userData)
+ {
+ unsigned sig = info.ssi_signo;
+ pMockSignalHandler->signalHandlerAction(handle, sig, userData);
+#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT
+ unsigned user = info.ssi_uid;
+ std::cout<<"signal handler was called from user "<< user << " with signal " << sig << std::endl;
+#endif
+ }, signalHandler2, &userData);
+ ASSERT_EQ(signalHandler2, 2);
+ timespec timeout4;
+ timeout4.tv_nsec = 200000000;
+ timeout4.tv_sec = 0;
+ std::set<unsigned> secondarySignals;
+ secondarySignals.insert({SIGHUP,SIGTERM, SIGCHLD});
+ std::set<unsigned> primarySignals({SIGQUIT,SIGINT});
+ std::set<unsigned> signals(primarySignals);
+ signals.insert(secondarySignals.begin(), secondarySignals.end());
+
+ CAmTimerSignalHandler testCallback4(&myHandler, timeout4, signals);
+ sh_timerHandle_t handle;
+
+ myHandler.addTimer(timeout4, &testCallback4.pTimerCallback, handle, NULL, true);
+#ifndef WITH_TIMERFD
+ ASSERT_EQ(handle, 1);
+#else
+ ASSERT_EQ(handle, 3);
+#endif
+ EXPECT_CALL(testCallback4,timerCallback(handle,NULL)).Times(signals.size()+1);
+ for(auto it: secondarySignals)
+ EXPECT_CALL(*pMockSignalHandler,signalHandlerAction(signalHandler1,it,&userData)).Times(1);
+ for(auto it: secondarySignals)
+ EXPECT_CALL(*pMockSignalHandler,signalHandlerAction(signalHandler2,it,&userData)).Times(1);
+ for(auto it: primarySignals)
+ EXPECT_CALL(*pMockSignalHandler,signalHandler(it,_,_)).Times(1);
+
+ myHandler.start_listenting();
+ delete pMockSignalHandler;
+}
+
TEST(CAmSocketHandlerTest,playWithUNIXSockets)
{
pthread_t serverThread;
struct sockaddr_un servAddr;
int socket_;
+ CAmSocketHandler myHandler;
+ ASSERT_FALSE(myHandler.fatalErrorOccurred());
+ CAmSamplePlugin::sockType_e type = CAmSamplePlugin::UNIX;
+ CAmSamplePlugin myplugin(&myHandler, type);
+
+ EXPECT_CALL(myplugin,receiveData(_,_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1);
+ EXPECT_CALL(myplugin,dispatchData(_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1);
+ EXPECT_CALL(myplugin,check(_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1);
+
//creates a thread that handles the serverpart
- pthread_create(&serverThread, NULL, playWithUnixSocketServer, NULL);
+ pthread_create(&serverThread, NULL, playWithUnixSocketServer, &myHandler);
sleep(1); //we need that here because the port needs to be opened
if ((socket_ = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
@@ -164,15 +507,16 @@ TEST(CAmSocketHandlerTest,playWithUNIXSockets)
std::cout << "ERROR: connect() failed\n" << std::endl;
}
- for (int i = 0; i <= 1000; i++)
+ for (int i = 1; i <= SOCKET_TEST_LOOPS_COUNT; i++)
{
- std::string string("Got It?");
- send(socket_, string.c_str(), string.size(), 0);
+ std::string stringToSend(TEST_SOCKET_DATA);
+ send(socket_, stringToSend.c_str(), stringToSend.size(), 0);
}
- std::string string("finish!");
- send(socket_, string.c_str(), string.size(), 0);
+ std::string stringToSend(TEST_SOCKET_DATA_FINAL);
+ send(socket_, stringToSend.c_str(), stringToSend.size(), 0);
pthread_join(serverThread, NULL);
+
}
TEST(CAmSocketHandlerTest,playWithSockets)
@@ -183,8 +527,17 @@ TEST(CAmSocketHandlerTest,playWithSockets)
struct hostent *host;
int socket_;
+ CAmSocketHandler myHandler;
+ ASSERT_FALSE(myHandler.fatalErrorOccurred());
+ CAmSamplePlugin::sockType_e type = CAmSamplePlugin::INET;
+ CAmSamplePlugin myplugin(&myHandler, type);
+
+ EXPECT_CALL(myplugin,receiveData(_,_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1);
+ EXPECT_CALL(myplugin,dispatchData(_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1);
+ EXPECT_CALL(myplugin,check(_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1);
+
//creates a thread that handles the serverpart
- pthread_create(&serverThread, NULL, playWithSocketServer, NULL);
+ pthread_create(&serverThread, NULL, playWithSocketServer, &myHandler);
sleep(1); //we need that here because the port needs to be opened
if ((socket_ = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
@@ -209,24 +562,16 @@ TEST(CAmSocketHandlerTest,playWithSockets)
std::cout << "ERROR: connect() failed\n" << std::endl;
}
- for (int i = 0; i <= 1000; i++)
+ for (int i = 1; i <= SOCKET_TEST_LOOPS_COUNT; i++)
{
- std::string string("Got It?");
+ std::string string(TEST_SOCKET_DATA);
send(socket_, string.c_str(), string.size(), 0);
}
- std::string string("finish!");
+ std::string string(TEST_SOCKET_DATA_FINAL);
send(socket_, string.c_str(), string.size(), 0);
pthread_join(serverThread, NULL);
-}
-
-
-void CAmSocketHandlerTest::SetUp()
-{
-}
-void CAmSocketHandlerTest::TearDown()
-{
}
int main(int argc, char **argv)
@@ -236,14 +581,14 @@ int main(int argc, char **argv)
}
am::CAmSamplePlugin::CAmSamplePlugin(CAmSocketHandler *mySocketHandler, sockType_e socketType) :
- connectFiredCB(this, &CAmSamplePlugin::connectSocket), //
+ MockSocketHandlerCb(), connectFiredCB(this, &CAmSamplePlugin::connectSocket), //
receiveFiredCB(this, &CAmSamplePlugin::receiveData), //
sampleDispatchCB(this, &CAmSamplePlugin::dispatchData), //
sampleCheckCB(this, &CAmSamplePlugin::check), //
mSocketHandler(mySocketHandler), //
mConnecthandle(), //
- mReceiveHandle(), //
- msgList()
+ mReceiveHandle(), //
+ msgList()
{
int yes = 1;
@@ -254,29 +599,31 @@ am::CAmSamplePlugin::CAmSamplePlugin(CAmSocketHandler *mySocketHandler, sockType
switch (socketType)
{
- case UNIX:
- socketHandle = socket(AF_UNIX, SOCK_STREAM, 0);
- unixAddr.sun_family = AF_UNIX;
- strcpy(unixAddr.sun_path, SOCK_PATH);
- unlink(unixAddr.sun_path);
- bind(socketHandle, (struct sockaddr *) &unixAddr, strlen(unixAddr.sun_path) + sizeof(unixAddr.sun_family));
- break;
- case INET:
- socketHandle = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
- setsockopt(socketHandle, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
- memset(&servAddr, 0, sizeof(servAddr));
- servAddr.sin_family = AF_INET;
- servAddr.sin_addr.s_addr = INADDR_ANY;
- servAddr.sin_port = htons(servPort);
- bind(socketHandle, (struct sockaddr *) &servAddr, sizeof(servAddr));
- break;
- default:
- break;
+ case UNIX:
+ socketHandle = socket(AF_UNIX, SOCK_STREAM, 0);
+ unixAddr.sun_family = AF_UNIX;
+ strcpy(unixAddr.sun_path, SOCK_PATH);
+ unlink(unixAddr.sun_path);
+ bind(socketHandle, (struct sockaddr *) &unixAddr, strlen(unixAddr.sun_path) + sizeof(unixAddr.sun_family));
+ break;
+ case INET:
+ socketHandle = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ setsockopt(socketHandle, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
+ memset(&servAddr, 0, sizeof(servAddr));
+ servAddr.sin_family = AF_INET;
+ servAddr.sin_addr.s_addr = INADDR_ANY;
+ servAddr.sin_port = htons(servPort);
+ bind(socketHandle, (struct sockaddr *) &servAddr, sizeof(servAddr));
+ break;
+ default:
+ break;
}
if (listen(socketHandle, 3) < 0)
{
+#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT
std::cout << "listen ok" << std::endl;
+#endif
} /* if */
int a = 1;
@@ -286,7 +633,9 @@ am::CAmSamplePlugin::CAmSamplePlugin(CAmSocketHandler *mySocketHandler, sockType
short events = 0;
events |= POLLIN;
mySocketHandler->addFDPoll(socketHandle, events, NULL, &connectFiredCB, NULL, NULL, NULL, mConnecthandle);
+#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT
std::cout << "setup server - listening" << std::endl;
+#endif
}
void am::CAmSamplePlugin::connectSocket(const pollfd pollfd1, const sh_pollHandle_t handle, void *userData)
@@ -294,7 +643,9 @@ void am::CAmSamplePlugin::connectSocket(const pollfd pollfd1, const sh_pollHandl
(void) handle;
(void) userData;
//first, accept the connection, create a new filedescriptor
+#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT
std::cout << "Got a connection request !" << std::endl;
+#endif
struct sockaddr answer;
socklen_t len = sizeof(answer);
int receiveFD = accept(pollfd1.fd, (struct sockaddr*) &answer, &len);
@@ -312,6 +663,7 @@ void am::CAmSamplePlugin::receiveData(const pollfd pollfd, const sh_pollHandle_t
{
(void) handle;
(void) userData;
+ MockSocketHandlerCb::receiveData(pollfd, handle, userData);
//initialize buffer
char buffer[10];
//read until buffer is full or no more data is there
@@ -321,7 +673,9 @@ void am::CAmSamplePlugin::receiveData(const pollfd pollfd, const sh_pollHandle_t
//read the message and store it in a queue
std::string msg = std::string(buffer, read);
msgList.push(msg);
+#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT
std::cout << "Got a message !" << std::endl;
+#endif
}
}
@@ -330,13 +684,20 @@ bool am::CAmSamplePlugin::dispatchData(const sh_pollHandle_t handle, void *userD
(void) handle;
(void) userData;
//read data from the queue
+ MockSocketHandlerCb::dispatchData(handle, userData);
+#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT
std::cout << "Data:" << msgList.front() << std::endl;
-
+#endif
//if the message was our finish message, we quit the poll loop
- if (msgList.front().compare("finish!") == 0)
+ if (!(msgList.front().compare(TEST_SOCKET_DATA_FINAL) == 0 || msgList.front().compare(TEST_SOCKET_DATA) == 0)) //error
{
mSocketHandler->stop_listening();
}
+ if (msgList.front().compare(TEST_SOCKET_DATA_FINAL) == 0) //ok
+ {
+ mSocketHandler->stop_listening();
+ }
+
//remove the message from the queue and return false if there is no more message to read.
msgList.pop();
if (msgList.size() != 0)
@@ -348,8 +709,11 @@ bool am::CAmSamplePlugin::check(const sh_pollHandle_t handle, void *userData)
{
(void) handle;
(void) userData;
+ MockSocketHandlerCb::check(handle, userData);
//checks if there is data to dispatch
+#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT
std::cout << "check!:" << std::endl;
+#endif
if (msgList.size() != 0)
return true;
return false;
diff --git a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h
index 95e5446..ba2bf51 100644
--- a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h
+++ b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h
@@ -25,63 +25,169 @@
#define WITH_DLT
+#include <ctime>
+#include <chrono>
#include "gtest/gtest.h"
+#include "gmock/gmock.h"
#include <queue>
#include "CAmSocketHandler.h"
+#undef ENABLED_SOCKETHANDLER_TEST_OUTPUT
+#undef ENABLED_TIMERS_TEST_OUTPUT
+#define TIMERS_CB_TOLERANCE 8.f
+
namespace am
{
+ class IAmTimerCb
+ {
+ public:
+ virtual ~IAmTimerCb()
+ {
+ }
+ virtual void timerCallback(sh_timerHandle_t handle, void * userData)=0;
+ };
-class CAmSamplePlugin
-{
-public:
- enum sockType_e
+ class IAmSignalHandler
{
- UNIX, INET
+ public:
+ virtual ~IAmSignalHandler()
+ {
+ }
+ virtual void signalHandlerAction(const sh_pollHandle_t handle, const unsigned sig, void* userData)=0;
+ virtual void signalHandler(int sig, siginfo_t *siginfo, void *context)=0;
};
- CAmSamplePlugin(CAmSocketHandler *mySocketHandler, sockType_e socketType);
- ~CAmSamplePlugin()
+
+ class IAmSocketHandlerCb
{
- }
- ;
- void connectSocket(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
- void receiveData(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
- bool dispatchData(const sh_pollHandle_t handle, void* userData);
- bool check(const sh_pollHandle_t handle, void* userData);
- TAmShPollFired<CAmSamplePlugin> connectFiredCB;
- TAmShPollFired<CAmSamplePlugin> receiveFiredCB;
- TAmShPollDispatch<CAmSamplePlugin> sampleDispatchCB;
- TAmShPollCheck<CAmSamplePlugin> sampleCheckCB;
-private:
- CAmSocketHandler *mSocketHandler;
- sh_pollHandle_t mConnecthandle, mReceiveHandle;
- std::queue<std::string> msgList;
-};
-
-class CAmTimerCb
-{
-public:
- CAmTimerCb(CAmSocketHandler *SocketHandler);
- virtual ~CAmTimerCb();
- void timer1Callback(sh_timerHandle_t handle, void * userData);
- void timer2Callback(sh_timerHandle_t handle, void * userData);
- void timer3Callback(sh_timerHandle_t handle, void * userData);
- void timer4Callback(sh_timerHandle_t handle, void * userData);
- TAmShTimerCallBack<CAmTimerCb> pTimer1Callback;
- TAmShTimerCallBack<CAmTimerCb> pTimer2Callback;
- TAmShTimerCallBack<CAmTimerCb> pTimer3Callback;
- TAmShTimerCallBack<CAmTimerCb> pTimer4Callback;
- CAmSocketHandler *mSocketHandler;
-};
-
-class CAmSocketHandlerTest: public ::testing::Test
-{
-public:
- CAmSocketHandlerTest();
- ~CAmSocketHandlerTest();
- void SetUp();
- void TearDown();
-};
+ public:
+ virtual ~IAmSocketHandlerCb()
+ {
+ }
+ virtual void receiveData(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)=0;
+ virtual bool dispatchData(const sh_pollHandle_t handle, void* userData)=0;
+ virtual bool check(const sh_pollHandle_t handle, void* userData)=0;
+ };
+
+ class MockIAmTimerCb: public IAmTimerCb
+ {
+ public:
+ MOCK_CONST_METHOD2(timerCallback,
+ void(sh_timerHandle_t handle, void *userData));
+ };
+
+ class MockIAmSignalHandler: public IAmSignalHandler
+ {
+ public:
+ MOCK_METHOD3(signalHandlerAction, void (const sh_pollHandle_t handle, const unsigned sig, void* userData));
+ MOCK_METHOD3(signalHandler, void(int sig, siginfo_t *siginfo, void *context));
+ };
+
+ class MockSocketHandlerCb: public IAmSocketHandlerCb
+ {
+ public:
+ MOCK_CONST_METHOD3(receiveData,
+ void(const pollfd pollfd, const sh_pollHandle_t handle, void* userData));
+ MOCK_CONST_METHOD2(dispatchData,
+ void(const sh_pollHandle_t handle, void* userData));
+ MOCK_CONST_METHOD2(check,
+ void(const sh_pollHandle_t handle, void* userData));
+ };
+
+ class CAmSamplePlugin: public MockSocketHandlerCb
+ {
+ public:
+ enum sockType_e
+ {
+ UNIX, INET
+ };
+ CAmSamplePlugin(CAmSocketHandler *mySocketHandler, sockType_e socketType);
+ ~CAmSamplePlugin()
+ {
+ }
+ ;
+ void connectSocket(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
+ void receiveData(const pollfd pollfd, const sh_pollHandle_t handle, void* userData);
+ bool dispatchData(const sh_pollHandle_t handle, void* userData);
+ bool check(const sh_pollHandle_t handle, void* userData);
+ TAmShPollFired<CAmSamplePlugin> connectFiredCB;
+ TAmShPollFired<CAmSamplePlugin> receiveFiredCB;
+ TAmShPollDispatch<CAmSamplePlugin> sampleDispatchCB;
+ TAmShPollCheck<CAmSamplePlugin> sampleCheckCB;
+
+ private:
+ CAmSocketHandler *mSocketHandler;
+ sh_pollHandle_t mConnecthandle, mReceiveHandle;
+ std::queue<std::string> msgList;
+ };
+
+ class CAmTimerSockethandlerController: public MockIAmTimerCb
+ {
+ CAmSocketHandler *mpSocketHandler;
+ timespec mUpdateTimeout;
+ public:
+ explicit CAmTimerSockethandlerController(CAmSocketHandler *SocketHandler, const timespec &timeout);
+ virtual ~CAmTimerSockethandlerController();
+
+ void timerCallback(sh_timerHandle_t handle, void * userData);
+
+ TAmShTimerCallBack<CAmTimerSockethandlerController> pTimerCallback;
+ };
+
+ class CAmTimerSignalHandler: public MockIAmTimerCb
+ {
+ unsigned mIndex;
+ std::set<unsigned> mSignals;
+ CAmSocketHandler *mpSocketHandler;
+ timespec mUpdateTimeout;
+ public:
+ explicit CAmTimerSignalHandler(CAmSocketHandler *SocketHandler, const timespec &timeout, const std::set<unsigned> & signals);
+ virtual ~CAmTimerSignalHandler();
+
+ void timerCallback(sh_timerHandle_t handle, void * userData);
+
+ TAmShTimerCallBack<CAmTimerSignalHandler> pTimerCallback;
+ };
+
+ class CAmTimer: public MockIAmTimerCb
+ {
+ CAmSocketHandler *mpSocketHandler;
+ timespec mUpdateTimeout;
+ int32_t mRepeats;
+ public:
+ explicit CAmTimer(CAmSocketHandler *SocketHandler, const timespec &timeout, const int32_t repeats = 0u);
+ virtual ~CAmTimer();
+
+ void timerCallback(sh_timerHandle_t handle, void * userData);
+
+ TAmShTimerCallBack<CAmTimer> pTimerCallback;
+ };
+
+ class CAmTimerMeasurment: public MockIAmTimerCb
+ {
+ CAmSocketHandler *mSocketHandler;
+ timespec mUpdateTimeout;
+ std::chrono::time_point<std::chrono::high_resolution_clock> mUpdateTimePoint;
+ std::chrono::time_point<std::chrono::high_resolution_clock> mLastInvocationTime;
+ std::chrono::duration<long, std::ratio<1l, 1000000000l>> mExpected;
+ int32_t mRepeats;
+ void * mpUserData;
+ std::string mDebugText;
+ public:
+ explicit CAmTimerMeasurment(CAmSocketHandler *SocketHandler, const timespec &timeout, const std::string & label, const int32_t repeats = 0u, void * userData = NULL);
+ virtual ~CAmTimerMeasurment();
+
+ void timerCallback(sh_timerHandle_t handle, void * userData);
+ TAmShTimerCallBack<CAmTimerMeasurment> pTimerCallback;
+ };
+
+ class CAmSocketHandlerTest: public ::testing::Test
+ {
+ public:
+ CAmSocketHandlerTest();
+ ~CAmSocketHandlerTest();
+ void SetUp();
+ void TearDown();
+ };
} /* namespace am */
#endif /* SOCKETHANDLERTEST_H_ */
diff --git a/AudioManagerUtilities/test/AmSocketHandlerTest/CMakeLists.txt b/AudioManagerUtilities/test/AmSocketHandlerTest/CMakeLists.txt
index 8f0c9e6..5e5b9e1 100644
--- a/AudioManagerUtilities/test/AmSocketHandlerTest/CMakeLists.txt
+++ b/AudioManagerUtilities/test/AmSocketHandlerTest/CMakeLists.txt
@@ -33,6 +33,7 @@ ADD_EXECUTABLE(AmSocketHandlerTest ${Socket_SRCS_CXX})
TARGET_LINK_LIBRARIES(AmSocketHandlerTest
${GTEST_LIBRARIES}
${GMOCK_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT}
AudioManagerUtilities
)
diff --git a/AudioManagerUtilities/test/CMakeLists.txt b/AudioManagerUtilities/test/CMakeLists.txt
index fb55831..414e199 100644
--- a/AudioManagerUtilities/test/CMakeLists.txt
+++ b/AudioManagerUtilities/test/CMakeLists.txt
@@ -1,4 +1,2 @@
add_subdirectory (AmSocketHandlerTest)
-
-
-
+add_subdirectory (AmSerializerTest)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 33433ee..5c70c61 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -59,7 +59,10 @@ option ( WITH_SHARED_UTILITIES
option ( WITH_SHARED_CORE
"Build audio manager core as dynamic library" OFF)
-
+
+option ( WITH_TIMERFD
+ "Build with the linux specific TIMERFD feature to support timing without using signals" ON)
+
set(DBUS_SERVICE_PREFIX "org.genivi.audiomanager"
CACHE PROPERTY "The dbus service prefix for the AM - only changable for legacy dbus")
@@ -138,6 +141,7 @@ if(WITH_TESTS)
#check if we can find the google stuff
pkg_check_modules (GTEST "gtest >= 1.6.0")
pkg_check_modules (GMOCK "gmock >= 1.6.0")
+ find_package (Threads)
if (NOT("${GTEST_FOUND}" AND "${GMOCK_FOUND}"))
message (STATUS "Building and installing with shipped sources")
add_subdirectory(googleMock)
@@ -219,6 +223,7 @@ message(STATUS "WITH_CAPI_WRAPPER = ${WITH_CAPI_WRAPPER}")
message(STATUS "WITH_DBUS_WRAPPER = ${WITH_DBUS_WRAPPER}")
message(STATUS "WITH_SHARED_UTILITIES = ${WITH_SHARED_UTILITIES}")
message(STATUS "WITH_SHARED_CORE = ${WITH_SHARED_CORE}")
+message(STATUS "WITH_TIMERFD = ${WITH_TIMERFD}")
message(STATUS "DYNAMIC_ID_BOUNDARY = ${DYNAMIC_ID_BOUNDARY}")
message(STATUS "LIB_INSTALL_SUFFIX = ${LIB_INSTALL_SUFFIX}")
message(STATUS "TEST_EXECUTABLE_INSTALL_PATH = ${TEST_EXECUTABLE_INSTALL_PATH}")
diff --git a/cmake/AudioManagerUtilitiesConfig.cmake.in b/cmake/AudioManagerUtilitiesConfig.cmake.in
index acca825..11ebf55 100644
--- a/cmake/AudioManagerUtilitiesConfig.cmake.in
+++ b/cmake/AudioManagerUtilitiesConfig.cmake.in
@@ -7,6 +7,7 @@ set(WITH_CAPI_WRAPPER "@WITH_CAPI_WRAPPER@")
set(WITH_DBUS_WRAPPER "@WITH_DBUS_WRAPPER@")
set(WITH_SYSTEMD_WATCHDOG "@WITH_SYSTEMD_WATCHDOG@")
set(WITH_DLT "@WITH_DLT@")
+set(WITH_TIMERFD "@WITH_TIMERFD@")
if(WITH_SYSTEMD_WATCHDOG)
diff --git a/cmake/config.cmake.in b/cmake/config.cmake.in
index da64732..1501393 100644
--- a/cmake/config.cmake.in
+++ b/cmake/config.cmake.in
@@ -9,6 +9,7 @@
#cmakedefine WITH_TELNET
#cmakedefine GLIB_DBUS_TYPES_TOLERANT
#cmakedefine WITH_SYSTEMD_WATCHDOG
+#cmakedefine WITH_TIMERFD
#cmakedefine DEFAULT_PLUGIN_DIR "@DEFAULT_PLUGIN_DIR@"
#cmakedefine DEFAULT_PLUGIN_COMMAND_DIR "@DEFAULT_PLUGIN_COMMAND_DIR@"
diff --git a/docs/main_8cpp_source.html b/docs/main_8cpp_source.html
index 9b9df41..0c55aa5 100644
--- a/docs/main_8cpp_source.html
+++ b/docs/main_8cpp_source.html
@@ -279,7 +279,7 @@ $(document).ready(function(){initNavTree('main_8cpp_source.html','');});
<div class="line"><a name="l00204"></a><span class="lineno"> 204</span>&#160; <span class="keywordflow">switch</span> (sig)</div>
<div class="line"><a name="l00205"></a><span class="lineno"> 205</span>&#160; {</div>
<div class="line"><a name="l00206"></a><span class="lineno"> 206</span>&#160; <span class="comment">/*ctl +c lets call direct controllerRundown, because we might be blocked at the moment.</span></div>
-<div class="line"><a name="l00207"></a><span class="lineno"> 207</span>&#160;<span class="comment"> But there is the risk of interrupting something important */</span>https:<span class="comment">//asc.bmwgroup.net/wiki/display/MGUROTO/Lastest+and+greatest</span></div>
+<div class="line"><a name="l00207"></a><span class="lineno"> 207</span>&#160;<span class="comment"> But there is the risk of interrupting something important */</span></div>
<div class="line"><a name="l00208"></a><span class="lineno"> 208</span>&#160; <span class="keywordflow">case</span> SIGINT:</div>
<div class="line"><a name="l00209"></a><span class="lineno"> 209</span>&#160; <a class="code" href="classam_1_1CAmControlSender.html#a347a2af727aeb11657f145329dd23dd8">CAmControlSender::CallsetControllerRundown</a>(sig);</div>
<div class="line"><a name="l00210"></a><span class="lineno"> 210</span>&#160; <span class="keywordflow">break</span>;</div>