Add PassRef and createRefCounted so we can improve creation of RefCounted objects
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 16 Oct 2013 17:18:05 +0000 (17:18 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 16 Oct 2013 17:18:05 +0000 (17:18 +0000)
https://bugs.webkit.org/show_bug.cgi?id=122904

Reviewed by Anders Carlsson.

Source/WTF:

* GNUmakefile.list.am: Added PassRef.h.
* WTF.vcxproj/WTF.vcxproj: Ditto.
* WTF.vcxproj/WTF.vcxproj.filters: Ditto.
* WTF.xcodeproj/project.pbxproj: Ditto.
* wtf/CMakeLists.txt: Ditto.

* wtf/Forward.h: Added PassRef. Also re-sorted and un-indented to match what
the style-checking script expects.

* wtf/PassRef.h: Added. Includes the createRefCounted function template, which
is analogous to make_unique, but is for reference counted objects, and also
assumes that new will never return null. Also includes an overload of adoptRef
that takes a reference rather than a pointer.

* wtf/PassRefPtr.h: Include "PassRef.h" so we can share the adopted function.
Got rid of declarations that duplicate ones in there.
(WTF::refIfNotNull): Use nullptr.
(WTF::derefIfNotNull): Use nullptr.
(WTF::PassRefPtr::PassRefPtr): Use nullptr. Added an overload that takes a PassRef.
(WTF::PassRefPtr::operator UnspecifiedBoolType): Use nullptr.
(WTF::PassRefPtr::operator=): Made this deleted instead of compile time assertion.
(WTF::PassRefPtr::PassRefPtr): Made adopting constructor use an adopt tag instead
of an unused boolean.
(WTF::PassRefPtr::leakRef): Use nullptr.
(WTF::adoptRef): Use the adopt tag.

* wtf/Ref.h: Use Noncopyable instead of rolling our own.
(WTF::Ref::Ref): Add an overload that takes a PassRef.
(WTF::Ref::operator=): Ditto.

* wtf/RefPtr.h: Removed unneeded forward declaration of PassRefPtr.
(WTF::RefPtr::RefPtr): Use nullptr. Added overload that takes a PassRef.
(WTF::RefPtr::release): Use nullptr.
(WTF::RefPtr::operator UnspecifiedBoolType): Use nullptr.
(WTF::RefPtr::operator=): Added overload that takes a PassRef.
(WTF::RefPtr::clear): Use nullptr.

* wtf/StdLibExtras.h: Added inline keyword to isPointerTypeAlignmentOkay,
reinterpret_cast_ptr, and make_unique. Seems like a simple oversight that these
were missing before.

Tools:

* TestWebKitAPI/Tests/WTF/Ref.cpp: Added some basic tests for adoptRef and PassRef.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@157520 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
Source/WTF/ChangeLog
Source/WTF/GNUmakefile.list.am
Source/WTF/WTF.vcxproj/WTF.vcxproj
Source/WTF/WTF.vcxproj/WTF.vcxproj.filters
Source/WTF/WTF.xcodeproj/project.pbxproj
Source/WTF/wtf/CMakeLists.txt
Source/WTF/wtf/Forward.h
Source/WTF/wtf/PassRef.h [new file with mode: 0644]
Source/WTF/wtf/PassRefPtr.h
Source/WTF/wtf/Ref.h
Source/WTF/wtf/RefPtr.h
Source/WTF/wtf/StdLibExtras.h
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WTF/Ref.cpp

index 0640120..ee2d794 100644 (file)
@@ -1,3 +1,51 @@
+2013-10-16  Darin Adler  <darin@apple.com>
+
+        Add PassRef and createRefCounted so we can improve creation of RefCounted objects
+        https://bugs.webkit.org/show_bug.cgi?id=122904
+
+        Reviewed by Anders Carlsson.
+
+        * GNUmakefile.list.am: Added PassRef.h.
+        * WTF.vcxproj/WTF.vcxproj: Ditto.
+        * WTF.vcxproj/WTF.vcxproj.filters: Ditto.
+        * WTF.xcodeproj/project.pbxproj: Ditto.
+        * wtf/CMakeLists.txt: Ditto.
+
+        * wtf/Forward.h: Added PassRef. Also re-sorted and un-indented to match what
+        the style-checking script expects.
+
+        * wtf/PassRef.h: Added. Includes the createRefCounted function template, which
+        is analogous to make_unique, but is for reference counted objects, and also
+        assumes that new will never return null. Also includes an overload of adoptRef
+        that takes a reference rather than a pointer.
+
+        * wtf/PassRefPtr.h: Include "PassRef.h" so we can share the adopted function.
+        Got rid of declarations that duplicate ones in there.
+        (WTF::refIfNotNull): Use nullptr.
+        (WTF::derefIfNotNull): Use nullptr.
+        (WTF::PassRefPtr::PassRefPtr): Use nullptr. Added an overload that takes a PassRef.
+        (WTF::PassRefPtr::operator UnspecifiedBoolType): Use nullptr.
+        (WTF::PassRefPtr::operator=): Made this deleted instead of compile time assertion.
+        (WTF::PassRefPtr::PassRefPtr): Made adopting constructor use an adopt tag instead
+        of an unused boolean.
+        (WTF::PassRefPtr::leakRef): Use nullptr.
+        (WTF::adoptRef): Use the adopt tag.
+
+        * wtf/Ref.h: Use Noncopyable instead of rolling our own.
+        (WTF::Ref::Ref): Add an overload that takes a PassRef.
+        (WTF::Ref::operator=): Ditto.
+
+        * wtf/RefPtr.h: Removed unneeded forward declaration of PassRefPtr.
+        (WTF::RefPtr::RefPtr): Use nullptr. Added overload that takes a PassRef.
+        (WTF::RefPtr::release): Use nullptr.
+        (WTF::RefPtr::operator UnspecifiedBoolType): Use nullptr.
+        (WTF::RefPtr::operator=): Added overload that takes a PassRef.
+        (WTF::RefPtr::clear): Use nullptr.
+
+        * wtf/StdLibExtras.h: Added inline keyword to isPointerTypeAlignmentOkay,
+        reinterpret_cast_ptr, and make_unique. Seems like a simple oversight that these
+        were missing before.
+
 2013-10-15  Dean Jackson  <dino@apple.com>
 
         Add ENABLE_WEB_ANIMATIONS flag
index 902ceed..45dc786 100644 (file)
@@ -117,6 +117,7 @@ wtf_sources += \
     Source/WTF/wtf/ParallelJobsLibdispatch.h \
     Source/WTF/wtf/ParallelJobsOpenMP.h \
     Source/WTF/wtf/PassOwnPtr.h \
+    Source/WTF/wtf/PassRef.h \
     Source/WTF/wtf/PassRefPtr.h \
     Source/WTF/wtf/Platform.h \
     Source/WTF/wtf/PossiblyNull.h \
index acda70d..964876a 100644 (file)
     <ClInclude Include="..\wtf\ParallelJobsLibdispatch.h" />\r
     <ClInclude Include="..\wtf\ParallelJobsOpenMP.h" />\r
     <ClInclude Include="..\wtf\PassOwnPtr.h" />\r
+    <ClInclude Include="..\wtf\PassRef.h" />\r
     <ClInclude Include="..\wtf\PassRefPtr.h" />\r
     <ClInclude Include="..\wtf\Platform.h" />\r
     <ClInclude Include="..\wtf\PossiblyNull.h" />\r
index 00a51db..cffa4ef 100644 (file)
     <ClInclude Include="..\wtf\PassOwnPtr.h">\r
       <Filter>wtf</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\wtf\PassRef.h">\r
+      <Filter>wtf</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\wtf\PassRefPtr.h">\r
       <Filter>wtf</Filter>\r
     </ClInclude>\r
index 9cd73bb..fbb6175 100644 (file)
@@ -63,6 +63,7 @@
                7E29C33E15FFD79B00516D61 /* ObjcRuntimeExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E29C33D15FFD79B00516D61 /* ObjcRuntimeExtras.h */; };
                8134013815B092FD001FF0B8 /* Base64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8134013615B092FD001FF0B8 /* Base64.cpp */; };
                8134013915B092FD001FF0B8 /* Base64.h in Headers */ = {isa = PBXBuildFile; fileRef = 8134013715B092FD001FF0B8 /* Base64.h */; };
