1/*
2 * Copyright (C) 2009, 2010 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#ifndef CrossThreadCopier_h
32#define CrossThreadCopier_h
33
34#include <wtf/Assertions.h>
35#include <wtf/Forward.h>
36#include <wtf/PassOwnPtr.h>
37#include <wtf/PassRefPtr.h>
38#include <wtf/RefPtr.h>
39#include <wtf/Threading.h>
40#include <wtf/TypeTraits.h>
41
42namespace WebCore {
43
44    class IntRect;
45    class IntSize;
46    class KURL;
47    class ResourceError;
48    class ResourceRequest;
49    class ResourceResponse;
50    struct CrossThreadResourceResponseData;
51    struct CrossThreadResourceRequestData;
52    struct ThreadableLoaderOptions;
53
54    template<typename T> struct CrossThreadCopierPassThrough {
55        typedef T Type;
56        static Type copy(const T& parameter)
57        {
58            return parameter;
59        }
60    };
61
62    template<bool isConvertibleToInteger, bool isThreadSafeRefCounted, typename T> struct CrossThreadCopierBase;
63
64    // Integers get passed through without any changes.
65    template<typename T> struct CrossThreadCopierBase<true, false, T> : public CrossThreadCopierPassThrough<T> {
66    };
67
68    // To allow a type to be passed across threads using its copy constructor, add a forward declaration of the type and
69    // a CopyThreadCopierBase<false, false, TypeName> : public CrossThreadCopierPassThrough<TypeName> { }; to this file.
70    template<> struct CrossThreadCopierBase<false, false, ThreadableLoaderOptions> : public CrossThreadCopierPassThrough<ThreadableLoaderOptions> {
71    };
72
73    template<> struct CrossThreadCopierBase<false, false, IntRect> : public CrossThreadCopierPassThrough<IntRect> {
74    };
75
76    template<> struct CrossThreadCopierBase<false, false, IntSize> : public CrossThreadCopierPassThrough<IntSize> {
77    };
78
79    // Custom copy methods.
80    template<typename T> struct CrossThreadCopierBase<false, true, T> {
81        typedef typename WTF::RemoveTemplate<T, RefPtr>::Type TypeWithoutRefPtr;
82        typedef typename WTF::RemoveTemplate<TypeWithoutRefPtr, PassRefPtr>::Type TypeWithoutPassRefPtr;
83        typedef typename WTF::RemovePointer<TypeWithoutPassRefPtr>::Type RefCountedType;
84
85        // Verify that only one of the above did a change.
86        COMPILE_ASSERT((WTF::IsSameType<RefPtr<RefCountedType>, T>::value
87                        || WTF::IsSameType<PassRefPtr<RefCountedType>, T>::value
88                        || WTF::IsSameType<RefCountedType*, T>::value),
89                       OnlyAllowOneTypeModification);
90
91        typedef PassRefPtr<RefCountedType> Type;
92        static Type copy(const T& refPtr)
93        {
94            return refPtr;
95        }
96    };
97
98    template<typename T> struct CrossThreadCopierBase<false, false, PassOwnPtr<T> > {
99        typedef PassOwnPtr<T> Type;
100        static Type copy(Type ownPtr)
101        {
102            return ownPtr;
103        }
104    };
105
106    template<> struct CrossThreadCopierBase<false, false, KURL> {
107        typedef KURL Type;
108        static Type copy(const KURL&);
109    };
110
111    template<> struct CrossThreadCopierBase<false, false, String> {
112        typedef String Type;
113        static Type copy(const String&);
114    };
115
116    template<> struct CrossThreadCopierBase<false, false, ResourceError> {
117        typedef ResourceError Type;
118        static Type copy(const ResourceError&);
119    };
120
121    template<> struct CrossThreadCopierBase<false, false, ResourceRequest> {
122        typedef PassOwnPtr<CrossThreadResourceRequestData> Type;
123        static Type copy(const ResourceRequest&);
124    };
125
126    template<> struct CrossThreadCopierBase<false, false, ResourceResponse> {
127        typedef PassOwnPtr<CrossThreadResourceResponseData> Type;
128        static Type copy(const ResourceResponse&);
129    };
130
131    template<typename T> struct CrossThreadCopier : public CrossThreadCopierBase<WTF::IsConvertibleToInteger<T>::value,
132                                                                                 WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, RefPtr>::Type, ThreadSafeRefCounted>::value
133                                                                                     || WTF::IsSubclassOfTemplate<typename WTF::RemovePointer<T>::Type, ThreadSafeRefCounted>::value
134                                                                                     || WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, PassRefPtr>::Type, ThreadSafeRefCounted>::value,
135                                                                                 T> {
136    };
137
138    template<typename T> struct AllowCrossThreadAccessWrapper {
139    public:
140        explicit AllowCrossThreadAccessWrapper(T* value) : m_value(value) { }
141        T* value() const { return m_value; }
142    private:
143        T* m_value;
144    };
145
146    template<typename T> struct CrossThreadCopierBase<false, false, AllowCrossThreadAccessWrapper<T> > {
147        typedef T* Type;
148        static Type copy(const AllowCrossThreadAccessWrapper<T>& wrapper) { return wrapper.value(); }
149    };
150
151    template<typename T> AllowCrossThreadAccessWrapper<T> AllowCrossThreadAccess(T* value)
152    {
153        return AllowCrossThreadAccessWrapper<T>(value);
154    }
155
156    // FIXME: Move to a different header file. AllowAccessLater is for cross-thread access
157    // that is not cross-thread (tasks posted to a queue guaranteed to run on the same thread).
158    template<typename T> struct AllowAccessLaterWrapper {
159    public:
160        explicit AllowAccessLaterWrapper(T* value) : m_value(value) { }
161        T* value() const { return m_value; }
162    private:
163        T* m_value;
164    };
165
166    template<typename T> struct CrossThreadCopierBase<false, false, AllowAccessLaterWrapper<T> > {
167        typedef T* Type;
168        static Type copy(const AllowAccessLaterWrapper<T>& wrapper) { return wrapper.value(); }
169    };
170
171    template<typename T> AllowAccessLaterWrapper<T> AllowAccessLater(T* value)
172    {
173        return AllowAccessLaterWrapper<T>(value);
174    }
175
176
177} // namespace WebCore
178
179#endif // CrossThreadCopier_h
180