mirror of
https://github.com/KjellKod/g3log.git
synced 2025-01-19 08:46:42 +01:00
Bugfix: sinkhandle can now be used to call, asynchronously, functions with more return types than std::string
This commit is contained in:
parent
ffb4d86c1e
commit
1ed4bcb38c
@ -9,6 +9,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
||||
#include "g2sinkwrapper.hpp"
|
||||
#include "active.hpp"
|
||||
@ -64,7 +65,7 @@ struct Sink : public SinkWrapper {
|
||||
}
|
||||
|
||||
template<typename Call, typename... Args>
|
||||
auto send(Call call, Args... args)-> std::future < decltype(bind(call, _real_sink.get(), args...)()) > {
|
||||
auto async(Call call, Args... args)-> std::future< typename std::result_of<decltype(call)(T, Args...)>::type> {
|
||||
return g2::spawn_task(std::bind(call, _real_sink.get(), args...), _bg.get());
|
||||
}
|
||||
};
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include "g2sink.hpp"
|
||||
|
||||
namespace g2 {
|
||||
@ -34,14 +35,13 @@ namespace g2 {
|
||||
// Asynchronous call to the real sink. If the real sink is already deleted
|
||||
// the returned future will contain a bad_weak_ptr exception instead of the
|
||||
// call result.
|
||||
template<typename Call, typename... Args>
|
||||
auto call(Call call, Args... args) -> decltype(_sink.lock()->send(call, args...)) {
|
||||
template<typename AsyncCall, typename... Args>
|
||||
auto call(AsyncCall func , Args... args) -> std::future<typename std::result_of<decltype(func)(T, Args...)>::type> {
|
||||
try {
|
||||
std::shared_ptr<internal::Sink<T>> sink(_sink);
|
||||
return sink->send(call, args...);
|
||||
return sink->async(func, args...);
|
||||
} catch (const std::bad_weak_ptr& e) {
|
||||
T* t = nullptr;
|
||||
typedef decltype(std::bind(call, t, args...)()) PromiseType;
|
||||
typedef typename std::result_of<decltype(func)(T, Args...)>::type PromiseType;
|
||||
std::promise<PromiseType> promise;
|
||||
promise.set_exception(std::make_exception_ptr(e));
|
||||
return std::move(promise.get_future());
|
||||
|
@ -11,10 +11,12 @@
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
|
||||
#include "testing_helpers.h"
|
||||
#include "g2logmessage.hpp"
|
||||
#include "g2logworker.hpp"
|
||||
#include "std2_make_unique.hpp"
|
||||
|
||||
using namespace testing_helpers;
|
||||
using namespace std;
|
||||
@ -88,3 +90,75 @@ TEST(ConceptSink, OneHundredSinks) {
|
||||
|
||||
cout << "test one hundred sinks is finished finished\n";
|
||||
}
|
||||
|
||||
struct VoidReceiver {
|
||||
std::atomic<int>* _atomicCounter;
|
||||
explicit VoidReceiver(std::atomic<int>* counter) : _atomicCounter(counter){}
|
||||
|
||||
void receiveMsg(std::string msg){ /*ignored*/}
|
||||
void incrementAtomic(){
|
||||
(*_atomicCounter)++;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(ConceptSink, VoidCall__NoCall_ExpectingNoAdd) {
|
||||
std::atomic<int> counter{0};
|
||||
{
|
||||
std::unique_ptr<g2::LogWorker> worker{g2::LogWorker::createWithNoSink()};
|
||||
auto handle = worker->addSink(std2::make_unique<VoidReceiver>(&counter), &VoidReceiver::receiveMsg);
|
||||
}
|
||||
EXPECT_EQ(counter, 0);
|
||||
}
|
||||
|
||||
TEST(ConceptSink, VoidCall__OneCall_ExpectingOneAdd) {
|
||||
std::atomic<int> counter{0};
|
||||
{
|
||||
std::unique_ptr<g2::LogWorker> worker{g2::LogWorker::createWithNoSink()};
|
||||
auto handle = worker->addSink(std2::make_unique<VoidReceiver>(&counter), &VoidReceiver::receiveMsg);
|
||||
std::future<void> ignored = handle->call(&VoidReceiver::incrementAtomic);
|
||||
}
|
||||
EXPECT_EQ(counter, 1);
|
||||
}
|
||||
|
||||
TEST(ConceptSink, VoidCall__TwoCalls_ExpectingTwoAdd) {
|
||||
std::atomic<int> counter{0};
|
||||
{
|
||||
std::unique_ptr<g2::LogWorker> worker{g2::LogWorker::createWithNoSink()};
|
||||
auto handle = worker->addSink(std2::make_unique<VoidReceiver>(&counter), &VoidReceiver::receiveMsg);
|
||||
auto voidFuture1 = handle->call(&VoidReceiver::incrementAtomic);
|
||||
auto voidFuture2 = handle->call(&VoidReceiver::incrementAtomic);
|
||||
voidFuture1.wait();
|
||||
EXPECT_TRUE(counter >= 1);
|
||||
}
|
||||
EXPECT_EQ(counter, 2);
|
||||
}
|
||||
|
||||
|
||||
struct IntReceiver {
|
||||
std::atomic<int>* _atomicCounter;
|
||||
explicit IntReceiver(std::atomic<int>* counter) : _atomicCounter(counter){}
|
||||
|
||||
void receiveMsg(std::string msg){ /*ignored*/}
|
||||
int incrementAtomic(){
|
||||
(*_atomicCounter)++;
|
||||
int value = *_atomicCounter;
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(ConceptSink, IntCall__TwoCalls_ExpectingTwoAdd) {
|
||||
std::atomic<int> counter{0};
|
||||
{
|
||||
std::unique_ptr<g2::LogWorker> worker{g2::LogWorker::createWithNoSink()};
|
||||
auto handle = worker->addSink(std2::make_unique<IntReceiver>(&counter), &IntReceiver::receiveMsg);
|
||||
std::future<int> intFuture1 = handle->call(&IntReceiver::incrementAtomic);
|
||||
EXPECT_EQ(intFuture1.get(), 1);
|
||||
EXPECT_EQ(counter, 1);
|
||||
|
||||
auto intFuture2 = handle->call(&IntReceiver::incrementAtomic);
|
||||
EXPECT_EQ(intFuture2.get(), 2);
|
||||
|
||||
}
|
||||
EXPECT_EQ(counter, 2);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user