Commit 652d34b9 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot 2

Some cleanups to folly::EventBase after converting to folly::Function

Summary:[Folly] Some cleanups to `folly::EventBase` after converting to `folly::Function`.

* Fix up some comments referring to `std::function`.
* Remove the `SmallFunctor` bits - `folly::Function` takes over for that.
* Remove `runFunctionPtr` - it's unused.

Reviewed By: spacedentist

Differential Revision: D3155511

fb-gh-sync-id: 38c75d1254993f59c8eaa7826dc8d9facb50a3a1
fbshipit-source-id: 38c75d1254993f59c8eaa7826dc8d9facb50a3a1
parent 2dafcc98
...@@ -712,28 +712,6 @@ bool EventBase::nothingHandledYet() { ...@@ -712,28 +712,6 @@ bool EventBase::nothingHandledYet() {
return (nextLoopCnt_ != latestLoopCnt_); return (nextLoopCnt_ != latestLoopCnt_);
} }
/* static */
void EventBase::runFunctionPtr(Cob* fn) {
// The function should never throw an exception, because we have no
// way of knowing what sort of error handling to perform.
//
// If it does throw, log a message and abort the program.
try {
(*fn)();
} catch (const std::exception &ex) {
LOG(ERROR) << "runInEventBaseThread() std::function threw a "
<< typeid(ex).name() << " exception: " << ex.what();
abort();
} catch (...) {
LOG(ERROR) << "runInEventBaseThread() std::function threw an exception";
abort();
}
// The function object was allocated by runInEventBaseThread().
// Delete it once it has been run.
delete fn;
}
void EventBase::attachTimeoutManager(AsyncTimeout* obj, void EventBase::attachTimeoutManager(AsyncTimeout* obj,
InternalEnum internal) { InternalEnum internal) {
......
...@@ -294,13 +294,12 @@ class EventBase : private boost::noncopyable, ...@@ -294,13 +294,12 @@ class EventBase : private boost::noncopyable,
void runInLoop(LoopCallback* callback, bool thisIteration = false); void runInLoop(LoopCallback* callback, bool thisIteration = false);
/** /**
* Convenience function to call runInLoop() with a std::function. * Convenience function to call runInLoop() with a folly::Function.
* *
* This creates a LoopCallback object to wrap the std::function, and invoke * This creates a LoopCallback object to wrap the folly::Function, and invoke
* the std::function when the loop callback fires. This is slightly more * the folly::Function when the loop callback fires. This is slightly more
* expensive than defining your own LoopCallback, but more convenient in * expensive than defining your own LoopCallback, but more convenient in
* areas that aren't performance sensitive where you just want to use * areas that aren't too performance sensitive.
* std::bind. (std::bind is fairly slow on even by itself.)
* *
* This method may only be called from the EventBase's thread. This * This method may only be called from the EventBase's thread. This
* essentially allows an event handler to schedule an additional callback to * essentially allows an event handler to schedule an additional callback to
...@@ -370,10 +369,11 @@ class EventBase : private boost::noncopyable, ...@@ -370,10 +369,11 @@ class EventBase : private boost::noncopyable,
/** /**
* Run the specified function in the EventBase's thread * Run the specified function in the EventBase's thread
* *
* This version of runInEventBaseThread() takes a std::function object. * This version of runInEventBaseThread() takes a folly::Function object.
* Note that this is less efficient than the version that takes a plain * Note that this may be less efficient than the version that takes a plain
* function pointer and void* argument, as it has to allocate memory to copy * function pointer and void* argument, if moving the function is expensive
* the std::function object. * (e.g., if it wraps a lambda which captures some values with expensive move
* constructors).
* *
* If the loop is terminated (and never later restarted) before it has a * If the loop is terminated (and never later restarted) before it has a
* chance to run the requested function, the function will be run upon the * chance to run the requested function, the function will be run upon the
...@@ -608,10 +608,6 @@ class EventBase : private boost::noncopyable, ...@@ -608,10 +608,6 @@ class EventBase : private boost::noncopyable,
*/ */
bool nothingHandledYet(); bool nothingHandledYet();
// --------- libevent callbacks (not for client use) ------------
static void runFunctionPtr(Cob* fn);
// small object used as a callback arg with enough info to execute the // small object used as a callback arg with enough info to execute the
// appropriate client-provided Cob // appropriate client-provided Cob
class CobTimeout : public AsyncTimeout { class CobTimeout : public AsyncTimeout {
...@@ -730,80 +726,21 @@ class EventBase : private boost::noncopyable, ...@@ -730,80 +726,21 @@ class EventBase : private boost::noncopyable,
std::unordered_set<detail::EventBaseLocalBaseBase*> localStorageToDtor_; std::unordered_set<detail::EventBaseLocalBaseBase*> localStorageToDtor_;
}; };
namespace detail {
/**
* Define a small functor (2 pointers) and specialize
* std::__is_location_invariant so that std::function does not require
* memory allocation.
*
* std::function<void()> func = SmallFunctor{f, p};
*
* TODO(lucian): remove this hack once GCC <= 4.9 are deprecated.
* In GCC >= 5.0 just use a lambda like:
*
* std::function<void()> func = [=] { f(p); };
*
* See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61909
*/
template <class T>
struct SmallFunctor {
void (*fn)(T*);
T* p;
void operator()() { fn(p); }
};
} // detail
template <typename T> template <typename T>
bool EventBase::runInEventBaseThread(void (*fn)(T*), T* arg) { bool EventBase::runInEventBaseThread(void (*fn)(T*), T* arg) {
return runInEventBaseThread(detail::SmallFunctor<T>{fn, arg}); return runInEventBaseThread([=] { fn(arg); });
} }
template <typename T> template <typename T>
bool EventBase::runInEventBaseThreadAndWait(void (*fn)(T*), T* arg) { bool EventBase::runInEventBaseThreadAndWait(void (*fn)(T*), T* arg) {
return runInEventBaseThreadAndWait(detail::SmallFunctor<T>{fn, arg}); return runInEventBaseThreadAndWait([=] { fn(arg); });
} }
template <typename T> template <typename T>
bool EventBase::runImmediatelyOrRunInEventBaseThreadAndWait(void (*fn)(T*), bool EventBase::runImmediatelyOrRunInEventBaseThreadAndWait(
T* arg) { void (*fn)(T*),
return runImmediatelyOrRunInEventBaseThreadAndWait( T* arg) {
detail::SmallFunctor<T>{fn, arg}); return runImmediatelyOrRunInEventBaseThreadAndWait([=] { fn(arg); });
} }
} // folly } // folly
FOLLY_NAMESPACE_STD_BEGIN
/**
* GCC's libstdc++ uses __is_location_invariant to decide wether to
* use small object optimization and embed the functor's contents in
* the std::function object.
*
* (gcc 4.9) $ libstdc++-v3/include/std/functional
* template<typename _Tp>
* struct __is_location_invariant
* : integral_constant<bool, (is_pointer<_Tp>::value
* || is_member_pointer<_Tp>::value)>
* { };
*
* (gcc 5.0) $ libstdc++-v3/include/std/functional
*
* template<typename _Tp>
* struct __is_location_invariant
* : is_trivially_copyable<_Tp>::type
* { };
*
*
* NOTE: Forward declare so this doesn't break when using other
* standard libraries: it just wont have any effect.
*/
template <typename T>
struct __is_location_invariant;
template <typename T>
struct __is_location_invariant<folly::detail::SmallFunctor<T>>
: public std::true_type {};
FOLLY_NAMESPACE_STD_END
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