Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / platform / Supplementable.h
blobfc765c6753809f406878761b3be8c443c8826e61
1 /*
2 * Copyright (C) 2012 Google, Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef Supplementable_h
27 #define Supplementable_h
29 #include "platform/PlatformExport.h"
30 #include "platform/heap/Handle.h"
31 #include "wtf/Assertions.h"
32 #include "wtf/HashMap.h"
33 #include "wtf/Noncopyable.h"
34 #include "wtf/OwnPtr.h"
35 #include "wtf/PassOwnPtr.h"
37 #if ENABLE(ASSERT)
38 #include "wtf/Threading.h"
39 #endif
41 namespace blink {
43 // What you should know about Supplementable and Supplement
44 // ========================================================
45 // Supplementable and Supplement instances are meant to be thread local. They
46 // should only be accessed from within the thread that created them. The
47 // 2 classes are not designed for safe access from another thread. Violating
48 // this design assumption can result in memory corruption and unpredictable
49 // behavior.
51 // What you should know about the Supplement keys
52 // ==============================================
53 // The Supplement is expected to use the same const char* string instance
54 // as its key. The Supplementable's SupplementMap will use the address of the
55 // string as the key and not the characters themselves. Hence, 2 strings with
56 // the same characters will be treated as 2 different keys.
58 // In practice, it is recommended that Supplements implements a static method
59 // for returning its key to use. For example:
61 // class MyClass : public Supplement<MySupplementable> {
62 // ...
63 // static const char* supplementName();
64 // }
66 // const char* MyClass::supplementName()
67 // {
68 // return "MyClass";
69 // }
71 // An example of the using the key:
73 // MyClass* MyClass::from(MySupplementable* host)
74 // {
75 // return reinterpret_cast<MyClass*>(Supplement<MySupplementable>::from(host, supplementName()));
76 // }
78 // What you should know about thread checks
79 // ========================================
80 // When assertion is enabled this class performs thread-safety check so that
81 // provideTo and from happen on the same thread. If you want to provide
82 // some value for Workers this thread check may not work very well though,
83 // since in most case you'd provide the value while worker preparation is
84 // being done on the main thread, even before the worker thread is started.
85 // If that's the case you can explicitly call reattachThread() when the
86 // Supplementable object is passed to the final destination thread (i.e.
87 // worker thread). Please be extremely careful to use the method though,
88 // as randomly calling the method could easily cause racy condition.
90 // Note that reattachThread() does nothing if assertion is not enabled.
93 template<typename T, bool isGarbageCollected>
94 class SupplementBase;
96 template<typename T, bool isGarbageCollected>
97 class SupplementableBase;
99 template<typename T, bool isGarbageCollected>
100 struct SupplementableTraits;
102 template<typename T>
103 struct SupplementableTraits<T, true> {
104 typedef RawPtr<SupplementBase<T, true>> SupplementArgumentType;
107 template<typename T>
108 struct SupplementableTraits<T, false> {
109 typedef PassOwnPtr<SupplementBase<T, false>> SupplementArgumentType;
112 template<bool>
113 class SupplementTracing;
115 template<>
116 class PLATFORM_EXPORT SupplementTracing<true> : public GarbageCollectedMixin { };
118 template<>
119 class GC_PLUGIN_IGNORE("crbug.com/476419") PLATFORM_EXPORT SupplementTracing<false> {
120 public:
121 virtual ~SupplementTracing() { }
122 // FIXME: Oilpan: this trace() method is only provided to minimize
123 // the use of ENABLE(OILPAN) for Supplements deriving from the
124 // transition type WillBeHeapSupplement<>.
126 // When that transition type is removed (or its use is substantially
127 // reduced), remove this dummy trace method also.
128 DEFINE_INLINE_VIRTUAL_TRACE() { }
131 template<typename T, bool isGarbageCollected = false>
132 class SupplementBase : public SupplementTracing<isGarbageCollected> {
133 public:
134 #if ENABLE(SECURITY_ASSERT)
135 virtual bool isRefCountedWrapper() const { return false; }
136 #endif
138 static void provideTo(SupplementableBase<T, isGarbageCollected>& host, const char* key, typename SupplementableTraits<T, isGarbageCollected>::SupplementArgumentType supplement)
140 host.provideSupplement(key, supplement);
143 static SupplementBase<T, isGarbageCollected>* from(SupplementableBase<T, isGarbageCollected>& host, const char* key)
145 return host.requireSupplement(key);
148 static SupplementBase<T, isGarbageCollected>* from(SupplementableBase<T, isGarbageCollected>* host, const char* key)
150 return host ? host->requireSupplement(key) : 0;
154 template<typename T, bool isGarbageCollected>
155 class SupplementableTracing;
157 // SupplementableTracing<T,true> inherits GarbageCollectedMixin virtually
158 // to allow ExecutionContext to derive from two GC mixin classes.
159 template<typename T>
160 class SupplementableTracing<T, true> : public virtual GarbageCollectedMixin {
161 WTF_MAKE_NONCOPYABLE(SupplementableTracing);
162 public:
163 DEFINE_INLINE_VIRTUAL_TRACE()
165 visitor->trace(m_supplements);
168 protected:
169 SupplementableTracing() { }
170 typedef HeapHashMap<const char*, Member<SupplementBase<T, true>>, PtrHash<const char*>> SupplementMap;
171 SupplementMap m_supplements;
174 template<typename T>
175 class SupplementableTracing<T, false> {
176 WTF_MAKE_NONCOPYABLE(SupplementableTracing);
177 protected:
178 SupplementableTracing() { }
179 typedef HashMap<const char*, OwnPtr<SupplementBase<T, false>>, PtrHash<const char*>> SupplementMap;
180 SupplementMap m_supplements;
183 // Helper class for implementing Supplementable and HeapSupplementable.
184 template<typename T, bool isGarbageCollected = false>
185 class SupplementableBase : public SupplementableTracing<T, isGarbageCollected> {
186 public:
187 void provideSupplement(const char* key, typename SupplementableTraits<T, isGarbageCollected>::SupplementArgumentType supplement)
189 ASSERT(m_threadId == currentThread());
190 ASSERT(!this->m_supplements.get(key));
191 this->m_supplements.set(key, supplement);
194 void removeSupplement(const char* key)
196 ASSERT(m_threadId == currentThread());
197 this->m_supplements.remove(key);
200 SupplementBase<T, isGarbageCollected>* requireSupplement(const char* key)
202 ASSERT(m_threadId == currentThread());
203 return this->m_supplements.get(key);
206 void reattachThread()
208 #if ENABLE(ASSERT)
209 m_threadId = currentThread();
210 #endif
213 #if ENABLE(ASSERT)
214 protected:
215 SupplementableBase() : m_threadId(currentThread()) { }
217 private:
218 ThreadIdentifier m_threadId;
219 #endif
222 template<typename T>
223 class HeapSupplement : public SupplementBase<T, true> { };
225 template<typename T>
226 class HeapSupplementable : public SupplementableBase<T, true> { };
228 template<typename T>
229 class Supplement : public SupplementBase<T, false> { };
231 template<typename T>
232 class Supplementable : public SupplementableBase<T, false> { };
234 template<typename T>
235 struct ThreadingTrait<SupplementBase<T, true>> {
236 static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity;
239 template<typename T>
240 struct ThreadingTrait<SupplementableBase<T, true>> {
241 static const ThreadAffinity Affinity = ThreadingTrait<T>::Affinity;
244 } // namespace blink
246 #endif // Supplementable_h