]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
common/shared_cache: add lockless SharedLRU 22736/head
authorKefu Chai <kchai@redhat.com>
Wed, 27 Jun 2018 07:41:29 +0000 (15:41 +0800)
committerKefu Chai <kchai@redhat.com>
Wed, 27 Jun 2018 14:50:38 +0000 (22:50 +0800)
Signed-off-by: Kefu Chai <kchai@redhat.com>
src/common/lock_cond.h [new file with mode: 0644]
src/common/lock_mutex.h
src/common/lock_shared_ptr.h [new file with mode: 0644]
src/common/shared_cache.hpp
src/test/common/test_shared_cache.cc

diff --git a/src/common/lock_cond.h b/src/common/lock_cond.h
new file mode 100644 (file)
index 0000000..0cab3fa
--- /dev/null
@@ -0,0 +1,41 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+
+#pragma once
+
+#include "lock_policy.h"
+#include "Cond.h"
+
+class SharedLRUTest;
+
+namespace ceph::internal {
+
+// empty helper class except when the template argument is LockPolicy::MUTEX
+template<LockPolicy lock_policy>
+class LockCond {
+public:
+  int Wait(LockMutex<lock_policy>&) {
+    return 0;
+  }
+  int Signal() {
+    return 0;
+  }
+};
+
+template<>
+class LockCond<LockPolicy::MUTEX> {
+public:
+  int Wait(LockMutex<LockPolicy::MUTEX>& mutex) {
+    return cond.Wait(mutex.get());
+  }
+  int Signal() {
+    return cond.Signal();
+  }
+private:
+  Cond& get() {
+    return cond;
+  }
+  Cond cond;
+  friend class ::SharedLRUTest;
+};
+
+} // namespace ceph::internal
index 40ffa51490f2bf4d16f6cb7f7136da186f849852..ea69d319fabe571b23b1ed485ae688c3073c769f 100644 (file)
@@ -5,6 +5,8 @@
 #include "lock_policy.h"
 #include "Mutex.h"
 
+class SharedLRUTest;
+
 namespace ceph::internal {
 
 template<LockPolicy lp> class LockCond;
@@ -43,6 +45,7 @@ private:
   }
   mutable Mutex mutex;
   friend class LockCond<LockPolicy::MUTEX>;
+  friend class ::SharedLRUTest;
 };
 
 } // namespace ceph::internal
diff --git a/src/common/lock_shared_ptr.h b/src/common/lock_shared_ptr.h
new file mode 100644 (file)
index 0000000..0e2f6e8
--- /dev/null
@@ -0,0 +1,23 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+
+#pragma once
+
+#include "lock_policy.h"
+#include <memory>
+#include <boost/smart_ptr/local_shared_ptr.hpp>
+
+namespace ceph::internal {
+
+template<LockPolicy lock_policy>
+struct SharedPtrTrait {
+  template<class T> using shared_ptr = boost::local_shared_ptr<T>;
+  template<class T> using weak_ptr = boost::weak_ptr<T>;
+};
+
+template<>
+struct SharedPtrTrait<LockPolicy::MUTEX> {
+  template<class T> using shared_ptr = std::shared_ptr<T>;
+  template<class T> using weak_ptr = std::weak_ptr<T>;
+};
+
+}
index 266a3b9def3810d66f68f5727d333df1cede558b..526de44f88756b1c2273d2b10247c97f3ebf71b4 100644 (file)
 
 #include <map>
 #include <list>
-#include "common/Mutex.h"
-#include "common/Cond.h"
+#include "common/lock_cond.h"
+#include "common/lock_mutex.h"
+#include "common/lock_policy.h"
+#include "common/lock_shared_ptr.h"
 #include "include/unordered_map.h"
 
 // re-include our assert to clobber the system one; fix dout:
 #include "include/assert.h"
 
