From 187cf0a0dadb9d1837aceea5030aad7914cd8646 Mon Sep 17 00:00:00 2001 From: James Sedgwick Date: Wed, 15 Oct 2014 15:58:44 -0700 Subject: [PATCH] support for move-only types Summary: universal references and perfect forwarding to the rescue Test Plan: added demonstrative unit tests Reviewed By: hans@fb.com Subscribers: trunkagent, fugalh, njormrod, bmatheny FB internal diff: D1592032 Tasks: 5283342 --- folly/experimental/wangle/rx/Observer.h | 6 +-- folly/experimental/wangle/rx/Subject.h | 2 +- folly/experimental/wangle/rx/test/RxTest.cpp | 40 ++++++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/folly/experimental/wangle/rx/Observer.h b/folly/experimental/wangle/rx/Observer.h index e2a7486b..cfe49dd9 100644 --- a/folly/experimental/wangle/rx/Observer.h +++ b/folly/experimental/wangle/rx/Observer.h @@ -31,7 +31,7 @@ template class FunctionObserver; template struct Observer { // These are what it means to be an Observer. - virtual void onNext(T) = 0; + virtual void onNext(const T&) = 0; virtual void onError(Error) = 0; virtual void onCompleted() = 0; @@ -79,7 +79,7 @@ struct Observer { /// make one of these directly - instead use the Observer::create() methods. template struct FunctionObserver : public Observer { - typedef std::function OnNext; + typedef std::function OnNext; typedef std::function OnError; typedef std::function OnCompleted; @@ -92,7 +92,7 @@ struct FunctionObserver : public Observer { onCompleted_(std::forward(c)) {} - void onNext(T val) override { + void onNext(const T& val) override { if (onNext_) onNext_(val); } diff --git a/folly/experimental/wangle/rx/Subject.h b/folly/experimental/wangle/rx/Subject.h index 67857205..0cb357fe 100644 --- a/folly/experimental/wangle/rx/Subject.h +++ b/folly/experimental/wangle/rx/Subject.h @@ -27,7 +27,7 @@ namespace folly { namespace wangle { template struct Subject : public Observable, public Observer { typedef typename Observable::ObserversGuard ObserversGuard; - void onNext(T val) override { + void onNext(const T& val) override { ObserversGuard guard(this); for (auto& kv : Observable::getObservers()) { kv.second->onNext(val); diff --git a/folly/experimental/wangle/rx/test/RxTest.cpp b/folly/experimental/wangle/rx/test/RxTest.cpp index a62d11ce..ab44657a 100644 --- a/folly/experimental/wangle/rx/test/RxTest.cpp +++ b/folly/experimental/wangle/rx/test/RxTest.cpp @@ -105,3 +105,43 @@ TEST(RxTest, SubscribeUnsubscribeDuringCallback) { EXPECT_EQ(2, outerCount); EXPECT_EQ(0, innerCount); } + +// Move only type +typedef std::unique_ptr MO; +static MO makeMO() { return folly::make_unique(1); } +template +static ObserverPtr makeMOObserver() { + return Observer::create([](const T& mo) { + EXPECT_EQ(1, *mo); + }); +} + +TEST(RxTest, MoveOnlyRvalue) { + Subject subject; + auto s1 = subject.subscribe(makeMOObserver()); + auto s2 = subject.subscribe(makeMOObserver()); + auto mo = makeMO(); + // Can't bind lvalues to rvalue references + // subject.onNext(mo); + subject.onNext(std::move(mo)); + subject.onNext(makeMO()); +} + +// Copy only type +struct CO { + CO() = default; + CO(const CO&) = default; + CO(CO&&) = delete; +}; + +template +static ObserverPtr makeCOObserver() { + return Observer::create([](const T& mo) {}); +} + +TEST(RxTest, CopyOnly) { + Subject subject; + auto s1 = subject.subscribe(makeCOObserver()); + CO co; + subject.onNext(co); +} -- 2.34.1