EventBaseLocal.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * Copyright 2015-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #pragma once
  17. #include <boost/noncopyable.hpp>
  18. #include <folly/Synchronized.h>
  19. #include <folly/io/async/EventBase.h>
  20. #include <memory>
  21. #include <mutex>
  22. #include <unordered_set>
  23. #include <utility>
  24. namespace folly {
  25. namespace detail {
  26. class EventBaseLocalBase : public EventBaseLocalBaseBase, boost::noncopyable {
  27. public:
  28. EventBaseLocalBase() {}
  29. ~EventBaseLocalBase() override;
  30. void erase(EventBase& evb);
  31. void onEventBaseDestruction(EventBase& evb) override;
  32. protected:
  33. void setVoid(EventBase& evb, std::shared_ptr<void>&& ptr);
  34. void* getVoid(EventBase& evb);
  35. folly::Synchronized<std::unordered_set<EventBase*>> eventBases_;
  36. static std::atomic<std::size_t> keyCounter_;
  37. std::size_t key_{keyCounter_++};
  38. };
  39. } // namespace detail
  40. /**
  41. * A storage abstraction for data that should be tied to an EventBase.
  42. *
  43. * struct Foo { Foo(int a, int b); };
  44. * EventBaseLocal<Foo> myFoo;
  45. * ...
  46. * EventBase evb;
  47. * myFoo.set(evb, new Foo(1, 2));
  48. * myFoo.set(evb, 1, 2);
  49. * Foo* foo = myFoo.get(evb);
  50. * myFoo.erase(evb);
  51. * Foo& foo = myFoo.getOrCreate(evb, 1, 2); // ctor
  52. * Foo& foo = myFoo.getOrCreate(evb, 1, 2); // no ctor
  53. * myFoo.erase(evb);
  54. * Foo& foo = myFoo.getOrCreateFn(evb, [] () { return new Foo(3, 4); })
  55. *
  56. * The objects will be deleted when the EventBaseLocal or the EventBase is
  57. * destructed (whichever comes first). All methods must be called from the
  58. * EventBase thread.
  59. *
  60. * The user is responsible for throwing away invalid references/ptrs returned
  61. * by the get() method after set/erase is called. If shared ownership is
  62. * needed, use a EventBaseLocal<shared_ptr<...>>.
  63. */
  64. template <typename T>
  65. class EventBaseLocal : public detail::EventBaseLocalBase {
  66. public:
  67. EventBaseLocal() : EventBaseLocalBase() {}
  68. T* get(EventBase& evb) {
  69. return static_cast<T*>(getVoid(evb));
  70. }
  71. void emplace(EventBase& evb, T* ptr) {
  72. std::shared_ptr<T> smartPtr(ptr);
  73. setVoid(evb, std::move(smartPtr));
  74. }
  75. template <typename... Args>
  76. void emplace(EventBase& evb, Args&&... args) {
  77. auto smartPtr = std::make_shared<T>(std::forward<Args>(args)...);
  78. setVoid(evb, smartPtr);
  79. }
  80. template <typename... Args>
  81. T& getOrCreate(EventBase& evb, Args&&... args) {
  82. if (auto ptr = getVoid(evb)) {
  83. return *static_cast<T*>(ptr);
  84. }
  85. auto smartPtr = std::make_shared<T>(std::forward<Args>(args)...);
  86. auto& ref = *smartPtr;
  87. setVoid(evb, std::move(smartPtr));
  88. return ref;
  89. }
  90. template <typename Func>
  91. T& getOrCreateFn(EventBase& evb, Func& fn) {
  92. // If this looks like it's copy/pasted from above, that's because it is.
  93. // gcc has a bug (fixed in 4.9) that doesn't allow capturing variadic
  94. // params in a lambda.
  95. if (auto ptr = getVoid(evb)) {
  96. return *static_cast<T*>(ptr);
  97. }
  98. std::shared_ptr<T> smartPtr(fn());
  99. auto& ref = *smartPtr;
  100. setVoid(evb, std::move(smartPtr));
  101. return ref;
  102. }
  103. };
  104. } // namespace folly