-template <class K, class V>
+template <class K, class V,
+         ceph::internal::LockPolicy lock_policy = ceph::internal::LockPolicy::MUTEX>
 class SharedLRU {
   CephContext *cct;
-  typedef std::shared_ptr<V> VPtr;
-  typedef std::weak_ptr<V> WeakVPtr;
-  Mutex lock;
+  using shared_ptr_trait_t = ceph::internal::SharedPtrTrait<lock_policy>;
+  using VPtr = typename shared_ptr_trait_t::template shared_ptr<V>;
+  using WeakVPtr = typename shared_ptr_trait_t::template weak_ptr<V>;
+  ceph::internal::LockMutex<lock_policy> lock;
   size_t max_size;
-  Cond cond;
+  ceph::internal::LockCond<lock_policy> cond;
   unsigned size;
 public:
   int waiting;
@@ -74,7 +78,7 @@ private:
   }
 
   void remove(const K& key, V *valptr) {
-    Mutex::Locker l(lock);
+    auto locker = lock();
     typename map<K, pair<WeakVPtr, V*>, C>::iterator i = weak_refs.find(key);
     if (i != weak_refs.end() && i->second.second == valptr) {
       weak_refs.erase(i);
@@ -84,9 +88,9 @@ private:
 
   class Cleanup {
   public:
-    SharedLRU<K, V, C> *cache;
+    SharedLRU<K, V> *cache;
     K key;
-    Cleanup(SharedLRU<K, V, C> *cache, K key) : cache(cache), key(key) {}
+    Cleanup(SharedLRU<K, V> *cache, K key) : cache(cache), key(key) {}
     void operator()(V *ptr) {
       cache->remove(key, ptr);
       delete ptr;
@@ -119,7 +123,7 @@ public:
     // reorder.
     map<K, pair<WeakVPtr, V*>, C> temp;
 
-    Mutex::Locker l(lock);
+    auto locker = lock();
     temp.swap(weak_refs);
 
     // reconstruct with new comparator
@@ -156,7 +160,7 @@ public:
   void clear() {
     while (true) {
       VPtr val; // release any ref we have after we drop the lock
-      Mutex::Locker l(lock);
+      auto locker = lock();
       if (size == 0)
         break;
 
@@ -168,7 +172,7 @@ public:
   void clear(const K& key) {
     VPtr val; // release any ref we have after we drop the lock
     {
-      Mutex::Locker l(lock);
+      auto locker = lock();
       typename map<K, pair<WeakVPtr, V*>, C>::iterator i = weak_refs.find(key);
       if (i != weak_refs.end()) {
        val = i->second.first.lock();
@@ -180,7 +184,7 @@ public:
   void purge(const K &key) {
     VPtr val; // release any ref we have after we drop the lock
     {
-      Mutex::Locker l(lock);
+      auto locker = lock();
       typename map<K, pair<WeakVPtr, V*>, C>::iterator i = weak_refs.find(key);
       if (i != weak_refs.end()) {
        val = i->second.first.lock();
@@ -193,7 +197,7 @@ public:
   void set_size(size_t new_size) {
     list<VPtr> to_release;
     {
-      Mutex::Locker l(lock);
+      auto locker = lock();
       max_size = new_size;
       trim_cache(&to_release);
     }
@@ -201,7 +205,7 @@ public:
 
   // Returns K key s.t. key <= k for all currently cached k,v
   K cached_key_lower_bound() {
-    Mutex::Locker l(lock);
+    auto locker = lock();
     return weak_refs.begin()->first;
   }
 
@@ -209,7 +213,7 @@ public:
     VPtr val;
     list<VPtr> to_release;
     {
-      Mutex::Locker l(lock);
+      auto locker = lock();
       ++waiting;
       bool retry = false;
       do {
@@ -236,7 +240,7 @@ public:
   bool get_next(const K &key, pair<K, VPtr> *next) {
     pair<K, VPtr> r;
     {
-      Mutex::Locker l(lock);
+      auto locker = lock();
       VPtr next_val;
       typename map<K, pair<WeakVPtr, V*>, C>::iterator i = weak_refs.upper_bound(key);
 
@@ -269,7 +273,7 @@ public:
     VPtr val;
     list<VPtr> to_release;
     {
-      Mutex::Locker l(lock);
+      auto locker = lock();
       ++waiting;
       bool retry = false;
       do {
@@ -294,7 +298,7 @@ public:
     VPtr val;
     list<VPtr> to_release;
     {
-      Mutex::Locker l(lock);
+      auto locker = lock();
       bool retry = false;
       do {
        retry = false;
@@ -327,7 +331,7 @@ public:
    * in the cache.
    */
   bool empty() {
-    Mutex::Locker l(lock);
+    auto locker = lock();
     return weak_refs.empty();
   }
 
@@ -347,7 +351,7 @@ public:
     VPtr val;
     list<VPtr> to_release;
     {
-      Mutex::Locker l(lock);
+      auto locker = lock();
       typename map<K, pair<WeakVPtr, V*>, C>::iterator actual =
        weak_refs.lower_bound(key);
       if (actual != weak_refs.end() && actual->first == key) {
index 026c99fe70b3b205009886f42838cda790611174..ea0ba288e42b06d7f5dfc163b39a489e53908cc4 100644 (file)
@@ -28,8 +28,8 @@
 
 class SharedLRUTest : public SharedLRU<unsigned int, int> {
 public:
-  Mutex &get_lock() { return lock; }
-  Cond &get_cond() { return cond; }
+  Mutex &get_lock() { return lock.get(); }
+  Cond &get_cond() { return cond.get(); }
   map<unsigned int, pair< std::weak_ptr<int>, int* > > &get_weak_refs() {
     return weak_refs;
   }