X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Fio%2Fasync%2FVirtualEventBase.h;h=a1194d82ab3f994d0106b1e4262e5348bd2cce1a;hb=d9bf016dbcafb3c7c3fac4d081c5e63bed6516c5;hp=ebe8118279e57e69b886cfaad52a35b40298bc8f;hpb=853adb4fb8812b65e360dc77ae14f6013a19119f;p=folly.git diff --git a/folly/io/async/VirtualEventBase.h b/folly/io/async/VirtualEventBase.h index ebe81182..a1194d82 100644 --- a/folly/io/async/VirtualEventBase.h +++ b/folly/io/async/VirtualEventBase.h @@ -1,5 +1,5 @@ /* - * Copyright 2016 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,8 @@ #pragma once +#include + #include #include #include @@ -27,7 +29,7 @@ namespace folly { * * Multiple VirtualEventBases can be backed by a single EventBase. Similarly * to EventBase, VirtualEventBase implements loopKeepAlive() functionality, - * which allows callbacks holding LoopKeepAlive token to keep EventBase looping + * which allows callbacks holding KeepAlive token to keep EventBase looping * until they are complete. * * VirtualEventBase destructor blocks until all its KeepAliveTokens are released @@ -59,14 +61,6 @@ class VirtualEventBase : public folly::Executor, public folly::TimeoutManager { */ void runOnDestruction(EventBase::LoopCallback* callback); - /** - * @see EventBase::runInLoop - */ - template - void runInLoop(F&& f, bool thisIteration = false) { - evb_.runInLoop(std::forward(f), thisIteration); - } - /** * VirtualEventBase destructor blocks until all tasks scheduled through its * runInEventBaseThread are complete. @@ -75,11 +69,11 @@ class VirtualEventBase : public folly::Executor, public folly::TimeoutManager { */ template void runInEventBaseThread(F&& f) { - // LoopKeepAlive token has to be released in the EventBase thread. If - // runInEventBaseThread() fails, we can't extract the LoopKeepAlive token + // KeepAlive token has to be released in the EventBase thread. If + // runInEventBaseThread() fails, we can't extract the KeepAlive token // from the callback to properly release it. CHECK(evb_.runInEventBaseThread([ - keepAlive = loopKeepAliveAtomic(), + keepAliveToken = getKeepAliveToken(), f = std::forward(f) ]() mutable { f(); })); } @@ -122,58 +116,54 @@ class VirtualEventBase : public folly::Executor, public folly::TimeoutManager { runInEventBaseThread(std::move(f)); } - struct LoopKeepAliveDeleter { - void operator()(VirtualEventBase* evb) { - DCHECK(evb->getEventBase().inRunningEventBaseThread()); - if (evb->loopKeepAliveCountAtomic_.load()) { - evb->loopKeepAliveCount_ += evb->loopKeepAliveCountAtomic_.exchange(0); - } - DCHECK(evb->loopKeepAliveCount_ > 0); - if (--evb->loopKeepAliveCount_ == 0) { - evb->loopKeepAliveBaton_.post(); - } - } - }; - using LoopKeepAlive = std::unique_ptr; - /** * Returns you a handle which prevents VirtualEventBase from being destroyed. - * LoopKeepAlive handle can be released from EventBase loop only. - * - * loopKeepAlive() can be called from EventBase thread only. + * KeepAlive handle can be released from EventBase loop only. */ - LoopKeepAlive loopKeepAlive() { - DCHECK(evb_.isInEventBaseThread()); - ++loopKeepAliveCount_; - return LoopKeepAlive(this); - } + KeepAlive getKeepAliveToken() override { + DCHECK(loopKeepAliveCount_ + loopKeepAliveCountAtomic_.load() > 0); - /** - * Thread-safe version of loopKeepAlive() - */ - LoopKeepAlive loopKeepAliveAtomic() { if (evb_.inRunningEventBaseThread()) { - return loopKeepAlive(); + ++loopKeepAliveCount_; + } else { + ++loopKeepAliveCountAtomic_; } - ++loopKeepAliveCountAtomic_; - return LoopKeepAlive(this); + return makeKeepAlive(); } bool inRunningEventBaseThread() const { return evb_.inRunningEventBaseThread(); } + protected: + void keepAliveRelease() override { + DCHECK(getEventBase().inRunningEventBaseThread()); + if (loopKeepAliveCountAtomic_.load()) { + loopKeepAliveCount_ += loopKeepAliveCountAtomic_.exchange(0); + } + DCHECK(loopKeepAliveCount_ > 0); + if (--loopKeepAliveCount_ == 0) { + destroyImpl(); + } + } + private: + friend class EventBase; + + std::future destroy(); + void destroyImpl(); + using LoopCallbackList = EventBase::LoopCallback::List; EventBase& evb_; - ssize_t loopKeepAliveCount_{0}; + ssize_t loopKeepAliveCount_{1}; std::atomic loopKeepAliveCountAtomic_{0}; - folly::Baton<> loopKeepAliveBaton_; - LoopKeepAlive loopKeepAlive_; + std::promise destroyPromise_; + std::future destroyFuture_{destroyPromise_.get_future()}; + KeepAlive loopKeepAlive_{makeKeepAlive()}; - EventBase::LoopKeepAlive evbLoopKeepAlive_; + KeepAlive evbLoopKeepAlive_; folly::Synchronized onDestructionCallbacks_; };