This commit is contained in:
sangelovic
2019-02-04 22:31:09 +01:00
parent 9292f293ec
commit d2d1a2ddbc
7 changed files with 291 additions and 316 deletions

View File

@ -570,6 +570,26 @@ namespace sdbus {
, std::forward<_Tuple>(t)
, std::make_index_sequence<std::tuple_size<std::decay_t<_Tuple>>::value>{} );
}
// Invoke a member function (custom version of C++17's invoke until we have full C++17 support)
template< typename _Function
, typename... _Args
, std::enable_if_t<std::is_member_pointer<std::decay_t<_Function>>{}, int> = 0 >
constexpr decltype(auto) invoke(_Function&& f, _Args&&... args)
noexcept(noexcept(std::mem_fn(f)(std::forward<_Args>(args)...)))
{
return std::mem_fn(f)(std::forward<_Args>(args)...);
}
// Invoke non-member function (custom version of C++17's invoke until we have full C++17 support)
template< typename _Function
, typename... _Args
, std::enable_if_t<!std::is_member_pointer<std::decay_t<_Function>>{}, int> = 0 >
constexpr decltype(auto) invoke(_Function&& f, _Args&&... args)
noexcept(noexcept(std::forward<_Function>(f)(std::forward<_Args>(args)...)))
{
return std::forward<_Function>(f)(std::forward<_Args>(args)...);
}
}
#endif /* SDBUS_CXX_TYPETRAITS_H_ */

View File

