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
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"
38 #include "wtf/Threading.h"
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
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> {
63 // static const char* supplementName();
66 // const char* MyClass::supplementName()
71 // An example of the using the key:
73 // MyClass* MyClass::from(MySupplementable* host)
75 // return reinterpret_cast<MyClass*>(Supplement<MySupplementable>::from(host, supplementName()));
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
>
96 template<typename T
, bool isGarbageCollected
>
97 class SupplementableBase
;
99 template<typename T
, bool isGarbageCollected
>
100 struct SupplementableTraits
;
103 struct SupplementableTraits
<T
, true> {
104 typedef RawPtr
<SupplementBase
<T
, true>> SupplementArgumentType
;
108 struct SupplementableTraits
<T
, false> {
109 typedef PassOwnPtr
<SupplementBase
<T
, false>> SupplementArgumentType
;
113 class SupplementTracing
;
116 class PLATFORM_EXPORT SupplementTracing
<true> : public GarbageCollectedMixin
{ };
119 class GC_PLUGIN_IGNORE("crbug.com/476419") PLATFORM_EXPORT SupplementTracing
<false> {
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
> {
134 #if ENABLE(SECURITY_ASSERT)
135 virtual bool isRefCountedWrapper() const { return false; }
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.
160 class SupplementableTracing
<T
, true> : public virtual GarbageCollectedMixin
{
161 WTF_MAKE_NONCOPYABLE(SupplementableTracing
);
163 DEFINE_INLINE_VIRTUAL_TRACE()
165 visitor
->trace(m_supplements
);
169 SupplementableTracing() { }
170 typedef HeapHashMap
<const char*, Member
<SupplementBase
<T
, true>>, PtrHash
<const char*>> SupplementMap
;
171 SupplementMap m_supplements
;
175 class SupplementableTracing
<T
, false> {
176 WTF_MAKE_NONCOPYABLE(SupplementableTracing
);
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
> {
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()
209 m_threadId
= currentThread();
215 SupplementableBase() : m_threadId(currentThread()) { }
218 ThreadIdentifier m_threadId
;
223 class HeapSupplement
: public SupplementBase
<T
, true> { };
226 class HeapSupplementable
: public SupplementableBase
<T
, true> { };
229 class Supplement
: public SupplementBase
<T
, false> { };
232 class Supplementable
: public SupplementableBase
<T
, false> { };
235 struct ThreadingTrait
<SupplementBase
<T
, true>> {
236 static const ThreadAffinity Affinity
= ThreadingTrait
<T
>::Affinity
;
240 struct ThreadingTrait
<SupplementableBase
<T
, true>> {
241 static const ThreadAffinity Affinity
= ThreadingTrait
<T
>::Affinity
;
246 #endif // Supplementable_h