Rocket.Chat.ReactNative/ios/Pods/Flipper-RSocket/rsocket/internal/SwappableEventBase.h

82 lines
2.9 KiB
C++

// 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.
#pragma once
#include <folly/Function.h>
#include <folly/io/async/EventBase.h>
#include <mutex>
namespace rsocket {
// SwappableEventBase provides an interface similar to EventBase, allowing
// an underlying EventBase to be changed, and to force callbacks to be
// executed in serial order regardless of which underlying EventBase they are
// enqueued on.
class SwappableEventBase final {
// std::mutex doesn't like being in a std::pair
struct MutexBoolPair {
// lock for synchronization on destroyed_, and all members of the parent SEB
std::mutex l_;
// has the SEB's destructor ran?
bool destroyed_{false};
};
public:
using CbFunc = folly::Function<void(folly::EventBase&)>;
explicit SwappableEventBase(folly::EventBase& eb)
: eb_(&eb),
nextEb_(nullptr),
hasSebDtored_(std::make_shared<MutexBoolPair>()) {}
// Run or enqueue 'cb', in order with all prior calls to runInEventBaseThread
// If setEventBase has been called, and the prior EventBase is still
// processing tasks, runInEventBaseThread will queue tasks until the old EB's
// tasks have all completed. After that, SwappableEventBase will enqueue
// buffered tasks on the last EB set via setEventBase.
//
// Callbacks take a single parameter: the underlying EventBase
// that the callback is executing on.
bool runInEventBaseThread(CbFunc cb);
// Sets the EventBase to enqueue callbacks on, once the current EventBase has
// drained
void setEventBase(folly::EventBase& newEb);
// SwappableEventBase will enqueue tasks on the old eventbase if
// there are any pending by the time the SEB is destroyed
~SwappableEventBase();
private:
folly::EventBase* eb_;
folly::EventBase* nextEb_; // also indicate if we're in the middle of a swap
// is the SwappableEventBase waiting for the current EventBase to finish
// draining?
bool isSwapping() const;
// shared data between the SwappableEventBase and anyone else holding
// a reference to the SEB (eg, swapping lambda in setEventBase) to avoid
// accessing a dangling pointer in the case where the SEB has already
// had its destructor run
mutable std::shared_ptr<MutexBoolPair> hasSebDtored_;
// tasks enqueued with runInEventBaseThread while the SEB is waiting for
// the old EventBase* eb_ to drain
std::vector<CbFunc> queued_;
};
} // namespace rsocket