folly: avoid compile warning/failure due to lvalue-to-rvalue conversion
[folly.git] / folly / io / async / EventBaseLocal.h
index 5681fac67f4aa56c32fb5df4d687408691698651..8e4bdce3b77b4b98bb6b90a75e47f84db07cb8ae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 #pragma once
 
-#if !defined(ANDROID) && !defined(__ANDROID__) && !defined(__APPLE__)
-
 #include <boost/noncopyable.hpp>
 #include <folly/Synchronized.h>
 #include <folly/io/async/EventBase.h>
 #include <memory>
 #include <mutex>
-#include <unordered_map>
 #include <unordered_set>
+#include <utility>
 
 namespace folly {
 
 namespace detail {
 
-class EventBaseLocalBase : boost::noncopyable {
+class EventBaseLocalBase : public EventBaseLocalBaseBase, boost::noncopyable {
  public:
   EventBaseLocalBase() {}
-  virtual ~EventBaseLocalBase();
+  ~EventBaseLocalBase() override;
   void erase(EventBase& evb);
-  void onEventBaseDestruction(EventBase& evb);
+  void onEventBaseDestruction(EventBase& evb) override;
 
  protected:
   void setVoid(EventBase& evb, std::shared_ptr<void>&& ptr);
-  void setVoidUnlocked(EventBase& evb, std::shared_ptr<void>&& ptr);
   void* getVoid(EventBase& evb);
 
   folly::Synchronized<std::unordered_set<EventBase*>> eventBases_;
@@ -47,7 +44,7 @@ class EventBaseLocalBase : boost::noncopyable {
   uint64_t key_{keyCounter_++};
 };
 
-}
+} // namespace detail
 
 /**
  * A storage abstraction for data that should be tied to an EventBase.
@@ -66,13 +63,14 @@ class EventBaseLocalBase : boost::noncopyable {
  *   Foo& foo = myFoo.getOrCreateFn(evb, [] () { return new Foo(3, 4); })
  *
  * The objects will be deleted when the EventBaseLocal or the EventBase is
- * destructed (whichever comes first).  All methods are thread-safe.
+ * destructed (whichever comes first). All methods must be called from the
+ * EventBase thread.
  *
  * The user is responsible for throwing away invalid references/ptrs returned
  * by the get() method after set/erase is called.  If shared ownership is
  * needed, use a EventBaseLocal<shared_ptr<...>>.
  */
-template<typename T>
+template <typename T>
 class EventBaseLocal : public detail::EventBaseLocalBase {
  public:
   EventBaseLocal(): EventBaseLocalBase() {}
@@ -86,25 +84,21 @@ class EventBaseLocal : public detail::EventBaseLocalBase {
     setVoid(evb, std::move(smartPtr));
   }
 
-  template<typename... Args>
-  void emplace(EventBase& evb, Args... args) {
-    auto smartPtr = std::make_shared<T>(args...);
+  template <typename... Args>
+  void emplace(EventBase& evb, Args&&... args) {
+    auto smartPtr = std::make_shared<T>(std::forward<Args>(args)...);
     setVoid(evb, smartPtr);
   }
 
-  template<typename... Args>
-  T& getOrCreate(EventBase& evb, Args... args) {
-    std::lock_guard<std::mutex> lg(evb.localStorageMutex_);
-
-    auto it2 = evb.localStorage_.find(key_);
-    if (LIKELY(it2 != evb.localStorage_.end())) {
-      return *static_cast<T*>(it2->second.get());
-    } else {
-      auto smartPtr = std::make_shared<T>(args...);
-      auto ptr = smartPtr.get();
-      setVoidUnlocked(evb, std::move(smartPtr));
-      return *ptr;
+  template <typename... Args>
+  T& getOrCreate(EventBase& evb, Args&&... args) {
+    if (auto ptr = getVoid(evb)) {
+      return *static_cast<T*>(ptr);
     }
+    auto smartPtr = std::make_shared<T>(std::forward<Args>(args)...);
+    auto& ref = *smartPtr;
+    setVoid(evb, std::move(smartPtr));
+    return ref;
   }
 
   template <typename Func>
@@ -112,21 +106,14 @@ class EventBaseLocal : public detail::EventBaseLocalBase {
     // If this looks like it's copy/pasted from above, that's because it is.
     // gcc has a bug (fixed in 4.9) that doesn't allow capturing variadic
     // params in a lambda.
-    std::lock_guard<std::mutex> lg(evb.localStorageMutex_);
-
-    auto it2 = evb.localStorage_.find(key_);
-    if (LIKELY(it2 != evb.localStorage_.end())) {
-      return *static_cast<T*>(it2->second.get());
-    } else {
-      std::shared_ptr<T> smartPtr(fn());
-      auto ptr = smartPtr.get();
-      setVoidUnlocked(evb, std::move(smartPtr));
-      return *ptr;
+    if (auto ptr = getVoid(evb)) {
+      return *static_cast<T*>(ptr);
     }
+    std::shared_ptr<T> smartPtr(fn());
+    auto& ref = *smartPtr;
+    setVoid(evb, std::move(smartPtr));
+    return ref;
   }
 };
 
-
-}
-
-#endif // !__ANDROID__ && !ANDROID && !__APPLE__
+} // namespace folly