Removed explicit reference counting in handle.cc
authorPeter Iannucci <iannucci@mit.edu>
Thu, 10 Oct 2013 18:03:31 +0000 (14:03 -0400)
committerPeter Iannucci <iannucci@mit.edu>
Thu, 10 Oct 2013 18:03:31 +0000 (14:03 -0400)
handle.cc
handle.h

index 1cb5cc2..42d038f 100644 (file)
--- a/handle.cc
+++ b/handle.cc
 
 class hinfo {
 public:
-    rpcc *cl = nullptr;
-    int refcnt = 0;
+    unique_ptr<rpcc> cl;
     bool del = false;
     string m;
     mutex client_mutex;
     hinfo(const string & m_) : m(m_) {}
 };
 
-class handle_mgr {
-    private:
-        mutex mgr_mutex;
-        map<string, hinfo *> hmap;
-        void delete_handle(const string & m, lock & handle_mutex_lock);
-    public:
-        hinfo *acquire_handle(string m);
-        void release_handle(hinfo *h);
-        void delete_handle(const string & m);
-};
-
-static handle_mgr mgr;
-
-handle::handle(const string & m) : h(mgr.acquire_handle(m)) {}
+static mutex mgr_mutex;
+static map<string, shared_ptr<hinfo>> hmap;
 
-rpcc * handle::safebind() {
-    if (!h)
-        return nullptr;
-    lock ml(h->client_mutex);
-    if (h->del)
-        return nullptr;
-    if (h->cl)
-        return h->cl;
-    rpcc *cl = new rpcc(h->m);
-    LOG("trying to bind..." << h->m);
-    // The test script assumes that the failure can be detected by paxos and
-    // rsm layer within few seconds. We have to set the timeout with a small
-    // value to support the assumption.
-    // 
-    // With RPC_LOSSY=5, tests may fail due to delays and time outs.
-    int ret = cl->bind(milliseconds(1000));
-    if (ret < 0) {
-        LOG("bind failure! " << h->m << " " << ret);
-        delete cl;
-        h->del = true;
-    } else {
-        LOG("bind succeeded " << h->m);
-        h->cl = cl;
-    }
-    return h->cl;
-}
-
-handle::~handle() {
-    if (h) mgr.release_handle(h);
+static shared_ptr<hinfo> acquire_handle(string m) {
+    lock ml(mgr_mutex);
+    shared_ptr<hinfo> h = hmap[m];
+    if (!h || h->del)
+        return (hmap[m] = make_shared<hinfo>(m));
+    return h;
 }
 
-hinfo * handle_mgr::acquire_handle(string m) {
-    lock ml(mgr_mutex);
-    hinfo *h = nullptr;
+static void delete_handle(const string & m, lock &) {
     if (hmap.find(m) == hmap.end()) {
-        h = new hinfo(m);
-        hmap[m] = h;
-        h->refcnt++;
-    } else if (!hmap[m]->del) {
-        h = hmap[m];
-        h->refcnt++;
+        LOG_NONMEMBER("cl " << m << " isn't in cl list");
+        return;
     }
-    return h;
-}
 
-void handle_mgr::release_handle(hinfo *h) {
-    lock ml(mgr_mutex);
-    if (--h->refcnt == 0 && h->del)
-        delete_handle(h->m, ml);
+    hmap[m]->del = true;
+    LOG_NONMEMBER("cl " << m << " refcnt " << hmap[m].use_count());
+    hmap.erase(m);
 }
 
-void handle_mgr::delete_handle(const string & m) {
+void invalidate_handle(const string & m) {
     lock ml(mgr_mutex);
     delete_handle(m, ml);
 }
 
-void handle_mgr::delete_handle(const string & m, lock &) {
-    if (hmap.find(m) == hmap.end()) {
-        LOG("cl " << m << " isn't in cl list");
-        return;
-    }
-    LOG("cl " << m << " refcnt " << hmap[m]->refcnt);
-    hinfo *h = hmap[m];
-    if (h->refcnt == 0) {
-        if (h->cl) {
-            h->cl->cancel();
-            delete h->cl;
-        }
-        hmap.erase(m);
-        delete h;
-    } else
-        h->del = true;
-}
+handle::handle(const string & m) : h(acquire_handle(m)) {}
 
-void invalidate_handle(const string & m) {
-    mgr.delete_handle(m);
+rpcc * handle::safebind() {
+    if (!h)
+        return nullptr;
+    lock ml(h->client_mutex);
+    if (h->del)
+        return nullptr;
+    if (!h->cl) {
+        unique_ptr<rpcc> cl(new rpcc(h->m));
+        LOG("trying to bind..." << h->m);
+        // The test script assumes that the failure can be detected by paxos and
+        // rsm layer within few seconds. We have to set the timeout with a small
+        // value to support the assumption.
+        // 
+        // With RPC_LOSSY=5, tests may fail due to delays and time outs.
+        int ret = cl->bind(milliseconds(1000));
+        if (ret < 0) {
+            LOG("bind failure! " << h->m << " " << ret);
+            h->del = true;
+        } else {
+            LOG("bind succeeded " << h->m);
+            h->cl = move(cl);
+        }
+    }
+    return h->cl.get();
 }
index d4b6223..dc2edb7 100644 (file)
--- a/handle.h
+++ b/handle.h
@@ -30,10 +30,9 @@ class hinfo;
 
 class handle {
     private:
-        hinfo *h;
+        shared_ptr<hinfo> h;
     public:
         handle(const string & m);
-        ~handle();
         /* safebind will try to bind with the rpc server on the first call.
          * Since bind may block, the caller probably should not hold a mutex
          * when calling safebind.