forked from Kistler-Group/sdbus-cpp
Add stress tests for sdbus-c++
This commit is contained in:
@ -51,6 +51,22 @@ set(INTEGRATIONTESTS_SRCS
|
||||
${INTEGRATIONTESTS_SOURCE_DIR}/TestingAdaptor.h
|
||||
${INTEGRATIONTESTS_SOURCE_DIR}/TestingProxy.h)
|
||||
|
||||
set(PERFTESTS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/perftests)
|
||||
set(STRESSTESTS_CLIENT_SRCS
|
||||
${PERFTESTS_SOURCE_DIR}/client.cpp
|
||||
${PERFTESTS_SOURCE_DIR}/perftest-proxy.h)
|
||||
set(STRESSTESTS_SERVER_SRCS
|
||||
${PERFTESTS_SOURCE_DIR}/server.cpp
|
||||
${PERFTESTS_SOURCE_DIR}/perftest-adaptor.h)
|
||||
|
||||
set(STRESSTESTS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/stresstests)
|
||||
set(STRESSTESTS_SRCS
|
||||
${STRESSTESTS_SOURCE_DIR}/stresstests.cpp
|
||||
${STRESSTESTS_SOURCE_DIR}/fahrenheit-thermometer-adaptor.h
|
||||
${STRESSTESTS_SOURCE_DIR}/fahrenheit-thermometer-proxy.h
|
||||
${STRESSTESTS_SOURCE_DIR}/concatenator-adaptor.h
|
||||
${STRESSTESTS_SOURCE_DIR}/concatenator-proxy.h)
|
||||
|
||||
#-------------------------------
|
||||
# GENERAL COMPILER CONFIGURATION
|
||||
#-------------------------------
|
||||
@ -74,12 +90,22 @@ target_link_libraries(libsdbus-c++_integrationtests sdbus-c++ gmock gmock_main)
|
||||
# Manual performance tests
|
||||
option(ENABLE_PERFTESTS "Build and install manual performance tests (default OFF)" OFF)
|
||||
if(ENABLE_PERFTESTS)
|
||||
add_executable(libsdbus-c++_perftests_client perftests/client.cpp perftests/perftest-proxy.h)
|
||||
add_executable(libsdbus-c++_perftests_client ${STRESSTESTS_CLIENT_SRCS})
|
||||
target_link_libraries(libsdbus-c++_perftests_client sdbus-c++)
|
||||
add_executable(libsdbus-c++_perftests_server perftests/server.cpp perftests/perftest-adaptor.h)
|
||||
add_executable(libsdbus-c++_perftests_server ${STRESSTESTS_SERVER_SRCS})
|
||||
target_link_libraries(libsdbus-c++_perftests_server sdbus-c++)
|
||||
endif()
|
||||
|
||||
# Manual stress tests
|
||||
option(ENABLE_STRESSTESTS "Build and install manual stress tests (default OFF)" ON)
|
||||
if(ENABLE_STRESSTESTS)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
add_executable(sdbus-c++-stress-tests ${STRESSTESTS_SRCS})
|
||||
target_link_libraries(sdbus-c++-stress-tests sdbus-c++ Threads::Threads)
|
||||
endif()
|
||||
|
||||
#----------------------------------
|
||||
# INSTALLATION
|
||||
#----------------------------------
|
||||
@ -94,6 +120,11 @@ if(ENABLE_PERFTESTS)
|
||||
install(FILES perftests/files/org.sdbuscpp.perftest.conf DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/dbus-1/system.d)
|
||||
endif()
|
||||
|
||||
if(ENABLE_STRESSTESTS)
|
||||
install(TARGETS sdbus-c++-stress-tests DESTINATION /opt/test/bin)
|
||||
install(FILES perftests/files/org.sdbuscpp.stresstest.conf DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/dbus-1/system.d)
|
||||
endif()
|
||||
|
||||
#----------------------------------
|
||||
# RUNNING THE TESTS UPON BUILD
|
||||
#----------------------------------
|
||||
|
39
test/stresstests/celsius-thermometer-adaptor.h
Executable file
39
test/stresstests/celsius-thermometer-adaptor.h
Executable file
@ -0,0 +1,39 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbuscpp-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__celsius_thermometer_adaptor_h__adaptor__H__
|
||||
#define __sdbuscpp__celsius_thermometer_adaptor_h__adaptor__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace org {
|
||||
namespace sdbuscpp {
|
||||
namespace stresstest {
|
||||
namespace celsius {
|
||||
|
||||
class thermometer_adaptor
|
||||
{
|
||||
public:
|
||||
static constexpr const char* interfaceName = "org.sdbuscpp.stresstest.celsius.thermometer";
|
||||
|
||||
protected:
|
||||
thermometer_adaptor(sdbus::IObject& object)
|
||||
: object_(object)
|
||||
{
|
||||
object_.registerMethod("getCurrentTemperature").onInterface(interfaceName).implementedAs([this](){ return this->getCurrentTemperature(); });
|
||||
}
|
||||
|
||||
private:
|
||||
virtual uint32_t getCurrentTemperature() = 0;
|
||||
|
||||
private:
|
||||
sdbus::IObject& object_;
|
||||
};
|
||||
|
||||
}}}} // namespaces
|
||||
|
||||
#endif
|
43
test/stresstests/celsius-thermometer-proxy.h
Executable file
43
test/stresstests/celsius-thermometer-proxy.h
Executable file
@ -0,0 +1,43 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbuscpp-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__celsius_thermometer_proxy_h__proxy__H__
|
||||
#define __sdbuscpp__celsius_thermometer_proxy_h__proxy__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace org {
|
||||
namespace sdbuscpp {
|
||||
namespace stresstest {
|
||||
namespace celsius {
|
||||
|
||||
class thermometer_proxy
|
||||
{
|
||||
public:
|
||||
static constexpr const char* interfaceName = "org.sdbuscpp.stresstest.celsius.thermometer";
|
||||
|
||||
protected:
|
||||
thermometer_proxy(sdbus::IObjectProxy& object)
|
||||
: object_(object)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
uint32_t getCurrentTemperature()
|
||||
{
|
||||
uint32_t result;
|
||||
object_.callMethod("getCurrentTemperature").onInterface(interfaceName).storeResultsTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
sdbus::IObjectProxy& object_;
|
||||
};
|
||||
|
||||
}}}} // namespaces
|
||||
|
||||
#endif
|
45
test/stresstests/concatenator-adaptor.h
Normal file
45
test/stresstests/concatenator-adaptor.h
Normal file
@ -0,0 +1,45 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbuscpp-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__concatenator_adaptor_h__adaptor__H__
|
||||
#define __sdbuscpp__concatenator_adaptor_h__adaptor__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace org {
|
||||
namespace sdbuscpp {
|
||||
namespace stresstest {
|
||||
|
||||
class concatenator_adaptor
|
||||
{
|
||||
public:
|
||||
static constexpr const char* interfaceName = "org.sdbuscpp.stresstest.concatenator";
|
||||
|
||||
protected:
|
||||
concatenator_adaptor(sdbus::IObject& object)
|
||||
: object_(object)
|
||||
{
|
||||
object_.registerMethod("concatenate").onInterface(interfaceName).implementedAs([this](sdbus::Result<std::string>&& result, std::map<std::string, sdbus::Variant> params){ this->concatenate(std::move(result), std::move(params)); });
|
||||
object_.registerSignal("concatenatedSignal").onInterface(interfaceName).withParameters<std::string>();
|
||||
}
|
||||
|
||||
public:
|
||||
void concatenatedSignal(const std::string& concatenatedString)
|
||||
{
|
||||
object_.emitSignal("concatenatedSignal").onInterface(interfaceName).withArguments(concatenatedString);
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void concatenate(sdbus::Result<std::string>&& result, std::map<std::string, sdbus::Variant> params) = 0;
|
||||
|
||||
private:
|
||||
sdbus::IObject& object_;
|
||||
};
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif
|
45
test/stresstests/concatenator-proxy.h
Normal file
45
test/stresstests/concatenator-proxy.h
Normal file
@ -0,0 +1,45 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbuscpp-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__concatenator_proxy_h__proxy__H__
|
||||
#define __sdbuscpp__concatenator_proxy_h__proxy__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace org {
|
||||
namespace sdbuscpp {
|
||||
namespace stresstest {
|
||||
|
||||
class concatenator_proxy
|
||||
{
|
||||
public:
|
||||
static constexpr const char* interfaceName = "org.sdbuscpp.stresstest.concatenator";
|
||||
|
||||
protected:
|
||||
concatenator_proxy(sdbus::IObjectProxy& object)
|
||||
: object_(object)
|
||||
{
|
||||
object_.uponSignal("concatenatedSignal").onInterface(interfaceName).call([this](const std::string& concatenatedString){ this->onConcatenatedSignal(concatenatedString); });
|
||||
}
|
||||
|
||||
virtual void onConcatenatedSignal(const std::string& concatenatedString) = 0;
|
||||
|
||||
virtual void onConcatenateReply(const std::string& result, const sdbus::Error* error) = 0;
|
||||
|
||||
public:
|
||||
void concatenate(const std::map<std::string, sdbus::Variant>& params)
|
||||
{
|
||||
object_.callMethodAsync("concatenate").onInterface(interfaceName).withArguments(params).uponReplyInvoke([this](const sdbus::Error* error, const std::string& result){ this->onConcatenateReply(result, error); });
|
||||
}
|
||||
|
||||
private:
|
||||
sdbus::IObjectProxy& object_;
|
||||
};
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif
|
39
test/stresstests/fahrenheit-thermometer-adaptor.h
Normal file
39
test/stresstests/fahrenheit-thermometer-adaptor.h
Normal file
@ -0,0 +1,39 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbuscpp-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__fahrenheit_thermometer_adaptor_h__adaptor__H__
|
||||
#define __sdbuscpp__fahrenheit_thermometer_adaptor_h__adaptor__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace org {
|
||||
namespace sdbuscpp {
|
||||
namespace stresstest {
|
||||
namespace fahrenheit {
|
||||
|
||||
class thermometer_adaptor
|
||||
{
|
||||
public:
|
||||
static constexpr const char* interfaceName = "org.sdbuscpp.stresstest.fahrenheit.thermometer";
|
||||
|
||||
protected:
|
||||
thermometer_adaptor(sdbus::IObject& object)
|
||||
: object_(object)
|
||||
{
|
||||
object_.registerMethod("getCurrentTemperature").onInterface(interfaceName).implementedAs([this](){ return this->getCurrentTemperature(); });
|
||||
}
|
||||
|
||||
private:
|
||||
virtual uint32_t getCurrentTemperature() = 0;
|
||||
|
||||
private:
|
||||
sdbus::IObject& object_;
|
||||
};
|
||||
|
||||
}}}} // namespaces
|
||||
|
||||
#endif
|
43
test/stresstests/fahrenheit-thermometer-proxy.h
Normal file
43
test/stresstests/fahrenheit-thermometer-proxy.h
Normal file
@ -0,0 +1,43 @@
|
||||
|
||||
/*
|
||||
* This file was automatically generated by sdbuscpp-xml2cpp; DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#ifndef __sdbuscpp__fahrenheit_thermometer_proxy_h__proxy__H__
|
||||
#define __sdbuscpp__fahrenheit_thermometer_proxy_h__proxy__H__
|
||||
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace org {
|
||||
namespace sdbuscpp {
|
||||
namespace stresstest {
|
||||
namespace fahrenheit {
|
||||
|
||||
class thermometer_proxy
|
||||
{
|
||||
public:
|
||||
static constexpr const char* interfaceName = "org.sdbuscpp.stresstest.fahrenheit.thermometer";
|
||||
|
||||
protected:
|
||||
thermometer_proxy(sdbus::IObjectProxy& object)
|
||||
: object_(object)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
uint32_t getCurrentTemperature()
|
||||
{
|
||||
uint32_t result;
|
||||
object_.callMethod("getCurrentTemperature").onInterface(interfaceName).storeResultsTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
sdbus::IObjectProxy& object_;
|
||||
};
|
||||
|
||||
}}}} // namespaces
|
||||
|
||||
#endif
|
22
test/stresstests/files/org.sdbuscpp.stresstest.conf
Executable file
22
test/stresstests/files/org.sdbuscpp.stresstest.conf
Executable file
@ -0,0 +1,22 @@
|
||||
<!-- This configuration file specifies the required security policies
|
||||
for the Kistler DBUS example to run core daemon to work. -->
|
||||
|
||||
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
<busconfig>
|
||||
|
||||
<!-- ../system.conf have denied everything, so we just punch some holes -->
|
||||
|
||||
<policy context="default">
|
||||
<allow own="org.sdbuscpp.stresstest.service1"/>
|
||||
<allow send_destination="org.sdbuscpp.stresstest.service1"/>
|
||||
<allow send_interface="org.sdbuscpp.stresstest.service1"/>
|
||||
</policy>
|
||||
|
||||
<policy context="default">
|
||||
<allow own="org.sdbuscpp.stresstest.service2"/>
|
||||
<allow send_destination="org.sdbuscpp.stresstest.service2"/>
|
||||
<allow send_interface="org.sdbuscpp.stresstest.service2"/>
|
||||
</policy>
|
||||
|
||||
</busconfig>
|
9
test/stresstests/org.sdbuscpp.stresstest.celsius.thermometer.xml
Executable file
9
test/stresstests/org.sdbuscpp.stresstest.celsius.thermometer.xml
Executable file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<node name="/org/sdbuscpp/stresstest/celsius/thermometer">
|
||||
<interface name="org.sdbuscpp.stresstest.celsius.thermometer">
|
||||
<method name="getCurrentTemperature">
|
||||
<arg type="u" name="result" direction="out" />
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
14
test/stresstests/org.sdbuscpp.stresstest.concatenator.xml
Executable file
14
test/stresstests/org.sdbuscpp.stresstest.concatenator.xml
Executable file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<node name="/org/sdbuscpp/stresstest/concatenator">
|
||||
<interface name="org.sdbuscpp.stresstest.concatenator">
|
||||
<method name="concatenate">
|
||||
<arg type="a{sv}" name="params" direction="in" />
|
||||
<arg type="s" name="result" direction="out" />
|
||||
<annotation name="org.freedesktop.DBus.Method.Async" value="clientserver" />
|
||||
</method>
|
||||
<signal name="concatenatedSignal">
|
||||
<arg type="s" name="concatenatedString" />
|
||||
</signal>
|
||||
</interface>
|
||||
</node>
|
9
test/stresstests/org.sdbuscpp.stresstest.fahrenheit.thermometer.xml
Executable file
9
test/stresstests/org.sdbuscpp.stresstest.fahrenheit.thermometer.xml
Executable file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<node name="/org/sdbuscpp/stresstest/fahrenheit/thermometer">
|
||||
<interface name="org.sdbuscpp.stresstest.fahrenheit.thermometer">
|
||||
<method name="getCurrentTemperature">
|
||||
<arg type="u" name="result" direction="out" />
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
322
test/stresstests/stresstests.cpp
Executable file
322
test/stresstests/stresstests.cpp
Executable file
@ -0,0 +1,322 @@
|
||||
/**
|
||||
* (C) 2019 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
|
||||
*
|
||||
* @file stresstests.cpp
|
||||
*
|
||||
* Created on: Jan 25, 2019
|
||||
* Project: sdbus-c++
|
||||
* Description: High-level D-Bus IPC C++ library based on sd-bus
|
||||
*
|
||||
* This file is part of sdbus-c++.
|
||||
*
|
||||
* sdbus-c++ is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* sdbus-c++ is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with sdbus-c++. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "celsius-thermometer-adaptor.h"
|
||||
#include "celsius-thermometer-proxy.h"
|
||||
#include "fahrenheit-thermometer-adaptor.h"
|
||||
#include "fahrenheit-thermometer-proxy.h"
|
||||
#include "concatenator-adaptor.h"
|
||||
#include "concatenator-proxy.h"
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <cassert>
|
||||
#include <atomic>
|
||||
#include <sstream>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <queue>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
using namespace std::string_literals;
|
||||
|
||||
#define SERVICE_1_BUS_NAME "org.sdbuscpp.stresstest.service1"
|
||||
#define SERVICE_2_BUS_NAME "org.sdbuscpp.stresstest.service2"
|
||||
#define CELSIUS_THERMOMETER_OBJECT_PATH "/org/sdbuscpp/stresstest/celsius/thermometer"
|
||||
#define FAHRENHEIT_THERMOMETER_OBJECT_PATH "/org/sdbuscpp/stresstest/fahrenheit/thermometer"
|
||||
#define CONCATENATOR_OBJECT_PATH "/org/sdbuscpp/stresstest/concatenator"
|
||||
|
||||
class CelsiusThermometerAdaptor : public sdbus::Interfaces<org::sdbuscpp::stresstest::celsius::thermometer_adaptor>
|
||||
{
|
||||
public:
|
||||
using sdbus::Interfaces<org::sdbuscpp::stresstest::celsius::thermometer_adaptor>::Interfaces;
|
||||
|
||||
protected:
|
||||
virtual uint32_t getCurrentTemperature() override
|
||||
{
|
||||
return m_currentTemperature++;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t m_currentTemperature{};
|
||||
};
|
||||
|
||||
class CelsiusThermometerProxy : public sdbus::ProxyInterfaces<org::sdbuscpp::stresstest::celsius::thermometer_proxy>
|
||||
{
|
||||
public:
|
||||
using sdbus::ProxyInterfaces<org::sdbuscpp::stresstest::celsius::thermometer_proxy>::ProxyInterfaces;
|
||||
};
|
||||
|
||||
class FahrenheitThermometerAdaptor : public sdbus::Interfaces<org::sdbuscpp::stresstest::fahrenheit::thermometer_adaptor>
|
||||
{
|
||||
public:
|
||||
FahrenheitThermometerAdaptor(sdbus::IConnection& connection, std::string objectPath)
|
||||
: sdbus::Interfaces<org::sdbuscpp::stresstest::fahrenheit::thermometer_adaptor>(connection, std::move(objectPath))
|
||||
, celsiusProxy_(connection, SERVICE_2_BUS_NAME, CELSIUS_THERMOMETER_OBJECT_PATH)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual uint32_t getCurrentTemperature() override
|
||||
{
|
||||
// In this D-Bus call, make yet another D-Bus call to another service over the same connection
|
||||
return static_cast<uint32_t>(celsiusProxy_.getCurrentTemperature() * 1.8 + 32.);
|
||||
}
|
||||
|
||||
private:
|
||||
CelsiusThermometerProxy celsiusProxy_;
|
||||
};
|
||||
|
||||
class FahrenheitThermometerProxy : public sdbus::ProxyInterfaces<org::sdbuscpp::stresstest::fahrenheit::thermometer_proxy>
|
||||
{
|
||||
public:
|
||||
using sdbus::ProxyInterfaces<org::sdbuscpp::stresstest::fahrenheit::thermometer_proxy>::ProxyInterfaces;
|
||||
};
|
||||
|
||||
class ConcatenatorAdaptor : public sdbus::Interfaces<org::sdbuscpp::stresstest::concatenator_adaptor>
|
||||
{
|
||||
public:
|
||||
ConcatenatorAdaptor(sdbus::IConnection& connection, std::string objectPath)
|
||||
: sdbus::Interfaces<org::sdbuscpp::stresstest::concatenator_adaptor>(connection, std::move(objectPath))
|
||||
{
|
||||
unsigned int workers = std::thread::hardware_concurrency();
|
||||
if (workers < 4)
|
||||
workers = 4;
|
||||
|
||||
for (unsigned int i = 0; i < workers; ++i)
|
||||
workers_.emplace_back([this]()
|
||||
{
|
||||
//std::cout << "Created worker thread 0x" << std::hex << std::this_thread::get_id() << std::dec << std::endl;
|
||||
|
||||
while(!exit_)
|
||||
{
|
||||
// Pop a work item from the queue
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
cond_.wait(lock, [this]{return !requests_.empty() || exit_;});
|
||||
if (exit_)
|
||||
break;
|
||||
auto request = std::move(requests_.front());
|
||||
requests_.pop();
|
||||
lock.unlock();
|
||||
|
||||
// Do concatenation work, return results and fire signal
|
||||
auto aString = request.input.at("key1").get<std::string>();
|
||||
auto aNumber = request.input.at("key2").get<uint32_t>();
|
||||
auto resultString = aString + " " + std::to_string(aNumber);
|
||||
|
||||
request.result.returnResults(resultString);
|
||||
|
||||
concatenatedSignal(resultString);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
~ConcatenatorAdaptor()
|
||||
{
|
||||
exit_ = true;
|
||||
cond_.notify_all();
|
||||
for (auto& worker : workers_)
|
||||
worker.join();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void concatenate(sdbus::Result<std::string>&& result, std::map<std::string, sdbus::Variant> params) override
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
requests_.push(WorkItem{std::move(params), std::move(result)});
|
||||
lock.unlock();
|
||||
cond_.notify_one();
|
||||
}
|
||||
|
||||
private:
|
||||
struct WorkItem
|
||||
{
|
||||
std::map<std::string, sdbus::Variant> input;
|
||||
sdbus::Result<std::string> result;
|
||||
};
|
||||
std::mutex mutex_;
|
||||
std::condition_variable cond_;
|
||||
std::queue<WorkItem> requests_;
|
||||
std::vector<std::thread> workers_;
|
||||
std::atomic<bool> exit_{};
|
||||
};
|
||||
|
||||
class ConcatenatorProxy : public sdbus::ProxyInterfaces<org::sdbuscpp::stresstest::concatenator_proxy>
|
||||
{
|
||||
public:
|
||||
using sdbus::ProxyInterfaces<org::sdbuscpp::stresstest::concatenator_proxy>::ProxyInterfaces;
|
||||
|
||||
private:
|
||||
virtual void onConcatenateReply(const std::string& result, const sdbus::Error* error) override
|
||||
{
|
||||
assert(error == nullptr);
|
||||
|
||||
std::stringstream str(result);
|
||||
std::string aString;
|
||||
str >> aString;
|
||||
assert(aString == "sdbus-c++-stress-tests");
|
||||
|
||||
uint32_t aNumber;
|
||||
str >> aNumber;
|
||||
assert(aNumber >= 0);
|
||||
|
||||
++repliesReceived_;
|
||||
}
|
||||
|
||||
virtual void onConcatenatedSignal(const std::string& concatenatedString) override
|
||||
{
|
||||
std::stringstream str(concatenatedString);
|
||||
std::string aString;
|
||||
str >> aString;
|
||||
assert(aString == "sdbus-c++-stress-tests");
|
||||
|
||||
uint32_t aNumber;
|
||||
str >> aNumber;
|
||||
assert(aNumber >= 0);
|
||||
|
||||
++signalsReceived_;
|
||||
}
|
||||
|
||||
public:
|
||||
std::atomic<uint32_t> repliesReceived_;
|
||||
std::atomic<uint32_t> signalsReceived_;
|
||||
};
|
||||
|
||||
//-----------------------------------------
|
||||
int main(int /*argc*/, char */*argv*/[])
|
||||
{
|
||||
auto service2Connection = sdbus::createSystemBusConnection(SERVICE_2_BUS_NAME);
|
||||
std::thread service2Thread([&con = *service2Connection]()
|
||||
{
|
||||
CelsiusThermometerAdaptor thermometer(con, CELSIUS_THERMOMETER_OBJECT_PATH);
|
||||
con.enterProcessingLoop();
|
||||
});
|
||||
|
||||
auto service1Connection = sdbus::createSystemBusConnection(SERVICE_1_BUS_NAME);
|
||||
std::thread service1Thread([&con = *service1Connection]()
|
||||
{
|
||||
ConcatenatorAdaptor concatenator(con, CONCATENATOR_OBJECT_PATH);
|
||||
FahrenheitThermometerAdaptor thermometer(con, FAHRENHEIT_THERMOMETER_OBJECT_PATH);
|
||||
con.enterProcessingLoop();
|
||||
});
|
||||
|
||||
std::this_thread::sleep_for(100ms);
|
||||
|
||||
std::atomic<uint32_t> concatenationCallsMade{0};
|
||||
std::atomic<uint32_t> concatenationRepliesReceived{0};
|
||||
std::atomic<uint32_t> concatenationSignalsReceived{0};
|
||||
std::atomic<uint32_t> thermometerCallsMade{0};
|
||||
|
||||
auto clientConnection = sdbus::createSystemBusConnection();
|
||||
std::thread clientThread([&, &con = *clientConnection]()
|
||||
{
|
||||
std::atomic<bool> stopClients{false};
|
||||
|
||||
std::thread concatenatorThread([&]()
|
||||
{
|
||||
ConcatenatorProxy concatenator(con, SERVICE_1_BUS_NAME, CONCATENATOR_OBJECT_PATH);
|
||||
|
||||
uint32_t localCounter{};
|
||||
|
||||
// Issue async concatenate calls densely one after another
|
||||
while (!stopClients)
|
||||
{
|
||||
std::map<std::string, sdbus::Variant> param;
|
||||
param["key1"] = "sdbus-c++-stress-tests";
|
||||
param["key2"] = localCounter++;
|
||||
|
||||
concatenator.concatenate(param);
|
||||
|
||||
if ((localCounter % 10) == 0)
|
||||
{
|
||||
// Make sure the system is catching up with our async requests,
|
||||
// otherwise sleep a bit to slow down flooding the server.
|
||||
assert(localCounter >= concatenator.repliesReceived_);
|
||||
while ((localCounter - concatenator.repliesReceived_) > 20 && !stopClients)
|
||||
std::this_thread::sleep_for(2ms);
|
||||
|
||||
// Update statistics
|
||||
concatenationCallsMade = localCounter;
|
||||
concatenationRepliesReceived = (uint32_t)concatenator.repliesReceived_;
|
||||
concatenationSignalsReceived = (uint32_t)concatenator.signalsReceived_;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
std::thread thermometerThread([&]()
|
||||
{
|
||||
FahrenheitThermometerProxy thermometer(con, SERVICE_1_BUS_NAME, FAHRENHEIT_THERMOMETER_OBJECT_PATH);
|
||||
uint32_t localCounter{};
|
||||
uint32_t previousTemperature{};
|
||||
|
||||
while (!stopClients)
|
||||
{
|
||||
localCounter++;
|
||||
auto temperature = thermometer.getCurrentTemperature();
|
||||
assert(temperature >= previousTemperature); // The temperature shall rise continually
|
||||
previousTemperature = temperature;
|
||||
std::this_thread::sleep_for(5ms);
|
||||
|
||||
if ((localCounter % 10) == 0)
|
||||
thermometerCallsMade = localCounter;
|
||||
}
|
||||
});
|
||||
|
||||
con.enterProcessingLoop();
|
||||
|
||||
stopClients = true;
|
||||
concatenatorThread.join();
|
||||
thermometerThread.join();
|
||||
});
|
||||
|
||||
std::atomic<bool> exitLogger{};
|
||||
std::thread loggerThread([&]()
|
||||
{
|
||||
while (!exitLogger)
|
||||
{
|
||||
std::this_thread::sleep_for(1s);
|
||||
|
||||
std::cout << "Made " << concatenationCallsMade << " concatenation calls, received " << concatenationRepliesReceived << " replies and " << concatenationSignalsReceived << " signals so far." << std::endl;
|
||||
std::cout << "Made " << thermometerCallsMade << " thermometer calls so far." << std::endl << std::endl;
|
||||
}
|
||||
});
|
||||
|
||||
getchar();
|
||||
|
||||
exitLogger = true;
|
||||
loggerThread.join();
|
||||
clientConnection->leaveProcessingLoop();
|
||||
clientThread.join();
|
||||
service1Connection->leaveProcessingLoop();
|
||||
service1Thread.join();
|
||||
service2Connection->leaveProcessingLoop();
|
||||
service2Thread.join();
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user