// Copyright (c) Facebook, Inc. and its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "yarpl/observable/Subscription.h" #include #include #include namespace yarpl { namespace observable { /** * Implementation that allows checking if a Subscription is cancelled. */ void Subscription::cancel() { cancelled_ = true; // Lock must be obtained here and not in the range expression for it to // apply to the loop body. auto locked = tiedSubscriptions_.wlock(); for (auto& subscription : *locked) { subscription->cancel(); } } bool Subscription::isCancelled() const { return cancelled_; } void Subscription::tieSubscription(std::shared_ptr subscription) { CHECK(subscription); if (isCancelled()) { subscription->cancel(); } tiedSubscriptions_.wlock()->push_back(std::move(subscription)); } std::shared_ptr Subscription::create( std::function onCancel) { class CallbackSubscription : public Subscription { public: explicit CallbackSubscription(std::function onCancel) : onCancel_(std::move(onCancel)) {} void cancel() override { bool expected = false; // mark cancelled 'true' and only if successful invoke 'onCancel()' if (cancelled_.compare_exchange_strong(expected, true)) { onCancel_(); // Lock must be obtained here and not in the range expression for it to // apply to the loop body. auto locked = tiedSubscriptions_.wlock(); for (auto& subscription : *locked) { subscription->cancel(); } } } private: std::function onCancel_; }; return std::make_shared(std::move(onCancel)); } std::shared_ptr Subscription::create( std::atomic_bool& cancelled) { return create([&cancelled]() { cancelled = true; }); } std::shared_ptr Subscription::create() { return std::make_shared(); } } // namespace observable } // namespace yarpl