Add WTF::move()
[WebKit-https.git] / Source / WebCore / platform / Supplementable.h
1 /*
2  * Copyright (C) 2012 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
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.
12  *
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.
24  */
25
26 #ifndef Supplementable_h
27 #define Supplementable_h
28
29 #include <wtf/Assertions.h>
30 #include <wtf/HashMap.h>
31 #include <wtf/MainThread.h>
32 #include <wtf/OwnPtr.h>
33 #include <wtf/PassOwnPtr.h>
34
35 #if !ASSERT_DISABLED
36 #include <wtf/Threading.h>
37 #endif
38
39 namespace WebCore {
40
41 // What you should know about Supplementable and Supplement
42 // ========================================================
43 // Supplementable and Supplement instances are meant to be thread local. They
44 // should only be accessed from within the thread that created them. The
45 // 2 classes are not designed for safe access from another thread. Violating
46 // this design assumption can result in memory corruption and unpredictable
47 // behavior.
48 //
49 // What you should know about the Supplement keys
50 // ==============================================
51 // The Supplement is expected to use the same const char* string instance
52 // as its key. The Supplementable's SupplementMap will use the address of the
53 // string as the key and not the characters themselves. Hence, 2 strings with
54 // the same characters will be treated as 2 different keys.
55 //
56 // In practice, it is recommended that Supplements implements a static method
57 // for returning its key to use. For example:
58 //
59 //     class MyClass : public Supplement<MySupplementable> {
60 //         ...
61 //         static const char* supplementName();
62 //     }
63 //
64 //     const char* MyClass::supplementName()
65 //     {
66 //         return "MyClass";
67 //     }
68 //
69 // An example of the using the key:
70 //
71 //     MyClass* MyClass::from(MySupplementable* host)
72 //     {
73 //         return reinterpret_cast<MyClass*>(Supplement<MySupplementable>::from(host, supplementName()));
74 //     }
75
76 template<typename T>
77 class Supplementable;
78
79 template<typename T>
80 class Supplement {
81 public:
82     virtual ~Supplement() { }
83 #if !ASSERT_DISABLED || defined(ADDRESS_SANITIZER)
84     virtual bool isRefCountedWrapper() const { return false; }
85 #endif
86
87     static void provideTo(Supplementable<T>* host, const char* key, std::unique_ptr<Supplement<T>> supplement)
88     {
89         host->provideSupplement(key, WTF::move(supplement));
90     }
91
92     static Supplement<T>* from(Supplementable<T>* host, const char* key)
93     {
94         return host ? host->requireSupplement(key) : 0;
95     }
96 };
97
98 template<typename T>
99 class Supplementable {
100 public:
101     void provideSupplement(const char* key, std::unique_ptr<Supplement<T>> supplement)
102     {
103         ASSERT(canAccessThreadLocalDataForThread(m_threadId));
104         ASSERT(!m_supplements.get(key));
105         m_supplements.set(key, WTF::move(supplement));
106     }
107
108     void removeSupplement(const char* key)
109     {
110         ASSERT(canAccessThreadLocalDataForThread(m_threadId));
111         m_supplements.remove(key);
112     }
113
114     Supplement<T>* requireSupplement(const char* key)
115     {
116         ASSERT(canAccessThreadLocalDataForThread(m_threadId));
117         return m_supplements.get(key);
118     }
119
120 #if !ASSERT_DISABLED
121 protected:
122     Supplementable() : m_threadId(currentThread()) { }
123 #endif
124
125 private:
126     typedef HashMap<const char*, std::unique_ptr<Supplement<T>>, PtrHash<const char*>> SupplementMap;
127     SupplementMap m_supplements;
128 #if !ASSERT_DISABLED
129     ThreadIdentifier m_threadId;
130 #endif
131 };
132
133 } // namespace WebCore
134
135 #endif // Supplementable_h
136