From 1ed4bcb38cda5a0834085c19284e8d01027f15f4 Mon Sep 17 00:00:00 2001 From: KjellKod Date: Tue, 11 Feb 2014 20:00:20 -0700 Subject: [PATCH] Bugfix: sinkhandle can now be used to call, asynchronously, functions with more return types than std::string --- g2log/src/g2sink.hpp | 3 +- g2log/src/g2sinkhandle.hpp | 10 ++--- g2log/test_unit/test_sink.cpp | 74 +++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 6 deletions(-) diff --git a/g2log/src/g2sink.hpp b/g2log/src/g2sink.hpp index 1f374f6..0501ddb 100644 --- a/g2log/src/g2sink.hpp +++ b/g2log/src/g2sink.hpp @@ -9,6 +9,7 @@ #include #include +#include #include "g2sinkwrapper.hpp" #include "active.hpp" @@ -64,7 +65,7 @@ struct Sink : public SinkWrapper { } template - 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::type> { return g2::spawn_task(std::bind(call, _real_sink.get(), args...), _bg.get()); } }; diff --git a/g2log/src/g2sinkhandle.hpp b/g2log/src/g2sinkhandle.hpp index 0bda393..115cbed 100644 --- a/g2log/src/g2sinkhandle.hpp +++ b/g2log/src/g2sinkhandle.hpp @@ -9,6 +9,7 @@ #include #include +#include #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 - auto call(Call call, Args... args) -> decltype(_sink.lock()->send(call, args...)) { + template + auto call(AsyncCall func , Args... args) -> std::future::type> { try { std::shared_ptr> 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::type PromiseType; std::promise promise; promise.set_exception(std::make_exception_ptr(e)); return std::move(promise.get_future()); diff --git a/g2log/test_unit/test_sink.cpp b/g2log/test_unit/test_sink.cpp index 97bcb38..f5971ad 100644 --- a/g2log/test_unit/test_sink.cpp +++ b/g2log/test_unit/test_sink.cpp @@ -11,10 +11,12 @@ #include #include #include +#include #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* _atomicCounter; + explicit VoidReceiver(std::atomic* counter) : _atomicCounter(counter){} + + void receiveMsg(std::string msg){ /*ignored*/} + void incrementAtomic(){ + (*_atomicCounter)++; + } +}; + +TEST(ConceptSink, VoidCall__NoCall_ExpectingNoAdd) { + std::atomic counter{0}; + { + std::unique_ptr worker{g2::LogWorker::createWithNoSink()}; + auto handle = worker->addSink(std2::make_unique(&counter), &VoidReceiver::receiveMsg); + } + EXPECT_EQ(counter, 0); +} + +TEST(ConceptSink, VoidCall__OneCall_ExpectingOneAdd) { + std::atomic counter{0}; + { + std::unique_ptr worker{g2::LogWorker::createWithNoSink()}; + auto handle = worker->addSink(std2::make_unique(&counter), &VoidReceiver::receiveMsg); + std::future ignored = handle->call(&VoidReceiver::incrementAtomic); + } + EXPECT_EQ(counter, 1); +} + +TEST(ConceptSink, VoidCall__TwoCalls_ExpectingTwoAdd) { + std::atomic counter{0}; + { + std::unique_ptr worker{g2::LogWorker::createWithNoSink()}; + auto handle = worker->addSink(std2::make_unique(&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* _atomicCounter; + explicit IntReceiver(std::atomic* counter) : _atomicCounter(counter){} + + void receiveMsg(std::string msg){ /*ignored*/} + int incrementAtomic(){ + (*_atomicCounter)++; + int value = *_atomicCounter; + return value; + } +}; + +TEST(ConceptSink, IntCall__TwoCalls_ExpectingTwoAdd) { + std::atomic counter{0}; + { + std::unique_ptr worker{g2::LogWorker::createWithNoSink()}; + auto handle = worker->addSink(std2::make_unique(&counter), &IntReceiver::receiveMsg); + std::future 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); +} +