+               93B1AA80180E5AF3004A2F05 /* PassRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 93B1AA7F180E5AF3004A2F05 /* PassRef.h */; };
                974CFC8E16A4F327006D5404 /* WeakPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 974CFC8D16A4F327006D5404 /* WeakPtr.h */; };
                9BC70F05176C379D00101DEC /* AtomicStringTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9BC70F04176C379D00101DEC /* AtomicStringTable.cpp */; };
                9BD8F40B176C2B470002D865 /* AtomicStringTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BD8F40A176C2AD80002D865 /* AtomicStringTable.h */; };
                7E29C33D15FFD79B00516D61 /* ObjcRuntimeExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjcRuntimeExtras.h; sourceTree = "<group>"; };
                8134013615B092FD001FF0B8 /* Base64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Base64.cpp; sourceTree = "<group>"; };
                8134013715B092FD001FF0B8 /* Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Base64.h; sourceTree = "<group>"; };
+               93B1AA7F180E5AF3004A2F05 /* PassRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PassRef.h; sourceTree = "<group>"; };
                974CFC8D16A4F327006D5404 /* WeakPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakPtr.h; sourceTree = "<group>"; };
                9BC70F04176C379D00101DEC /* AtomicStringTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AtomicStringTable.cpp; sourceTree = "<group>"; };
                9BD8F40A176C2AD80002D865 /* AtomicStringTable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AtomicStringTable.h; sourceTree = "<group>"; };
                                A8A472CE151A825B004123FF /* MetaAllocator.h */,
                                A8A472CF151A825B004123FF /* MetaAllocatorHandle.h */,
                                1A3F6BE6174ADA2100B2EEA7 /* NeverDestroyed.h */,
