CLEANFILES =
+
noinst_PROGRAMS = generate_fingerprint_tables
generate_fingerprint_tables_SOURCES = build/GenerateFingerprintTables.cpp
generate_fingerprint_tables_LDADD = libfollybase.la
Func function_;
};
+ // Like FunctionLoopCallback, but saves one allocation. Use with caution.
+ //
+ // The caller is responsible for maintaining the lifetime of this callback
+ // until after the point at which the contained function is called.
+ class StackFunctionLoopCallback : public LoopCallback {
+ public:
+ explicit StackFunctionLoopCallback(Func&& function)
+ : function_(std::move(function)) {}
+ void runLoopCallback() noexcept override {
+ Func(std::move(function_))();
+ }
+
+ private:
+ Func function_;
+ };
+
/**
* Create a new EventBase object.
*
#include <thread>
+#include <folly/Function.h>
#include <folly/Memory.h>
#include <folly/io/async/EventBaseManager.h>
static void run(EventBaseManager* ebm, EventBase* eb) {
ebm->setEventBase(eb, false);
eb->loopForever();
- ebm->clearEventBase();
+
+ // must destruct in io thread for on-destruction callbacks
+ EventBase::StackFunctionLoopCallback cb([=] { ebm->clearEventBase(); });
+ eb->runOnDestruction(&cb);
+ eb->~EventBase();
}
ScopedEventBaseThread::ScopedEventBaseThread()
ScopedEventBaseThread::ScopedEventBaseThread(EventBaseManager* ebm)
: ebm_(ebm ? ebm : EventBaseManager::get()) {
+ new (&eb_) EventBase();
th_ = thread(run, ebm_, &eb_);
eb_.waitUntilRunning();
}
#include <memory>
#include <thread>
+
#include <folly/io/async/EventBase.h>
namespace folly {
return &eb_;
}
+ std::thread::id getThreadId() const {
+ return th_.get_id();
+ }
+
private:
ScopedEventBaseThread(ScopedEventBaseThread&& other) = delete;
ScopedEventBaseThread& operator=(ScopedEventBaseThread&& other) = delete;
ScopedEventBaseThread& operator=(const ScopedEventBaseThread& other) = delete;
EventBaseManager* ebm_;
- mutable EventBase eb_;
+ union {
+ mutable EventBase eb_;
+ };
std::thread th_;
};
#include <chrono>
#include <folly/Baton.h>
+#include <folly/Optional.h>
#include <folly/io/async/EventBaseManager.h>
#include <folly/portability/GTest.h>
sebt_eb->runInEventBaseThreadAndWait([&] { ebm_eb = ebm.getEventBase(); });
EXPECT_EQ(uintptr_t(sebt_eb), uintptr_t(ebm_eb));
}
+
+TEST_F(ScopedEventBaseThreadTest, eb_dtor_in_io_thread) {
+ Optional<ScopedEventBaseThread> sebt;
+ sebt.emplace();
+ auto const io_thread_id = sebt->getThreadId();
+ EXPECT_NE(this_thread::get_id(), io_thread_id) << "sanity";
+
+ auto const eb = sebt->getEventBase();
+ thread::id eb_dtor_thread_id;
+ eb->runOnDestruction(new EventBase::FunctionLoopCallback(
+ [&] { eb_dtor_thread_id = this_thread::get_id(); }));
+ sebt.clear();
+ EXPECT_EQ(io_thread_id, eb_dtor_thread_id);
+}