Commit 187cf0a0 authored by James Sedgwick's avatar James Sedgwick Committed by dcsommer

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
parent ea078b87
...@@ -31,7 +31,7 @@ template <class T> class FunctionObserver; ...@@ -31,7 +31,7 @@ template <class T> class FunctionObserver;
template <class T> template <class T>
struct Observer { struct Observer {
// These are what it means to be an 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 onError(Error) = 0;
virtual void onCompleted() = 0; virtual void onCompleted() = 0;
...@@ -79,7 +79,7 @@ struct Observer { ...@@ -79,7 +79,7 @@ struct Observer {
/// make one of these directly - instead use the Observer::create() methods. /// make one of these directly - instead use the Observer::create() methods.
template <class T> template <class T>
struct FunctionObserver : public Observer<T> { struct FunctionObserver : public Observer<T> {
typedef std::function<void(T)> OnNext; typedef std::function<void(const T&)> OnNext;
typedef std::function<void(Error)> OnError; typedef std::function<void(Error)> OnError;
typedef std::function<void()> OnCompleted; typedef std::function<void()> OnCompleted;
...@@ -92,7 +92,7 @@ struct FunctionObserver : public Observer<T> { ...@@ -92,7 +92,7 @@ struct FunctionObserver : public Observer<T> {
onCompleted_(std::forward<C>(c)) onCompleted_(std::forward<C>(c))
{} {}
void onNext(T val) override { void onNext(const T& val) override {
if (onNext_) onNext_(val); if (onNext_) onNext_(val);
} }
......
...@@ -27,7 +27,7 @@ namespace folly { namespace wangle { ...@@ -27,7 +27,7 @@ namespace folly { namespace wangle {
template <class T> template <class T>
struct Subject : public Observable<T>, public Observer<T> { struct Subject : public Observable<T>, public Observer<T> {
typedef typename Observable<T>::ObserversGuard ObserversGuard; typedef typename Observable<T>::ObserversGuard ObserversGuard;
void onNext(T val) override { void onNext(const T& val) override {
ObserversGuard guard(this); ObserversGuard guard(this);
for (auto& kv : Observable<T>::getObservers()) { for (auto& kv : Observable<T>::getObservers()) {
kv.second->onNext(val); kv.second->onNext(val);
......
...@@ -105,3 +105,43 @@ TEST(RxTest, SubscribeUnsubscribeDuringCallback) { ...@@ -105,3 +105,43 @@ TEST(RxTest, SubscribeUnsubscribeDuringCallback) {
EXPECT_EQ(2, outerCount); EXPECT_EQ(2, outerCount);
EXPECT_EQ(0, innerCount); EXPECT_EQ(0, innerCount);
} }
// Move only type
typedef std::unique_ptr<int> MO;
static MO makeMO() { return folly::make_unique<int>(1); }
template <typename T>
static ObserverPtr<T> makeMOObserver() {
return Observer<T>::create([](const T& mo) {
EXPECT_EQ(1, *mo);
});
}
TEST(RxTest, MoveOnlyRvalue) {
Subject<MO> subject;
auto s1 = subject.subscribe(makeMOObserver<MO>());
auto s2 = subject.subscribe(makeMOObserver<MO>());
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 <typename T>
static ObserverPtr<T> makeCOObserver() {
return Observer<T>::create([](const T& mo) {});
}
TEST(RxTest, CopyOnly) {
Subject<CO> subject;
auto s1 = subject.subscribe(makeCOObserver<CO>());
CO co;
subject.onNext(co);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment