Skip to content

Commit

Permalink
[callback] update OnceCallback to clear moved-from rvalue reference
Browse files Browse the repository at this point in the history
This commit updates the `OnceCallback` move constructor and move
assignment operator to ensure that the passed-in rvalue reference is
cleared.
  • Loading branch information
abtink committed Jun 16, 2023
1 parent 34c3899 commit 83e2b98
Showing 1 changed file with 18 additions and 6 deletions.
24 changes: 18 additions & 6 deletions src/common/callback.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,29 +63,41 @@ template <typename R, typename... Args> class OnceCallback<R(Args...)>
// compiling issue which trying to instantiate this template constructor
// for use cases like `::mOnceCallback(aOnceCallback)`.
template <typename T, typename = typename std::enable_if<!std::is_same<OnceCallback, T>::value>::type>
OnceCallback(T &&func)
: mFunc(std::forward<T>(func))
OnceCallback(T &&aFunc)
: mFunc(std::forward<T>(aFunc))
{
}

OnceCallback(OnceCallback &&aCallback)
: mFunc(aCallback.mFunc)
{
aCallback.mFunc = nullptr;
}

OnceCallback &operator=(OnceCallback &&aCallback)
{
mFunc = aCallback.mFunc;
aCallback.mFunc = nullptr;

return *this;
}

OnceCallback(const OnceCallback &) = delete;
OnceCallback &operator=(const OnceCallback &) = delete;
OnceCallback(OnceCallback &&) = default;
OnceCallback &operator=(OnceCallback &&) = default;

R operator()(Args...) const &
{
static_assert(!sizeof(*this), "OnceCallback::() can only be invoked on a non-const "
"rvalue, i.e. std::move(callback)().");
}

R operator()(Args... args) &&
R operator()(Args... aArgs) &&
{
// Move `this` to a local variable to clear internal state
// before invoking the callback function.
OnceCallback cb = std::move(*this);

return cb.mFunc(std::forward<Args>(args)...);
return cb.mFunc(std::forward<Args>(aArgs)...);
}

bool IsNull() const { return mFunc == nullptr; }
Expand Down

0 comments on commit 83e2b98

Please sign in to comment.