core-refcounting
author Benjamin Smedberg <benjamin@smedbergs.us>
Sat, 26 Jul 2008 22:49:39 -0400
changeset 167 a4da40849f5436e629c5732f4368c6c48189637f
parent 154 7b66eb66ba95f04cfa2392550b012262466a1275
permissions -rw-r--r--
State as of now

* * *
* * *
* * *

diff --git a/core/Makefile.in b/core/Makefile.in
new file mode 100644
--- /dev/null
+++ b/core/Makefile.in
@@ -0,0 +1,52 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla.
+#
+# The Initial Developer of the Original Code is
+# the Mozilla Foundation <http://www.mozilla.org/>
+#
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Benjamin Smedberg <benjamin@smedbergs.us> - Author
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = mozilla
+
+EXPORTS = \
+  RefPtr.h \
+  $(NULL)
+
+include $(topsrcdir)/config/rules.mk
diff --git a/core/RefPtr.h b/core/RefPtr.h
new file mode 100644
--- /dev/null
+++ b/core/RefPtr.h
@@ -0,0 +1,238 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation <http://www.mozilla.org/>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Benjamin Smedberg <benjamin@smedbergs.us> - Author
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_RefPtr_h__
+#define mozilla_RefPtr_h__
+
+namespace mozilla
+{
+    /**
+     * A lightweight wrapper around uint32_t which auto-initializes to 0
+     */
+    class RefCnt
+    {
+    private:
+        uint32_t mValue;
+
+    public:
+        RefCnt()
+            : mValue(0)
+        { }
+
+        uint32_t operator++() { return ++mValue; }
+        uint32_t operator--() { return --mValue; }
+
+        operator uint32_t() const { return mValue; }
+        uint32_t get() const { return mValue; }
+    };
+
+    template<class T>
+    class
+        NS_STACK_CLASS
+    AddRefed
+    {
+    private:
+        T *mRawPtr;
+
+    public:
+        explicit AddRefed(T *ptr) : mRawPtr(ptr) { }
+
+        T* get() const { return mRawPtr; }
+
+        // allow conversion from AddRefed<DerivedClass> to AddRefed<BaseClass>
+        template<class D>
+        operator AddRefed<D>() const {
+            return AddRefed<D>(mRawPtr);
+        }
+    };
+
+    template<class T>
+    class RefPtr
+    {
+    private:
+        T *mPtr;
+
+    public:
+        RefPtr() : mPtr(NULL) { }
+        RefPtr(const RefPtr<T> &copy)
+            : mPtr(copy.mPtr)
+        {
+            if (mPtr)
+                mPtr->AddReference();
+        }
+        RefPtr(T *ptr)
+            : mPtr(ptr)
+        {
+            if (ptr)
+                ptr->AddReference();
+        }
+        RefPtr(AddRefed<T> ref)
+            : mPtr(ref.get())
+        {
+        }
+
+        ~RefPtr()
+        {
+            set(NULL);
+        }
+
+        T* get() const
+        {
+            return mPtr;
+        }
+        operator T*() const
+        {
+            return mPtr;
+        }
+        T* operator->() const
+        {
+            return mPtr;
+        }
+
+        void set(T *ptr)
+        {
+            if (mPtr)
+                mPtr->ReleaseReference();
+
+            mPtr = ptr;
+
+            if (mPtr)
+                mPtr->AddReference();
+        }
+        T* operator=(RefPtr<T> &ref)
+        {
+            set(ref.mPtr);
+            return mPtr;
+        }
+        T* operator=(T *ptr)
+        {
+            set(ptr);
+            return ptr;
+        }
+        T* operator=(AddRefed<T> ref)
+        {
+            if (mPtr)
+                mPtr->ReleaseReference();
+
+            mPtr = ref.get();
+            return mPtr;
+        }
+
+        AddRefed<T> forget()
+        {
+            T *ptr = mPtr;
+            mPtr = NULL;
+            return AddRefed<T>(ptr);
+        }
+
+        void forget(T **outparam)
+        {
+            *outparam = mPtr;
+            mPtr = NULL;
+        }
+
+        T** assign_assuming_addref()
+        {
+            set(NULL);
+            return &mPtr;
+        }
+    };
+
+    template<class T>
+    inline T**
+    getter_AddRefs(RefPtr<T> &ref)
+    {
+        return ref.assign_assuming_addref();
+    }
+
+    template<class T>
+    inline AddRefed<T>
+    do_AddRef(T *ptr)
+    {
+        if (ptr)
+            ptr->AddReference();
+        return AddRefed<T>(ptr);
+    }
+
+    template<class T>
+    AddRefed<T>
+    do_AddRef(RefPtr<T> &ref)
+    {
+        return do_AddRef(ref.get());
+    }
+
+    /**
+     * This is a return type which can become a null AddRefed of
+     * any type.
+     */
+    class
+        NS_STACK_CLASS
+    NullRefType
+    {
+        template<class T>
+        operator AddRefed<T>()
+        {
+            return AddRefed<T>(NULL);
+        }
+    };
+
+    inline NullRefType
+    NullRef()
+    {
+        return NullRefType();
+    }
+}
+
+#define DECL_INLINE_REFCOUNTING(_class)                                 \
+    protected:                                                          \
+        mozilla::RefCnt mRefCnt;                                        \
+    public:                                                             \
+        void AddReference()                                             \
+        {                                                               \
+            ++mRefCnt;                                                  \
+        }                                                               \
+        void ReleaseReference()                                         \
+        {                                                               \
+            NS_PRECONDITION(mRefCnt, "Duplicate release?");             \
+            --mRefCnt;                                                  \
+            if (mRefCnt == 0)                                           \
+                delete this;                                            \
+        }
+
+#endif // mozilla_RefPtr_h__
diff --git a/xpcom/build.mk b/xpcom/build.mk
--- a/xpcom/build.mk
+++ b/xpcom/build.mk
@@ -41,4 +41,7 @@ tier_xpcom_dirs = tools/trace-malloc/lib
 tier_xpcom_dirs = tools/trace-malloc/lib
 endif
 
-tier_xpcom_dirs += xpcom
+tier_xpcom_dirs = \
+  core \
+  xpcom \
+  $(NULL)