-                               26299B6D17A9E5B800ADEBE5 /* Ref.h */,
                                0F0D85B317234CB100338210 /* NoLock.h */,
                                A8A472D0151A825B004123FF /* Noncopyable.h */,
                                A8A472D5151A825B004123FF /* NumberOfCores.cpp */,
                                A8A472E6151A825B004123FF /* ParallelJobs.h */,
                                A8A472E9151A825B004123FF /* ParallelJobsLibdispatch.h */,
                                A8A472EC151A825B004123FF /* PassOwnPtr.h */,
+                               93B1AA7F180E5AF3004A2F05 /* PassRef.h */,
                                A8A472ED151A825B004123FF /* PassRefPtr.h */,
                                A876DBD7151816E500DADB95 /* Platform.h */,
                                A8A472F3151A825B004123FF /* PossiblyNull.h */,
                                A8A472FD151A825B004123FF /* RandomNumberSeed.h */,
                                0F87105916643F190090B0AD /* RawPointer.h */,
                                A8A472FE151A825B004123FF /* RedBlackTree.h */,
+                               26299B6D17A9E5B800ADEBE5 /* Ref.h */,
                                A8A472FF151A825B004123FF /* RefCounted.h */,
                                A8A47300151A825B004123FF /* RefCountedArray.h */,
                                A8A47301151A825B004123FF /* RefCountedLeakCounter.cpp */,
                                A8A473E3151A825B004123FF /* Locker.h in Headers */,
                                A8A473E6151A825B004123FF /* MainThread.h in Headers */,
                                A8A473E8151A825B004123FF /* MathExtras.h in Headers */,
+                               93B1AA80180E5AF3004A2F05 /* PassRef.h in Headers */,
                                A8A473EA151A825B004123FF /* MD5.h in Headers */,
                                CD5497AD15857D0300B5BC30 /* MediaTime.h in Headers */,
                                A8A473EB151A825B004123FF /* MessageQueue.h in Headers */,
index 01e604b..60ede56 100644 (file)
@@ -67,6 +67,7 @@ set(WTF_HEADERS
     ParallelJobsLibdispatch.h
     ParallelJobsOpenMP.h
     PassOwnPtr.h
+    PassRef.h
     PassRefPtr.h
     Platform.h
     PossiblyNull.h
index efbbcd5..f1c223f 100644 (file)
 
 namespace WTF {
 
-    template<typename T> class Function;
-    template<typename T> class OwnPtr;
-    template<typename T> class PassOwnPtr;
-    template<typename T> class PassRefPtr;
-    template<typename T> class RefPtr;
-    template<typename T> class Ref;
-    template<typename T, size_t inlineCapacity, typename OverflowHandler> class Vector;
+template<typename T> class Function;
+template<typename T> class OwnPtr;
+template<typename T> class PassOwnPtr;
+template<typename T> class PassRef;
+template<typename T> class PassRefPtr;
+template<typename T> class RefPtr;
+template<typename T> class Ref;
+template<typename T> class StringBuffer;
 
-    class AtomicString;
-    class AtomicStringImpl;
-    class BinarySemaphore;
-    class CString;
-    class Decoder;
-    class Encoder;
-    class FunctionDispatcher;
-    class PrintStream;
-    class String;
-    template <typename T> class StringBuffer;
-    class StringBuilder;
-    class StringImpl;
-}
+template<typename T, size_t inlineCapacity, typename OverflowHandler> class Vector;
 
-using WTF::Function;
-using WTF::OwnPtr;
-using WTF::PassOwnPtr;
-using WTF::PassRefPtr;
-using WTF::RefPtr;
-using WTF::Ref;
-using WTF::Vector;
+class AtomicString;
+class AtomicStringImpl;
+class BinarySemaphore;
+class CString;
+class Decoder;
+class Encoder;
+class FunctionDispatcher;
+class PrintStream;
+class String;
+class StringBuilder;
+class StringImpl;
+
+}
 
 using WTF::AtomicString;
 using WTF::AtomicStringImpl;
 using WTF::BinarySemaphore;
 using WTF::CString;
-using WTF::Encoder;
 using WTF::Decoder;
+using WTF::Encoder;
+using WTF::Function;
 using WTF::FunctionDispatcher;
+using WTF::OwnPtr;
+using WTF::PassOwnPtr;
+using WTF::PassRef;
+using WTF::PassRefPtr;
 using WTF::PrintStream;
+using WTF::Ref;
+using WTF::RefPtr;
 using WTF::String;
 using WTF::StringBuffer;
 using WTF::StringBuilder;
 using WTF::StringImpl;
+using WTF::Vector;
 
 #endif // WTF_Forward_h
diff --git a/Source/WTF/wtf/PassRef.h b/Source/WTF/wtf/PassRef.h
new file mode 100644 (file)
index 0000000..eef384d
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ *  Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef WTF_PassRef_h
+#define WTF_PassRef_h
+
+#include "Assertions.h"
+#include <cstddef>
+
+namespace WTF {
+
+template<typename T> class PassRef;
+template<typename T> class PassRefPtr;
+template<typename T> class Ref;
+template<typename T> class RefPtr;
+
+template<typename T> PassRef<T> adoptRef(T&);
+
+inline void adopted(const void*) { }
+
+template<typename T> class PassRef {
+public:
+    PassRef(T&);
+    PassRef(PassRef&&);
+    template<typename U> PassRef(PassRef<U>);
+
+#ifndef NDEBUG
+    ~PassRef();
+#endif
+
+private:
+    friend PassRef adoptRef<T>(T&);
+
+    template<typename U> friend class PassRef;
+    template<typename U> friend class PassRefPtr;
+    template<typename U> friend class Ref;
+    template<typename U> friend class RefPtr;
+
+    enum AdoptTag { Adopt };
+    PassRef(T&, AdoptTag);
+
+    T& takeReference();
+
+    T& m_reference;
+
+#ifndef NDEBUG
+    bool m_gaveUpReference;
+#endif
+};
+
+template<typename T> inline PassRef<T>::PassRef(T& reference)
+    : m_reference(reference)
+#ifndef NDEBUG
+    , m_gaveUpReference(false)
+#endif
+{
+    reference.ref();
+}
+
+template<typename T> inline PassRef<T>::PassRef(PassRef&& other)
+    : m_reference(other.takeReference())
+#ifndef NDEBUG
+    , m_gaveUpReference(false)
+#endif
+{
+}
+
+template<typename T> template<typename U> inline PassRef<T>::PassRef(PassRef<U> other)
+    : m_reference(other.takeReference())
+#ifndef NDEBUG
+    , m_gaveUpReference(false)
+#endif
+{
+}
+
+#ifndef NDEBUG
+
+template<typename T> PassRef<T>::~PassRef()
+{
+    ASSERT(m_gaveUpReference);
+}
+
+#endif
+
+template<typename T> inline T& PassRef<T>::takeReference()
+{
+#ifndef NDEBUG
+    ASSERT(!m_gaveUpReference);
+    m_gaveUpReference = true;
+#endif
+    return m_reference;
+}
+
+template<typename T> inline PassRef<T>::PassRef(T& reference, AdoptTag)
+    : m_reference(reference)
+#ifndef NDEBUG
+    , m_gaveUpReference(false)
+#endif
+{
+}
+
+template<typename T> inline PassRef<T> adoptRef(T& reference)
+{
+    adopted(&reference);
+    return PassRef<T>(reference, PassRef<T>::Adopt);
+}
+
+#if COMPILER_SUPPORTS(CXX_VARIADIC_TEMPLATES)
+
+template<typename T, typename... Args> inline PassRef<T> createRefCounted(Args&&... args)
+{
+    return adoptRef(*new T(std::forward<Args>(args)...));
+}
+
+#else
+
+template<typename T> inline PassRef<T> createRefCounted()
+{
+    return adoptRef(*new T);
+}
+
+template<typename T, typename A1> inline PassRef<T> createRefCounted(A1&& a1)
+{
+    return adoptRef(*new T(std::forward<A1>(a1)));
+}
+
+template<typename T, typename A1, typename A2> inline PassRef<T> createRefCounted(A1&& a1, A2&& a2)
+{
+    return adoptRef(*new T(std::forward<A1>(a1), std::forward<A2>(a2)));
+}
+
+template<typename T, typename A1, typename A2, typename A3> inline PassRef<T> createRefCounted(A1&& a1, A2&& a2, A3&& a3)
+{
+    return adoptRef(*new T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3)));
+}
+
+template<typename T, typename A1, typename A2, typename A3, typename A4> inline PassRef<T> createRefCounted(A1&& a1, A2&& a2, A3&& a3, A4&& a4)
+{
+    return adoptRef(*new T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4)));
+}
+
+template<typename T, typename A1, typename A2, typename A3, typename A4, typename A5> inline PassRef<T> createRefCounted(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5)
+{
+    return adoptRef(*new T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5)));
+}
+
+template<typename T, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> inline PassRef<T> createRefCounted(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6)
+{
+    return adoptRef(*new T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5), std::forward<A6>(a6)));
+}
+
+template<typename T, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> inline PassRef<T> createRefCounted(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7)
+{
+    return adoptRef(*new T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5), std::forward<A6>(a6), std::forward<A7>(a7)));
+}
+
+template<typename T, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> inline PassRef<T> createRefCounted(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8)
+{
+    return adoptRef(*new T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5), std::forward<A6>(a6), std::forward<A7>(a7), std::forward<A8>(a8)));
+}
+
+template<typename T, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> inline PassRef<T> createRefCounted(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9)
+{
+    return adoptRef(*new T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5), std::forward<A6>(a6), std::forward<A7>(a7), std::forward<A8>(a8), std::forward<A9>(a9)));
+}
+
+template<typename T, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10> inline PassRef<T> createRefCounted(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9, A10&& a10)
+{
+    return adoptRef(*new T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5), std::forward<A6>(a6), std::forward<A7>(a7), std::forward<A8>(a8), std::forward<A9>(a9), std::forward<A10>(a10)));
+}
+
+#endif
+
+} // namespace WTF
+
+using WTF::PassRef;
+using WTF::adoptRef;
+using WTF::createRefCounted;
+
+#endif // WTF_PassRef_h
index 8729e73..5c8b3f2 100644 (file)
 #ifndef WTF_PassRefPtr_h
 #define WTF_PassRefPtr_h
 
-#include <cstddef>
-#include <wtf/Assertions.h>
+#include "PassRef.h"
 
 namespace WTF {
 
-    template<typename T> class RefPtr;
-    template<typename T> class PassRefPtr;
     template<typename T> PassRefPtr<T> adoptRef(T*);
 
-    inline void adopted(const void*) { }
-
     template<typename T> ALWAYS_INLINE void refIfNotNull(T* ptr)
     {
-        if (LIKELY(ptr != 0))
+        if (LIKELY(ptr != nullptr))
             ptr->ref();
     }
 
     template<typename T> ALWAYS_INLINE void derefIfNotNull(T* ptr)
     {
-        if (LIKELY(ptr != 0))
+        if (LIKELY(ptr != nullptr))
             ptr->deref();
     }
 
     template<typename T> class PassRefPtr {
     public:
-        PassRefPtr() : m_ptr(0) { }
+        PassRefPtr() : m_ptr(nullptr) { }
         PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
         // It somewhat breaks the type system to allow transfer of ownership out of
         // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr
@@ -57,7 +52,8 @@ namespace WTF {
         ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); }
 
         template<typename U> PassRefPtr(const RefPtr<U>&);
-        
+        template<typename U> PassRefPtr(PassRef<U> reference) : m_ptr(&reference.takeReference()) { }
+
         T* get() const { return m_ptr; }
 
         T* leakRef() const WARN_UNUSED_RETURN;
@@ -69,15 +65,15 @@ namespace WTF {
 
         // This conversion operator allows implicit conversion to bool but not to other integer types.
         typedef T* (PassRefPtr::*UnspecifiedBoolType);
-        operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; }
-
-        PassRefPtr& operator=(const PassRefPtr&) { COMPILE_ASSERT(!sizeof(T*), PassRefPtr_should_never_be_assigned_to); return *this; }
+        operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : nullptr; }
 
         friend PassRefPtr adoptRef<T>(T*);
 
     private:
-        // adopting constructor
-        PassRefPtr(T* ptr, bool) : m_ptr(ptr) { }
+        PassRefPtr& operator=(const PassRefPtr&) WTF_DELETED_FUNCTION;
+
+        enum AdoptTag { Adopt };
+        PassRefPtr(T* ptr, AdoptTag) : m_ptr(ptr) { }
 
         mutable T* m_ptr;
     };
@@ -92,7 +88,7 @@ namespace WTF {
     template<typename T> inline T* PassRefPtr<T>::leakRef() const
     {
         T* ptr = m_ptr;
-        m_ptr = 0;
+        m_ptr = nullptr;
         return ptr;
     }
 
@@ -149,7 +145,7 @@ namespace WTF {
     template<typename T> inline PassRefPtr<T> adoptRef(T* p)
     {
         adopted(p);
-        return PassRefPtr<T>(p, true);
+        return PassRefPtr<T>(p, PassRefPtr<T>::Adopt);
     }
 
     template<typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p) 
index 73414ff..4d833d2 100644 (file)
 #ifndef WTF_Ref_h
 #define WTF_Ref_h
 
-#include <wtf/Compiler.h>
+#include "Noncopyable.h"
 
 namespace WTF {
 
+template<typename T> class PassRef;
+
 template<typename T> class Ref {
+    WTF_MAKE_NONCOPYABLE(Ref)
 public:
     Ref(T& object) : m_ptr(&object) { m_ptr->ref(); }
+    template<typename U> Ref(PassRef<U> reference) : m_ptr(&reference.takeReference()) { }
+
+    ~Ref() { m_ptr->deref(); }
+
     Ref& operator=(T& object)
     {
         object.ref();
@@ -40,8 +47,12 @@ public:
         m_ptr = &object;
         return *this;
     }
-
-    ~Ref() { m_ptr->deref(); }
+    template<typename U> Ref& operator=(PassRef<U> reference)
+    {
+        m_ptr->deref();
+        m_ptr = &reference.takeReference();
+        return *this;
+    }
 
     const T* operator->() const { return m_ptr; }
     T* operator->() { return m_ptr; }
@@ -50,9 +61,6 @@ public:
     T& get() { return *m_ptr; }
 
 private:
-    Ref(const Ref&);
-    Ref& operator=(const Ref<T>&);
-
     T* m_ptr;
 };
 
index 00be88b..4e4fcf0 100644 (file)
 #ifndef WTF_RefPtr_h
 #define WTF_RefPtr_h
 
+#include "FastMalloc.h"
+#include "PassRefPtr.h"
 #include <algorithm>
 #include <utility>
-#include <wtf/FastMalloc.h>
-#include <wtf/PassRefPtr.h>
 
 namespace WTF {
 
-    template<typename T> class PassRefPtr;
-
     enum HashTableDeletedValueType { HashTableDeletedValue };
 
     template<typename T> class RefPtr {
         WTF_MAKE_FAST_ALLOCATED;
     public:
-        ALWAYS_INLINE RefPtr() : m_ptr(0) { }
+        ALWAYS_INLINE RefPtr() : m_ptr(nullptr) { }
         ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
         ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(m_ptr); }
         template<typename U> RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { refIfNotNull(m_ptr); }
@@ -48,6 +46,8 @@ namespace WTF {
         // See comments in PassRefPtr.h for an explanation of why this takes a const reference.
         template<typename U> RefPtr(const PassRefPtr<U>&);
 
+        template<typename U> RefPtr(PassRef<U>);
+
         // Hash table deleted values, which are only constructed and never copied or destroyed.
         RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
         bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
@@ -57,7 +57,7 @@ namespace WTF {
         T* get() const { return m_ptr; }
         
         void clear();
-        PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; }
+        PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = nullptr; return tmp; }
 
         T& operator*() const { return *m_ptr; }
         ALWAYS_INLINE T* operator->() const { return m_ptr; }
@@ -66,7 +66,7 @@ namespace WTF {
     
         // This conversion operator allows implicit conversion to bool but not to other integer types.
         typedef T* (RefPtr::*UnspecifiedBoolType);
-        operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::m_ptr : 0; }
+        operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::m_ptr : nullptr; }
         
         RefPtr& operator=(const RefPtr&);
         RefPtr& operator=(T*);
@@ -78,6 +78,8 @@ namespace WTF {
         template<typename U> RefPtr& operator=(const PassRefPtr<U>&);
         RefPtr& operator=(RefPtr&&);
         template<typename U> RefPtr& operator=(RefPtr<U>&&);
+        template<typename U> RefPtr& operator=(PassRef<U>);
+
         void swap(RefPtr&);
 
         static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
@@ -91,10 +93,15 @@ namespace WTF {
     {
     }
 
+    template<typename T> template<typename U> inline RefPtr<T>::RefPtr(PassRef<U> reference)
+        : m_ptr(&reference.takeReference())
+    {
+    }
+
     template<typename T> inline void RefPtr<T>::clear()
     {
         T* ptr = m_ptr;
-        m_ptr = 0;
+        m_ptr = nullptr;
         derefIfNotNull(ptr);
     }
 
@@ -147,6 +154,13 @@ namespace WTF {
         return *this;
     }
 
+    template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(PassRef<U> reference)
+    {
+        RefPtr ptr = reference;
+        swap(ptr);
+        return *this;
+    }
+
     template<class T> inline void RefPtr<T>::swap(RefPtr& o)
     {
         std::swap(m_ptr, o.m_ptr);
index ac92729..cfc9d3f 100644 (file)
  */
 #if (CPU(ARM) || CPU(MIPS)) && COMPILER(GCC)
 template<typename Type>
-bool isPointerTypeAlignmentOkay(Type* ptr)
+inline bool isPointerTypeAlignmentOkay(Type* ptr)
 {
     return !(reinterpret_cast<intptr_t>(ptr) % __alignof__(Type));
 }
 
 template<typename TypePtr>
-TypePtr reinterpret_cast_ptr(void* ptr)
+inline TypePtr reinterpret_cast_ptr(void* ptr)
 {
     ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr)));
     return reinterpret_cast<TypePtr>(ptr);
 }
 
 template<typename TypePtr>
-TypePtr reinterpret_cast_ptr(const void* ptr)
+inline TypePtr reinterpret_cast_ptr(const void* ptr)
 {
     ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr)));
     return reinterpret_cast<TypePtr>(ptr);
 }
 #else
 template<typename Type>
-bool isPointerTypeAlignmentOkay(Type*)
+inline bool isPointerTypeAlignmentOkay(Type*)
 {
     return true;
 }
@@ -330,80 +330,80 @@ namespace std {
     };
 
 #if COMPILER_SUPPORTS(CXX_VARIADIC_TEMPLATES)
-    template<class T, class... Args> typename _Unique_if<T>::_Single_object
+    template<class T, class... Args> inline typename _Unique_if<T>::_Single_object
     make_unique(Args&&... args)
     {
         return unique_ptr<T>(new T(std::forward<Args>(args)...));
     }
 #else
-    template<class T> typename _Unique_if<T>::_Single_object
+    template<class T> inline typename _Unique_if<T>::_Single_object
     make_unique()
     {
         return unique_ptr<T>(new T);
     }
 
-    template<class T, class A1> typename _Unique_if<T>::_Single_object
+    template<class T, class A1> inline typename _Unique_if<T>::_Single_object
     make_unique(A1&& a1)
     {
         return unique_ptr<T>(new T(std::forward<A1>(a1)));
     }
 
-    template<class T, class A1, class A2> typename _Unique_if<T>::_Single_object
+    template<class T, class A1, class A2> inline typename _Unique_if<T>::_Single_object
     make_unique(A1&& a1, A2&& a2)
     {
         return unique_ptr<T>(new T(std::forward<A1>(a1), std::forward<A2>(a2)));
     }
 
-    template<class T, class A1, class A2, class A3> typename _Unique_if<T>::_Single_object
+    template<class T, class A1, class A2, class A3> inline typename _Unique_if<T>::_Single_object
     make_unique(A1&& a1, A2&& a2, A3&& a3)
     {
         return unique_ptr<T>(new T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3)));
     }
 
-    template<class T, class A1, class A2, class A3, class A4> typename _Unique_if<T>::_Single_object
+    template<class T, class A1, class A2, class A3, class A4> inline typename _Unique_if<T>::_Single_object
     make_unique(A1&& a1, A2&& a2, A3&& a3, A4&& a4)
     {
         return unique_ptr<T>(new T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4)));
     }
 
-    template<class T, class A1, class A2, class A3, class A4, class A5> typename _Unique_if<T>::_Single_object
+    template<class T, class A1, class A2, class A3, class A4, class A5> inline typename _Unique_if<T>::_Single_object
     make_unique(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5)
     {
         return unique_ptr<T>(new T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5)));
     }
 
-    template<class T, class A1, class A2, class A3, class A4, class A5, class A6> typename _Unique_if<T>::_Single_object
+    template<class T, class A1, class A2, class A3, class A4, class A5, class A6> inline typename _Unique_if<T>::_Single_object
     make_unique(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6)
     {
         return unique_ptr<T>(new T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5), std::forward<A6>(a6)));
     }
 
-    template<class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> typename _Unique_if<T>::_Single_object
+    template<class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> inline typename _Unique_if<T>::_Single_object
     make_unique(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7)
     {
         return unique_ptr<T>(new T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5), std::forward<A6>(a6), std::forward<A7>(a7)));
     }
 
-    template<class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> typename _Unique_if<T>::_Single_object
+    template<class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> inline typename _Unique_if<T>::_Single_object
     make_unique(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8)
     {
         return unique_ptr<T>(new T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5), std::forward<A6>(a6), std::forward<A7>(a7), std::forward<A8>(a8)));
     }
 
-    template<class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> typename _Unique_if<T>::_Single_object
+    template<class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> inline typename _Unique_if<T>::_Single_object
     make_unique(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9)
     {
         return unique_ptr<T>(new T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5), std::forward<A6>(a6), std::forward<A7>(a7), std::forward<A8>(a8), std::forward<A9>(a9)));
     }
 
-    template<class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10> typename _Unique_if<T>::_Single_object
+    template<class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10> inline typename _Unique_if<T>::_Single_object
     make_unique(A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9, A10&& a10)
     {
         return unique_ptr<T>(new T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4), std::forward<A5>(a5), std::forward<A6>(a6), std::forward<A7>(a7), std::forward<A8>(a8), std::forward<A9>(a9), std::forward<A10>(a10)));
     }
 #endif
 
-    template<class T> typename _Unique_if<T>::_Unknown_bound
+    template<class T> inline typename _Unique_if<T>::_Unknown_bound
     make_unique(size_t n)
     {
         typedef typename remove_extent<T>::type U;
index 2094209..3d54029 100644 (file)
@@ -1,5 +1,14 @@
 2013-10-16  Darin Adler  <darin@apple.com>
 
+        Add PassRef and createRefCounted so we can improve creation of RefCounted objects
+        https://bugs.webkit.org/show_bug.cgi?id=122904
+
+        Reviewed by Anders Carlsson.
+
+        * TestWebKitAPI/Tests/WTF/Ref.cpp: Added some basic tests for adoptRef and PassRef.
+
+2013-10-16  Darin Adler  <darin@apple.com>
+
         Need tests for RefPtr self-assignment and self-move-assignment.
 
         * TestWebKitAPI/Tests/WTF/RefPtr.cpp: Added tests.
index 455d00c..1b9eef6 100644 (file)
@@ -26,7 +26,9 @@
 #include "config.h"
 
 #include "RefLogger.h"
+#include <wtf/PassRef.h>
 #include <wtf/Ref.h>
+#include <wtf/RefPtr.h>
 
 namespace TestWebKitAPI {
 
@@ -40,6 +42,13 @@ TEST(WTF_Ref, Basic)
         ASSERT_EQ(&a.name, &ptr->name);
     }
     ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        Ref<RefLogger> ptr(adoptRef(a));
+        ASSERT_EQ(&a, &ptr.get());
+        ASSERT_EQ(&a.name, &ptr->name);
+    }
+    ASSERT_STREQ("deref(a) ", takeLogStr().c_str());
 }
 
 TEST(WTF_Ref, Assignment)
@@ -67,6 +76,71 @@ TEST(WTF_Ref, Assignment)
         log() << "| ";
     }
     ASSERT_STREQ("ref(a) | ref(c) deref(a) | deref(c) ", takeLogStr().c_str());
+
+    {
+        Ref<RefLogger> ptr(a);
+        ASSERT_EQ(&a, &ptr.get());
+        log() << "| ";
+        ptr = adoptRef(b);
+        ASSERT_EQ(&b, &ptr.get());
+        log() << "| ";
+    }
+    ASSERT_STREQ("ref(a) | deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        Ref<RefLogger> ptr(a);
+        ASSERT_EQ(&a, &ptr.get());
+        log() << "| ";
+        ptr = adoptRef(c);
+        ASSERT_EQ(&c, &ptr.get());
+        log() << "| ";
+    }
+    ASSERT_STREQ("ref(a) | deref(a) | deref(c) ", takeLogStr().c_str());
+}
+
+PassRef<RefLogger> passWithPassRef(PassRef<RefLogger> reference)
+{
+    return reference;
+}
+
+RefPtr<RefLogger> passWithPassRefPtr(PassRefPtr<RefLogger> reference)
+{
+    return reference;
+}
+
+TEST(WTF_Ref, ReturnValue)
+{
+    DerivedRefLogger a("a");
+    RefLogger b("b");
+    DerivedRefLogger c("c");
+
+    {
+        Ref<RefLogger> ptr(passWithPassRef(a));
+        ASSERT_EQ(&a, &ptr.get());
+    }
+    ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        Ref<RefLogger> ptr(a);
+        ASSERT_EQ(&a, &ptr.get());
+        log() << "| ";
+        ptr = passWithPassRef(b);
+        ASSERT_EQ(&b, &ptr.get());
+        log() << "| ";
+    }
+    ASSERT_STREQ("ref(a) | ref(b) deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        RefPtr<RefLogger> ptr(passWithPassRef(a));
+        ASSERT_EQ(&a, ptr.get());
+    }
+    ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        RefPtr<RefLogger> ptr(passWithPassRefPtr(passWithPassRef(a)));
+        ASSERT_EQ(&a, ptr.get());
+    }
+    ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
 }
 
 } // namespace TestWebKitAPI