@ -43,11 +43,13 @@ Connection::Connection(Connection::BusType type)
finishHandshake(bus);
notificationFd_ = createLoopNotificationDescriptor();
std::cerr << "Created eventfd " << notificationFd_ << " of " << this << std::endl;
}
Connection::~Connection()
{
leaveProcessingLoop();
std::cerr << "Closing eventfd " << notificationFd_ << " of " << this << std::endl;
closeLoopNotificationDescriptor(notificationFd_);
}
@ -87,8 +89,9 @@ void Connection::enterProcessingLoop()
void Connection::enterProcessingLoopAsync()
{
std::cerr << "--> enterProcessingLoopAsync() for connection " << this << std::endl;
// TODO: Check that joinable() means a valid non-empty thread
if (!asyncLoopThread_.joinable())
//if (!asyncLoopThread_.joinable())
asyncLoopThread_ = std::thread([this](){ enterProcessingLoop(); });
}
@ -166,6 +169,122 @@ Signal Connection::createSignal( const std::string& objectPath
return Signal(sdbusSignal);
}
template<typename _Callable, typename... _Args, std::enable_if_t<std::is_void<function_result_t<_Callable>>::value, int>>
inline auto Connection::tryExecuteSync(_Callable&& fnc, const _Args&... args)
{
std::thread::id loopThreadId = loopThreadId_.load(std::memory_order_relaxed);
// Is the loop not yet on? => Go make synchronous call
while (loopThreadId == std::thread::id{})
{
// Did the loop begin in the meantime? Or try_lock() failed spuriously?
if (!loopMutex_.try_lock())
{
loopThreadId = loopThreadId_.load(std::memory_order_relaxed);
continue;
}
// Synchronous call
std::lock_guard<std::mutex> guard(loopMutex_, std::adopt_lock);
sdbus::invoke(std::forward<_Callable>(fnc), args...);
return true;
}
// Is the loop on and we are in the same thread? => Go for synchronous call
if (loopThreadId == std::this_thread::get_id())
{
assert(!loopMutex_.try_lock());
sdbus::invoke(std::forward<_Callable>(fnc), args...);
return true;
}
return false;
}
template<typename _Callable, typename... _Args, std::enable_if_t<!std::is_void<function_result_t<_Callable>>::value, int>>
inline auto Connection::tryExecuteSync(_Callable&& fnc, const _Args&... args)
{
std::thread::id loopThreadId = loopThreadId_.load(std::memory_order_relaxed);
// Is the loop not yet on? => Go make synchronous call
while (loopThreadId == std::thread::id{})
{
// Did the loop begin in the meantime? Or try_lock() failed spuriously?
if (!loopMutex_.try_lock())
{
loopThreadId = loopThreadId_.load(std::memory_order_relaxed);
continue;
}
// Synchronous call
std::lock_guard<std::mutex> guard(loopMutex_, std::adopt_lock);
return std::make_pair(true, sdbus::invoke(std::forward<_Callable>(fnc), args...));
}
// Is the loop on and we are in the same thread? => Go for synchronous call
if (loopThreadId == std::this_thread::get_id())
{
assert(!loopMutex_.try_lock());
return std::make_pair(true, sdbus::invoke(std::forward<_Callable>(fnc), args...));
}
return std::make_pair(false, function_result_t<_Callable>{});
}
template<typename _Callable, typename... _Args, std::enable_if_t<std::is_void<function_result_t<_Callable>>::value, int>>
inline void Connection::executeAsync(_Callable&& fnc, const _Args&... args)
{
std::promise<void> result;
auto future = result.get_future();
queueUserRequest([fnc = std::forward<_Callable>(fnc), args..., &result]()
{
SCOPE_EXIT_NAMED(onSdbusError){ result.set_exception(std::current_exception()); };
std::cerr << " [lt] ... Invoking void request from within event loop thread..." << std::endl;
sdbus::invoke(fnc, args...);
std::cerr << " [lt] Request invoked" << std::endl;
result.set_value();
onSdbusError.dismiss();
});
// Wait for the the processing loop thread to process the request
future.get();
}
template<typename _Callable, typename... _Args, std::enable_if_t<!std::is_void<function_result_t<_Callable>>::value, int>>
inline auto Connection::executeAsync(_Callable&& fnc, const _Args&... args)
{
std::promise<function_result_t<_Callable>> result;
auto future = result.get_future();
queueUserRequest([fnc = std::forward<_Callable>(fnc), args..., &result]()
{
SCOPE_EXIT_NAMED(onSdbusError){ result.set_exception(std::current_exception()); };
std::cerr << " [lt] ... Invoking request from within event loop thread..." << std::endl;
auto returnValue = sdbus::invoke(fnc, args...);
std::cerr << " [lt] Request invoked and got result" << std::endl;
result.set_value(returnValue);
onSdbusError.dismiss();
});
// Wait for the reply from the processing loop thread
return future.get();
}
template<typename _Callable, typename... _Args>
inline void Connection::executeAsyncAndDontWaitForResult(_Callable&& fnc, const _Args&... args)
{
queueUserRequest([fnc = std::forward<_Callable>(fnc), args...]()
{
sdbus::invoke(fnc, args...);
});
}
void* Connection::registerSignalHandler( const std::string& objectPath
, const std::string& interfaceName
, const std::string& signalName
@ -182,181 +301,62 @@ void* Connection::registerSignalHandler( const std::string& objectPath
auto filter = composeSignalMatchFilter(objectPath, interfaceName, signalName);
auto r = sd_bus_add_match(bus_.get(), &slot, filter.c_str(), callback, userData);
std::cerr << "Registered signal " << signalName << " with slot " << slot << std::endl;
SDBUS_THROW_ERROR_IF(r < 0, "Failed to register signal handler", -r);
return slot;
};
std::thread::id loopThreadId = loopThreadId_;
// Is the loop not yet on? => Go make synchronous call
while (loopThreadId == std::thread::id{})
{
// Did the loop begin in the meantime? Or try_lock() failed spuriously?
if (!loopMutex_.try_lock())
continue;
// Synchronous call
std::lock_guard<std::mutex> guard(loopMutex_, std::adopt_lock);
return registerSignalHandler(objectPath, interfaceName, signalName, callback, userData);
}
// Is the loop on and we are in the same thread? => Go for synchronous call
if (loopThreadId == std::this_thread::get_id())
{
assert(!loopMutex_.try_lock());
return registerSignalHandler(objectPath, interfaceName, signalName, callback, userData);
}
// We are in a different thread than the loop thread => Asynchronous call
std::promise<void*> result;
auto future = result.get_future();
queueUserRequest([registerSignalHandler, objectPath, interfaceName, signalName, callback, userData, &result]()
{
SCOPE_EXIT_NAMED(onSdbusError){ result.set_exception(std::current_exception()); };
void* slot = registerSignalHandler(objectPath, interfaceName, signalName, callback, userData);
result.set_value(slot);
onSdbusError.dismiss();
});
auto request = std::make_unique<SignalRegistrationRequest>();
request->registerSignalHandler = registerSignalHandler;
auto future = request->result.get_future();
queueUserRequest(std::move(request));
// Wait for the reply from the loop thread
return future.get();
std::cerr << "Trying to register signal " << signalName << " synchronously..." << std::endl;
auto result = tryExecuteSync(registerSignalHandler, objectPath, interfaceName, signalName, callback, userData);
if (!result.first) std::cerr << " ... Nope, going async way" << std::endl;
return result.first ? result.second
: executeAsync(registerSignalHandler, objectPath, interfaceName, signalName, callback, userData);
}
void Connection::unregisterSignalHandler(void* handlerCookie)
{
sd_bus_slot_unref((sd_bus_slot *)handlerCookie);
auto result = tryExecuteSync(sd_bus_slot_unref, (sd_bus_slot *)handlerCookie);
// if (!result.first)
// executeAsync(sd_bus_slot_unref, (sd_bus_slot *)handlerCookie);
if (result.first)
{
std::cerr << "Synchronously unregistered signal " << handlerCookie << ": " << result.second << std::endl;
return;
}
auto slot = executeAsync(sd_bus_slot_unref, (sd_bus_slot *)handlerCookie);
std::cerr << "Asynchronously unregistered signal " << handlerCookie << ": " << slot << std::endl;
}
//class AsyncExecutor
//ifPossibleExecuteSync()
MethodReply Connection::callMethod(const MethodCall& message)
{
//ifPossibleExecuteSync().otherwiseExecuteAsync();
std::thread::id loopThreadId = loopThreadId_;
// Is the loop not yet on? => Go make synchronous call
while (loopThreadId == std::thread::id{})
{
// Did the loop begin in the meantime? Or try_lock() failed spuriously?
if (!loopMutex_.try_lock())
continue;
// Synchronous call
std::lock_guard<std::mutex> guard(loopMutex_, std::adopt_lock);
return message.send();
}
// Is the loop on and we are in the same thread? => Go for synchronous call
if (loopThreadId == std::this_thread::get_id())
{
assert(!loopMutex_.try_lock());
return message.send(); // Synchronous call
}
// We are in a different thread than the loop thread => Asynchronous call
auto request = std::make_unique<MethodCallRequest>();
request->msg = message;
auto future = request->result.get_future();
queueUserRequest(std::move(request));
// Wait for the reply from the loop thread
return future.get();
std::cerr << "Trying to call method synchronously..." << std::endl;
auto result = tryExecuteSync(&MethodCall::send, message);
if (!result.first) std::cerr << " ... Nope, going async way" << std::endl;
return result.first ? result.second
: executeAsync(&MethodCall::send, message);
}
void Connection::callMethod(const AsyncMethodCall& message, void* callback, void* userData)
{
std::thread::id loopThreadId = loopThreadId_;
// Is the loop not yet on? => Go make synchronous call
while (loopThreadId == std::thread::id{})
{
// Did the loop begin in the meantime? Or try_lock() failed spuriously?
if (!loopMutex_.try_lock())
continue;
// Synchronous call
std::lock_guard<std::mutex> guard(loopMutex_, std::adopt_lock);
return message.send(callback, userData);
}
// Is the loop on and we are in the same thread? => Go for synchronous call
if (loopThreadId == std::this_thread::get_id())
{
assert(!loopMutex_.try_lock());
return message.send(callback, userData); // Synchronous call
}
// We are in a different thread than the loop thread => Asynchronous call
auto request = std::make_unique<AsyncMethodCallRequest>();
request->msg = message;
request->callback = callback;
request->userData = userData;
queueUserRequest(std::move(request));
auto result = tryExecuteSync(&AsyncMethodCall::send, message, callback, userData);
if (!result)
executeAsyncAndDontWaitForResult(&AsyncMethodCall::send, message, callback, userData);
}
void Connection::sendMethodReply(const MethodReply& message)
{
std::thread::id loopThreadId = loopThreadId_;
// Is the loop not yet on? => Go make synchronous call
while (loopThreadId == std::thread::id{})
{
// Did the loop begin in the meantime? Or try_lock() failed spuriously?
if (!loopMutex_.try_lock())
continue;
// Synchronous call
std::lock_guard<std::mutex> guard(loopMutex_, std::adopt_lock);
return message.send();
}
// Is the loop on and we are in the same thread? => Go for synchronous call
if (loopThreadId == std::this_thread::get_id())
{
assert(!loopMutex_.try_lock());
return message.send(); // Synchronous call
}
// We are in a different thread than the loop thread => Asynchronous call
auto request = std::make_unique<MethodReplyRequest>();
request->msg = message;
queueUserRequest(std::move(request));
auto result = tryExecuteSync(&MethodReply::send, message);
if (!result)
executeAsyncAndDontWaitForResult(&MethodReply::send, message);
}
void Connection::emitSignal(const Signal& message)
{
std::thread::id loopThreadId = loopThreadId_;
// Is the loop not yet on? => Go make synchronous call
while (loopThreadId == std::thread::id{})
{
// Did the loop begin in the meantime? Or try_lock() failed spuriously?
if (!loopMutex_.try_lock())
continue;
// Synchronous call
std::lock_guard<std::mutex> guard(loopMutex_, std::adopt_lock);
return message.send();
}
// Is the loop on and we are in the same thread? => Go for synchronous call
if (loopThreadId == std::this_thread::get_id())
{
assert(!loopMutex_.try_lock());
return message.send(); // Synchronous call
}
// We are in a different thread than the loop thread => Asynchronous call
auto request = std::make_unique<SignalEmissionRequest>();
request->msg = message;
queueUserRequest(std::move(request));
auto result = tryExecuteSync(&Signal::send, message);
if (!result)
executeAsyncAndDontWaitForResult(&Signal::send, message);
}
std::unique_ptr<sdbus::internal::IConnection> Connection::clone() const
@ -413,10 +413,14 @@ void Connection::notifyProcessingLoop()
{
assert(notificationFd_ >= 0);
uint64_t value = 1;
auto r = write(notificationFd_, &value, sizeof(value));
SDBUS_THROW_ERROR_IF(r < 0, "Failed to notify processing loop", -errno);
for (int i = 0; i < 1; ++i)
{
//std::this_thread::sleep_for(std::chrono::milliseconds(5));
uint64_t value = 1;
auto r = write(notificationFd_, &value, sizeof(value));
std::cerr << "Wrote to notification fd " << notificationFd_ << std::endl;
SDBUS_THROW_ERROR_IF(r < 0, "Failed to notify processing loop", -errno);
}
}
void Connection::notifyProcessingLoopToExit()
@ -445,11 +449,12 @@ bool Connection::processPendingRequest()
return r > 0;
}
void Connection::queueUserRequest(std::unique_ptr<IUserRequest>&& request)
void Connection::queueUserRequest(UserRequest&& request)
{
{
std::lock_guard<std::mutex> guard(userRequestsMutex_);
userRequests_.push(std::move(request));
std::cerr << "Pushed to user request queue. Size: " << userRequests_.size() << std::endl;
}
notifyProcessingLoop();
}
@ -459,8 +464,8 @@ void Connection::processUserRequests()
std::lock_guard<std::mutex> guard(userRequestsMutex_);
while (!userRequests_.empty())
{
auto& reply = userRequests_.front();
reply->process();
auto& request = userRequests_.front();
request();
userRequests_.pop();
}
}
@ -483,22 +488,31 @@ Connection::WaitResult Connection::waitForNextRequest()
uint64_t usec;
sd_bus_get_timeout(bus, &usec);
struct pollfd fds[] = {{sdbusFd, sdbusEvents, 0}, {notificationFd_, POLLIN, 0}};
struct pollfd fds[] = {{sdbusFd, sdbusEvents, 0}, {notificationFd_, POLLIN | POLLHUP | POLLERR | POLLNVAL, 0}};
auto fdsCount = sizeof(fds)/sizeof(fds[0]);
std::cerr << "[lt] Going to poll on fs " << sdbusFd << ", " << notificationFd_ << " with timeout " << usec << " and fdscount == " << fdsCount << std::endl;
r = poll(fds, fdsCount, usec == (uint64_t) -1 ? -1 : (usec+999)/1000);
if (r < 0 && errno == EINTR)
{
std::cerr << "<<<>>>> GOT EINTR" << std::endl;
return {true, false}; // Try again
}
SDBUS_THROW_ERROR_IF(r < 0, "Failed to wait on the bus", -errno);
if ((fds[1].revents & POLLHUP) || (fds[1].revents & POLLERR) || ((fds[1].revents & POLLNVAL)))
{
std::cerr << "!!!!!!!!!! Something went wrong on polling" << std::endl;
}
if (fds[1].revents & POLLIN)
{
if (exitLoopThread_)
return {false, false}; // Got exit notification
// Otherwise we have some async messages to process
// Otherwise we have some user requests to process
std::cerr << "Loop found it has some async requests to process" << std::endl;
uint64_t value{};
auto r = read(notificationFd_, &value, sizeof(value));

View File

@ -99,104 +99,14 @@ namespace sdbus { namespace internal {
}
};
// TODO move down
struct IUserRequest
{
virtual void process() = 0;
virtual ~IUserRequest() = default;
};
struct MethodCallRequest : IUserRequest
{
MethodCall msg;
std::promise<MethodReply> result;
void process() override
{
SCOPE_EXIT_NAMED(onSdbusError){ result.set_exception(std::current_exception()); };
auto reply = msg.send();
result.set_value(std::move(reply));
onSdbusError.dismiss();
}
};
struct AsyncMethodCallRequest : IUserRequest
{
AsyncMethodCall msg;
void* callback;
void* userData;
// TODO: Catch exception and store to promise?
void process() override
{
msg.send(callback, userData);
}
};
struct MethodReplyRequest : IUserRequest
{
MethodReply msg;
// TODO: Catch exception and store to promise?
void process() override
{
msg.send();
}
};
struct SignalEmissionRequest : IUserRequest
{
Signal msg;
// TODO: Catch exception and store to promise?
void process() override
{
msg.send();
}
};
struct SignalRegistrationRequest : IUserRequest
{
std::function<void*()> registerSignalHandler;
std::promise<void*> result;
void process() override
{
SCOPE_EXIT_NAMED(onSdbusError){ result.set_exception(std::current_exception()); };
assert(registerSignalHandler);
void* slot = registerSignalHandler();
result.set_value(slot);
onSdbusError.dismiss();
}
};
struct SignalUnregistrationRequest : IUserRequest
{
std::function<void()> unregisterSignalHandler;
std::promise<void> result;
void process() override
{
SCOPE_EXIT_NAMED(onSdbusError){ result.set_exception(std::current_exception()); };
assert(unregisterSignalHandler);
unregisterSignalHandler();
result.set_value();
onSdbusError.dismiss();
}
};
using UserRequest = std::function<void()>;
static sd_bus* openBus(Connection::BusType type);
static void finishHandshake(sd_bus* bus);
static int createLoopNotificationDescriptor();
static void closeLoopNotificationDescriptor(int fd);
bool processPendingRequest();
void queueUserRequest(std::unique_ptr<IUserRequest>&& request);
void queueUserRequest(UserRequest&& request);
void processUserRequests();
WaitResult waitForNextRequest();
static std::string composeSignalMatchFilter( const std::string& objectPath
@ -206,13 +116,25 @@ namespace sdbus { namespace internal {
void notifyProcessingLoopToExit();
void joinWithProcessingLoop();
// TODO move this and threading logic and method around it to separate class?
template <typename _Callable, typename... _Args, std::enable_if_t<std::is_void<function_result_t<_Callable>>::value, int> = 0>
inline auto tryExecuteSync(_Callable&& fnc, const _Args&... args);
template <typename _Callable, typename... _Args, std::enable_if_t<!std::is_void<function_result_t<_Callable>>::value, int> = 0>
inline auto tryExecuteSync(_Callable&& fnc, const _Args&... args);
template <typename _Callable, typename... _Args, std::enable_if_t<std::is_void<function_result_t<_Callable>>::value, int> = 0>
inline void executeAsync(_Callable&& fnc, const _Args&... args);
template <typename _Callable, typename... _Args, std::enable_if_t<!std::is_void<function_result_t<_Callable>>::value, int> = 0>
inline auto executeAsync(_Callable&& fnc, const _Args&... args);
template <typename _Callable, typename... _Args>
inline void executeAsyncAndDontWaitForResult(_Callable&& fnc, const _Args&... args);
private:
std::unique_ptr<sd_bus, decltype(&sd_bus_flush_close_unref)> bus_{nullptr, &sd_bus_flush_close_unref};
std::thread asyncLoopThread_;
std::atomic<std::thread::id> loopThreadId_;
std::mutex loopMutex_;
std::queue<std::unique_ptr<IUserRequest>> userRequests_;
std::queue<UserRequest> userRequests_;
std::mutex userRequestsMutex_;
std::atomic<bool> exitLoopThread_;

View File

@ -30,6 +30,8 @@
#include "IConnection.h"
#include <systemd/sd-bus.h>
#include <cassert>
#include <chrono>
#include <thread>
namespace sdbus { namespace internal {
@ -49,7 +51,8 @@ ObjectProxy::ObjectProxy( std::unique_ptr<sdbus::internal::IConnection>&& connec
{
// The connection is ours only, so we have to manage event loop upon this connection,
// so we get signals, async replies, and other messages from D-Bus.
// TODO uncomment connection_->enterProcessingLoopAsync();
connection_->enterProcessingLoopAsync();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
MethodCall ObjectProxy::createMethodCall(const std::string& interfaceName, const std::string& methodName)

View File

@ -59,10 +59,12 @@ public:
{
m_connection.requestName(INTERFACE_NAME);
m_connection.enterProcessingLoopAsync();
//m_connection2.enterProcessingLoopAsync();
}
static void TearDownTestCase()
{
//m_connection2.leaveProcessingLoop();
m_connection.leaveProcessingLoop();
m_connection.releaseName(INTERFACE_NAME);
}
@ -71,7 +73,7 @@ private:
void SetUp() override
{
m_adaptor = std::make_unique<TestingAdaptor>(m_connection);
m_proxy = std::make_unique<TestingProxy>(INTERFACE_NAME, OBJECT_PATH);
m_proxy = std::make_unique<TestingProxy>(/*m_connection2, */INTERFACE_NAME, OBJECT_PATH);
std::this_thread::sleep_for(50ms); // Give time for the proxy to start listening to signals
}
@ -83,12 +85,14 @@ private:
public:
static sdbus::internal::Connection m_connection;
//static sdbus::internal::Connection m_connection2;
std::unique_ptr<TestingAdaptor> m_adaptor;
std::unique_ptr<TestingProxy> m_proxy;
};
sdbus::internal::Connection AdaptorAndProxyFixture::m_connection{sdbus::internal::Connection::BusType::eSystem};
//sdbus::internal::Connection AdaptorAndProxyFixture::m_connection2{sdbus::internal::Connection::BusType::eSystem};
}
@ -96,16 +100,16 @@ sdbus::internal::Connection AdaptorAndProxyFixture::m_connection{sdbus::internal
/* -- TEST CASES -- */
/*-------------------------------------*/
TEST(AdaptorAndProxy, CanBeConstructedSuccesfully)
{
auto connection = sdbus::createConnection();
connection->requestName(INTERFACE_NAME);
//TEST(AdaptorAndProxy, CanBeConstructedSuccesfully)
//{
// auto connection = sdbus::createConnection();
// connection->requestName(INTERFACE_NAME);
ASSERT_NO_THROW(TestingAdaptor adaptor(*connection));
ASSERT_NO_THROW(TestingProxy proxy(INTERFACE_NAME, OBJECT_PATH));
// ASSERT_NO_THROW(TestingAdaptor adaptor(*connection));
// ASSERT_NO_THROW(TestingProxy proxy(INTERFACE_NAME, OBJECT_PATH));
connection->releaseName(INTERFACE_NAME);
}
// connection->releaseName(INTERFACE_NAME);
//}
// Methods

View File

@ -45,7 +45,7 @@ public:
protected:
void noArgNoReturn() const { }
void noArgNoReturn() const { std::cerr << "Server: noArgNoReturn() called;" << std::endl;}
int32_t getInt() const { return INT32_VALUE; }

View File

@ -90,72 +90,84 @@ int main(int /*argc*/, char */*argv*/[])
{
const char* destinationName = "org.sdbuscpp.perftest";
const char* objectPath = "/org/sdbuscpp/perftest";
PerftestClient client(destinationName, objectPath);
//PerftestClient client(destinationName, objectPath);
const unsigned int repetitions{2};
unsigned int msgCount = 1000;
unsigned int msgSize{};
msgSize = 20;
std::cout << "** Measuring signals of size " << msgSize << " bytes (" << repetitions << " repetitions)..." << std::endl << std::endl;
client.m_msgCount = msgCount; client.m_msgSize = msgSize;
for (unsigned int r = 0; r < repetitions; ++r)
{
client.sendDataSignals(msgCount, msgSize);
std::this_thread::sleep_for(1000ms);
}
msgSize = 1000;
std::cout << std::endl << "** Measuring signals of size " << msgSize << " bytes (" << repetitions << " repetitions)..." << std::endl << std::endl;
client.m_msgCount = msgCount; client.m_msgSize = msgSize;
for (unsigned int r = 0; r < repetitions; ++r)
{
client.sendDataSignals(msgCount, msgSize);
std::this_thread::sleep_for(1000ms);
}
msgSize = 20;
std::cout << std::endl << "** Measuring method calls of size " << msgSize << " bytes (" << repetitions << " repetitions)..." << std::endl << std::endl;
for (unsigned int r = 0; r < repetitions; ++r)
{
auto str1 = createRandomString(msgSize/2);
auto str2 = createRandomString(msgSize/2);
auto startTime = std::chrono::steady_clock::now();
for (unsigned int i = 0; i < msgCount; i++)
PerftestClient client(destinationName, objectPath);
msgSize = 20;
std::cout << "** Measuring signals of size " << msgSize << " bytes (" << repetitions << " repetitions)..." << std::endl << std::endl;
client.m_msgCount = msgCount; client.m_msgSize = msgSize;
for (unsigned int r = 0; r < repetitions; ++r)
{
auto result = client.concatenateTwoStrings(str1, str2);
assert(result.size() == str1.size() + str2.size());
assert(result.size() == msgSize);
client.sendDataSignals(msgCount, msgSize);
std::this_thread::sleep_for(1000ms);
}
auto stopTime = std::chrono::steady_clock::now();
std::cout << "Called " << msgCount << " methods in: " << std::chrono::duration_cast<std::chrono::milliseconds>(stopTime - startTime).count() << " ms" << std::endl;
std::this_thread::sleep_for(1000ms);
}
msgSize = 1000;
std::cout << std::endl << "** Measuring method calls of size " << msgSize << " bytes (" << repetitions << " repetitions)..." << std::endl << std::endl;
for (unsigned int r = 0; r < repetitions; ++r)
{
auto str1 = createRandomString(msgSize/2);
auto str2 = createRandomString(msgSize/2);
auto startTime = std::chrono::steady_clock::now();
for (unsigned int i = 0; i < msgCount; i++)
PerftestClient client(destinationName, objectPath);
msgSize = 1000;
std::cout << std::endl << "** Measuring signals of size " << msgSize << " bytes (" << repetitions << " repetitions)..." << std::endl << std::endl;
client.m_msgCount = msgCount; client.m_msgSize = msgSize;
for (unsigned int r = 0; r < repetitions; ++r)
{
auto result = client.concatenateTwoStrings(str1, str2);
assert(result.size() == str1.size() + str2.size());
assert(result.size() == msgSize);
client.sendDataSignals(msgCount, msgSize);
std::this_thread::sleep_for(1000ms);
}
}
{
PerftestClient client(destinationName, objectPath);
msgSize = 20;
std::cout << std::endl << "** Measuring method calls of size " << msgSize << " bytes (" << repetitions << " repetitions)..." << std::endl << std::endl;
for (unsigned int r = 0; r < repetitions; ++r)
{
auto str1 = createRandomString(msgSize/2);
auto str2 = createRandomString(msgSize/2);
auto startTime = std::chrono::steady_clock::now();
for (unsigned int i = 0; i < msgCount; i++)
{
auto result = client.concatenateTwoStrings(str1, str2);
assert(result.size() == str1.size() + str2.size());
assert(result.size() == msgSize);
}
auto stopTime = std::chrono::steady_clock::now();
std::cout << "Called " << msgCount << " methods in: " << std::chrono::duration_cast<std::chrono::milliseconds>(stopTime - startTime).count() << " ms" << std::endl;
std::this_thread::sleep_for(1000ms);
}
}
{
PerftestClient client(destinationName, objectPath);
msgSize = 1000;
std::cout << std::endl << "** Measuring method calls of size " << msgSize << " bytes (" << repetitions << " repetitions)..." << std::endl << std::endl;
for (unsigned int r = 0; r < repetitions; ++r)
{
auto str1 = createRandomString(msgSize/2);
auto str2 = createRandomString(msgSize/2);
auto startTime = std::chrono::steady_clock::now();
for (unsigned int i = 0; i < msgCount; i++)
{
auto result = client.concatenateTwoStrings(str1, str2);
assert(result.size() == str1.size() + str2.size());
assert(result.size() == msgSize);
}
auto stopTime = std::chrono::steady_clock::now();
std::cout << "Called " << msgCount << " methods in: " << std::chrono::duration_cast<std::chrono::milliseconds>(stopTime - startTime).count() << " ms" << std::endl;
std::this_thread::sleep_for(1000ms);
}
auto stopTime = std::chrono::steady_clock::now();
std::cout << "Called " << msgCount << " methods in: " << std::chrono::duration_cast<std::chrono::milliseconds>(stopTime - startTime).count() << " ms" << std::endl;
std::this_thread::sleep_for(1000ms);
}
return 0;