You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/09/24 04:01:54 UTC

svn commit: r1000688 - in /subversion/branches/object-model/subversion: bindings/c++/include/Types.h tests/libsvn++/util-test.cpp

Author: hwright
Date: Fri Sep 24 02:01:54 2010
New Revision: 1000688

URL: http://svn.apache.org/viewvc?rev=1000688&view=rev
Log:
On the object-model branch:
Attempt some reference-counting smart pointer magic to prevent pool
proliferation.

Note: This could probably stand with a bit of documentation.

* subversion/bindings/c++/include/Types.h
  (RefCounter, CStructWrapper): New.
  (CommitInfo): Use the CStructWrapper to hold the underlying commit_info
    struct.

* subversion/tests/libsvn++/util-test.cpp
  (test_struct_wrapping): New test.
  (test_funcs): Run the new test.

Modified:
    subversion/branches/object-model/subversion/bindings/c++/include/Types.h
    subversion/branches/object-model/subversion/tests/libsvn++/util-test.cpp

Modified: subversion/branches/object-model/subversion/bindings/c++/include/Types.h
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/bindings/c%2B%2B/include/Types.h?rev=1000688&r1=1000687&r2=1000688&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/bindings/c++/include/Types.h (original)
+++ subversion/branches/object-model/subversion/bindings/c++/include/Types.h Fri Sep 24 02:01:54 2010
@@ -33,8 +33,10 @@
 #include "svn_wc.h"
 #include "svn_types.h"
 
+#include <stdlib.h>
 #include <map>
 #include <string>
+#include <iostream>
 
 namespace SVN
 {
@@ -42,34 +44,101 @@ namespace SVN
 // Typedefs
 typedef std::map<std::string, std::string> PropTable;
 
+namespace Private
+{
 
-// C-struct wrapper classes
-class CommitInfo
+// Magic
+template<typename C, typename T>
+class RefCounter
 {
   private:
     Pool m_pool;
-    svn_commit_info_t *m_info;
+    size_t count;
+    T *p;
 
   public:
     inline
-    CommitInfo(const svn_commit_info_t *info)
-      : m_pool()
+    RefCounter<C, T>(T *in)
+      : m_pool(),
+        count(1)
     {
-      m_info = svn_commit_info_dup(info, m_pool.pool());
+      p = C::dup(in, m_pool);
     }
 
+    inline void inc_ref() { ++count; }
+    inline void dec_ref() { --count; }
+    inline T const *ptr() { return p; }
+    inline size_t refs() { return count; }
+
+    // The default destructor will destroy the Pool, and deallocate our object
+};
+
+template<typename C, typename T>
+class CStructWrapper
+{
+  private:
+    RefCounter<C, T> *m_data;
+
+  public:
     inline
-    CommitInfo(const CommitInfo &that)
-      : m_pool()
+    CStructWrapper(T *data)
     {
-      m_info = svn_commit_info_dup(that.m_info, m_pool.pool());
+      m_data = new RefCounter<C, T>(data);
     }
 
-    inline CommitInfo&
-    operator=(const CommitInfo &that)
+    inline
+    CStructWrapper(const CStructWrapper<C, T> &that)
+    {
+      m_data = that.m_data;
+      m_data->inc_ref();
+    }
+
+    inline CStructWrapper<C, T>&
+    operator= (const CStructWrapper<C, T> &that)
+    {
+      // Self assignment
+      if (&that == this)
+        return *this;
+      
+      m_data->dec_ref();
+      if (m_data->refs() == 0)
+        delete m_data;
+      m_data = that.m_data;
+      m_data->inc_ref();
+
+      return *this;
+    }
+
+    inline ~CStructWrapper()
+    {
+      m_data->dec_ref();
+      if (m_data->refs() == 0)
+        delete m_data;
+    }
+
+    inline const T& operator* () const { return *m_data->ptr(); }
+    inline const T* operator-> () const { return m_data->ptr(); }
+};
+
+} // namespace Private
+
+// C-struct wrapper classes
+class CommitInfo
+{
+  private:
+    Private::CStructWrapper<CommitInfo, const svn_commit_info_t> m_info;
+
+  public:
+    inline static svn_commit_info_t *
+    dup(const svn_commit_info_t *info, Pool &pool)
+    {
+      return svn_commit_info_dup(info, pool.pool());
+    }
+
+    explicit inline
+    CommitInfo(const svn_commit_info_t *info)
+      : m_info(info)
     {
-      m_pool.clear();
-      m_info = svn_commit_info_dup(that.m_info, m_pool.pool());
     }
 
     inline Revision

Modified: subversion/branches/object-model/subversion/tests/libsvn++/util-test.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/object-model/subversion/tests/libsvn%2B%2B/util-test.cpp?rev=1000688&r1=1000687&r2=1000688&view=diff
==============================================================================
--- subversion/branches/object-model/subversion/tests/libsvn++/util-test.cpp (original)
+++ subversion/branches/object-model/subversion/tests/libsvn++/util-test.cpp Fri Sep 24 02:01:54 2010
@@ -164,6 +164,37 @@ test_map_wrapping(apr_pool_t *p)
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test_struct_wrapping(apr_pool_t *p)
+{
+  apr_pool_t *subpool = svn_pool_create(p);
+  svn_commit_info_t *commit_info = svn_create_commit_info(subpool);
+
+  commit_info->author = "hwright";
+
+  CommitInfo info(commit_info);
+  svn_pool_destroy(subpool);
+
+  SVN_TEST_ASSERT(info.getAuthor() == "hwright");
+
+  CommitInfo info2(info);
+  SVN_TEST_ASSERT(info2.getAuthor() == "hwright");
+
+  CommitInfo *info3 = new CommitInfo(info2);
+  SVN_TEST_ASSERT(info3->getAuthor() == "hwright");
+
+  CommitInfo *info4 = new CommitInfo(*info3);
+  SVN_TEST_ASSERT(info4->getAuthor() == "hwright");
+
+  delete info3;
+  SVN_TEST_ASSERT(info.getAuthor() == "hwright");
+  SVN_TEST_ASSERT(info4->getAuthor() == "hwright");
+
+  delete info4;
+
+  return SVN_NO_ERROR;
+}
+
 /* The test table.  */
 
 struct svn_test_descriptor_t test_funcs[] =
@@ -181,5 +212,7 @@ struct svn_test_descriptor_t test_funcs[
                    "test various vector to array transforms"),
     SVN_TEST_PASS2(test_map_wrapping,
                    "test various map to hash transforms"),
+    SVN_TEST_PASS2(test_struct_wrapping,
+                   "test our ref-counted struct wrappers"),
     SVN_TEST_NULL
   };