Use std::shared_ptr to do reference counting in Socket.

Review: https://reviews.apache.org/r/27957


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/075859d9
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/075859d9
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/075859d9

Branch: refs/heads/master
Commit: 075859d984aa0b23d8efb18cc9bf0e6a17f3e00f
Parents: 9eda433
Author: Joris Van Remoortere <[email protected]>
Authored: Sat Nov 15 16:45:35 2014 -0800
Committer: Benjamin Hindman <[email protected]>
Committed: Sat Nov 15 17:38:21 2014 -0800

----------------------------------------------------------------------
 3rdparty/libprocess/include/process/socket.hpp | 87 ++++++++++-----------
 1 file changed, 42 insertions(+), 45 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/075859d9/3rdparty/libprocess/include/process/socket.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/socket.hpp 
b/3rdparty/libprocess/include/process/socket.hpp
index 6683881..9f4302e 100644
--- a/3rdparty/libprocess/include/process/socket.hpp
+++ b/3rdparty/libprocess/include/process/socket.hpp
@@ -4,6 +4,7 @@
 #include <assert.h>
 
 #include <stout/abort.hpp>
+#include <stout/memory.hpp>
 #include <stout/nothing.hpp>
 #include <stout/os.hpp>
 #include <stout/try.hpp>
@@ -40,66 +41,62 @@ inline Try<int> socket(int family, int type, int protocol) {
 class Socket
 {
 public:
-  Socket()
-    : refs(new int(1)), s(-1) {}
+  class Impl
+  {
+  public:
+    Impl() : s(-1) {}
 
-  explicit Socket(int _s)
-    : refs(new int(1)), s(_s) {}
+    explicit Impl(int _s) : s(_s) {}
 
-  ~Socket()
-  {
-    cleanup();
-  }
+    ~Impl()
+    {
+      if (s >= 0) {
+        Try<Nothing> close = os::close(s);
+        if (close.isError()) {
+          ABORT(
+            "Failed to close socket " + stringify(s) + ": " + close.error());
+        }
+      }
+    }
 
-  Socket(const Socket& that)
-  {
-    copy(that);
-  }
+    int get() const
+    {
+      return s >= 0 ? s : create().get();
+    }
 
-  Socket& operator = (const Socket& that)
-  {
-    if (this != &that) {
-      cleanup();
-      copy(that);
+  private:
+    const Impl& create() const
+    {
+      CHECK(s < 0);
+      Try<int> fd =
+        process::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 
0);
+      if (fd.isError()) {
+        ABORT("Failed to create socket: " + fd.error());
+      }
+      s = fd.get();
+      return *this;
     }
-    return *this;
-  }
+
+    // Mutable so that the socket can be lazily created.
+    mutable int s;
+  };
+
+  Socket() : impl(std::make_shared<Impl>()) {}
+
+  explicit Socket(int s) : impl(std::make_shared<Impl>(s)) {}
 
   bool operator == (const Socket& that) const
   {
-    return s == that.s && refs == that.refs;
+    return impl == that.impl;
   }
 
   operator int () const
   {
-    return s;
+    return impl->get();
   }
 
 private:
-  void copy(const Socket& that)
-  {
-    assert(that.refs > 0);
-    __sync_fetch_and_add(that.refs, 1);
-    refs = that.refs;
-    s = that.s;
-  }
-
-  void cleanup()
-  {
-    assert(refs != NULL);
-    if (__sync_sub_and_fetch(refs, 1) == 0) {
-      delete refs;
-      if (s >= 0) {
-        Try<Nothing> close = os::close(s);
-        if (close.isError()) {
-          ABORT("Failed to close socket: " + close.error());
-        }
-      }
-    }
-  }
-
-  int* refs;
-  int s;
+  memory::shared_ptr<Impl> impl;
 };
 
 } // namespace process {

Reply via email to