]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/common/cohort_lru.h
update sources to v12.2.1
[ceph.git] / ceph / src / common / cohort_lru.h
index 13c760f76f2e69814b75b7c274e3ede3fd9c44d1..6c8264a5efd0c21ba071736fa872027e8b4dbfca 100644 (file)
@@ -14,6 +14,7 @@
 #define COHORT_LRU_H
 
 #include <boost/intrusive/list.hpp>
+#include <boost/intrusive/slist.hpp>
 
 #include "common/likely.h"
 
@@ -38,7 +39,7 @@ namespace cohort {
       LRU
     };
 
-    typedef bi::link_mode<bi::safe_link> link_mode; // for debugging
+    typedef bi::link_mode<bi::safe_link> link_mode;
 
     class Object
     {
@@ -54,6 +55,14 @@ namespace cohort {
                         &Object::lru_hook >,
                       bi::constant_time_size<true>> Queue;
 
+      bi::slist_member_hook< link_mode > q2_hook;
+
+      typedef bi::slist<Object,
+                       bi::member_hook<
+                         Object, bi::slist_member_hook< link_mode >,
+                         &Object::q2_hook >,
+                       bi::constant_time_size<true>> Queue2;
+
     public:
 
       Object() : lru_flags(FLAG_NONE), lru_refcnt(0), lru_adj(0) {}
@@ -67,6 +76,10 @@ namespace cohort {
     private:
       template <typename LK>
       friend class LRU;
+
+      template <typename T, typename TTree, typename CLT, typename CEQ,
+             typename K, typename LK>
+      friend class TreeX;
     };
 
     /* allocator & recycler interface (create or re-use LRU objects) */
@@ -123,14 +136,9 @@ namespace cohort {
        for (int ix = 0; ix < n_lanes; ++ix,
               lane_ix = next_evict_lane()) {
          Lane& lane = qlane[lane_ix];
+         lane.lock.lock();
          /* if object at LRU has refcnt==1, it may be reclaimable */
          Object* o = &(lane.q.back());
-#if 0 /* XXX save for refactor */
-         std::cout << __func__
-                   << " " << o
-                   << " refcnt: " << o->lru_refcnt
-                   << std::endl;
-#endif
          if (can_reclaim(o)) {
            ++(o->lru_refcnt);
            o->lru_flags |= FLAG_EVICTING;
@@ -149,7 +157,6 @@ namespace cohort {
              return o;
            } else {
              // XXX can't make unreachable (means what?)
-             lane.lock.lock();
              --(o->lru_refcnt);
              o->lru_flags &= ~FLAG_EVICTING;
              /* unlock in next block */
@@ -190,6 +197,7 @@ namespace cohort {
 
       void unref(Object* o, uint32_t flags) {
        uint32_t refcnt = --(o->lru_refcnt);
+       Object* tdo = nullptr;
        if (unlikely(refcnt == 0)) {
          Lane& lane = lane_of(o);
          lane.lock.lock();
@@ -198,7 +206,7 @@ namespace cohort {
            Object::Queue::iterator it =
              Object::Queue::s_iterator_to(*o);
            lane.q.erase(it);
-           delete o;
+           tdo = o;
          }
          lane.lock.unlock();
        } else if (unlikely(refcnt == SENTINEL_REFCNT)) {
@@ -212,13 +220,16 @@ namespace cohort {
            lane.q.erase(it);
            /* hiwat check */
            if (lane.q.size() > lane_hiwat) {
-             delete o;
+             tdo = o;
            } else {
              lane.q.push_back(*o);
            }
          }
          lane.lock.unlock();
        }
+       /* unref out-of-line && !LOCKED */
+       if (tdo)
+         delete tdo;
       } /* unref */
 
       Object* insert(ObjectFactory* fac, Edge edge, uint32_t flags) {
@@ -388,7 +399,7 @@ namespace cohort {
          v = lat.p->cache[slot];
          if (v) {
            if (CEQ()(*v, k)) {
-             if (flags & (FLAG_LOCK|FLAG_UNLOCK))
+             if ((flags & FLAG_LOCK) && (flags & FLAG_UNLOCK))
                lat.lock->unlock();
              return v;
            }
@@ -406,7 +417,7 @@ namespace cohort {
            lat.p->cache[slot] = v;
          }
        }
-       if (flags & (FLAG_LOCK|FLAG_UNLOCK))
+       if ((flags & FLAG_LOCK) && (flags & FLAG_UNLOCK))
          lat.lock->unlock();
        return v;
       } /* find_latch */
@@ -448,6 +459,7 @@ namespace cohort {
        /* clear a table, call supplied function on
         * each element found (e.g., retuns sentinel
         * references) */
+       Object::Queue2 drain_q;
        for (int t_ix = 0; t_ix < n_part; ++t_ix) {
          Partition& p = part[t_ix];
          if (flags & FLAG_LOCK) /* LOCKED */
@@ -455,13 +467,19 @@ namespace cohort {
          while (p.tr.size() > 0) {
            iterator it = p.tr.begin();
            T* v = &(*it);
-           p.tr.erase(it); /* must precede uref(v), in
-                            * safe_link mode */
-           uref(v);
+           p.tr.erase(it);
+           drain_q.push_front(*v);
          }
          if (flags & FLAG_LOCK) /* we locked it, !LOCKED */
            p.lock.unlock();
        } /* each partition */
+       /* unref out-of-line && !LOCKED */
+       while (drain_q.size() > 0) {
+         Object::Queue2::iterator it = drain_q.begin();
+         T* v = static_cast<T*>(&(*it));
+         drain_q.erase(it); /* must precede uref(v) in safe_link mode */
+         uref(v);
+       }
       } /* drain */
 
     private: