SharedFunction.h 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #include <functional>
  8. #include <memory>
  9. #include <mutex>
  10. #include <better/mutex.h>
  11. namespace facebook {
  12. namespace react {
  13. /*
  14. * `SharedFunction` implements a pattern of a shared callable object that
  15. * contains the same executable inside. It's similar to `std::function` with
  16. * one important difference: when the object is copied, the stored function (and
  17. * captured values) are shared between instances (not copied). `SharedFunction`
  18. * can be stored inside `std::function` because it's callable. It useful in some
  19. * scenarios, such as:
  20. * - When captured by `std::function` arguments are not copyable;
  21. * - When we need to replace the content of the callable later on the go.
  22. */
  23. template <typename ReturnT = void, typename... ArgumentT>
  24. class SharedFunction {
  25. using T = ReturnT(ArgumentT...);
  26. struct Pair {
  27. Pair(std::function<T> &&function) : function(std::move(function)) {}
  28. std::function<T> function;
  29. better::shared_mutex mutex{};
  30. };
  31. public:
  32. SharedFunction(std::function<T> &&function = nullptr)
  33. : pair_(std::make_shared<Pair>(std::move(function))) {}
  34. SharedFunction(const SharedFunction &other) = default;
  35. SharedFunction(SharedFunction &&other) noexcept = default;
  36. SharedFunction &operator=(const SharedFunction &other) = default;
  37. SharedFunction &operator=(SharedFunction &&other) noexcept = default;
  38. void assign(std::function<T> function) const {
  39. std::unique_lock<better::shared_mutex> lock(pair_->mutex);
  40. pair_->function = function;
  41. }
  42. ReturnT operator()(ArgumentT... args) const {
  43. std::shared_lock<better::shared_mutex> lock(pair_->mutex);
  44. return pair_->function(args...);
  45. }
  46. private:
  47. std::shared_ptr<Pair> pair_;
  48. };
  49. } // namespace react
  50. } // namespace facebook