Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(207)

Side by Side Diff: chrome/browser/sync/util/immutable.h

Issue 7904021: [Sync] Rework SharedValue<T> into Immutable<T> (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rename vars Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Immutable<T> provides an easy, cheap, and thread-safe way to pass
6 // large immutable data around.
7 //
8 // For example, consider the following code:
9 //
10 // typedef std::vector<LargeObject> LargeObjectList;
11 //
12 // void ProcessStuff(const LargeObjectList& stuff) {
13 // for (LargeObjectList::const_iterator it = stuff.begin();
14 // it != stuff.end(); ++it) {
15 // ... process it ...
16 // }
17 // }
18 //
19 // ...
20 //
21 // LargeObjectList my_stuff;
22 // ... fill my_stuff with lots of LargeObjects ...
23 // some_loop->PostTask(FROM_HERE, base::Bind(&ProcessStuff, my_stuff));
24 //
25 // The last line incurs the cost of copying my_stuff, which is
26 // undesirable. Here's the above code re-written using Immutable<T>:
27 //
28 // void ProcessStuff(
29 // const browser_sync::Immutable<LargeObjectList>& stuff) {
30 // for (LargeObjectList::const_iterator it = stuff.Get().begin();
31 // it != stuff.Get().end(); ++it) {
32 // ... process it ...
33 // }
34 // }
35 //
36 // ...
37 //
38 // LargeObjectList my_stuff;
39 // ... fill my_stuff with lots of LargeObjects ...
40 // some_loop->PostTask(
41 // FROM_HERE, base::Bind(&ProcessStuff, MakeImmutable(&my_stuff)));
42 //
43 // The last line, which resets my_stuff to a default-initialized
44 // state, incurs only the cost of a swap of LargeObjectLists, which is
45 // O(1) for most STL container implementations. The data in my_stuff
46 // is ref-counted (thread-safely), so it is freed as soon as
47 // ProcessStuff is finished.
48 //
49 // NOTE: By default, Immutable<T> relies on ADL
50 // (http://en.wikipedia.org/wiki/Argument-dependent_name_lookup) to
51 // find a swap() function for T, falling back to std::swap() when
52 // necessary. If you overload swap() for your type in its namespace,
53 // or if you specialize std::swap() for your type, (see
54 // http://stackoverflow.com/questions/11562/how-to-overload-stdswap
55 // for discussion) Immutable<T> should be able to find it.
56 //
57 // Alternatively, you could explicitly control which swap function is
58 // used by providing your own traits class or using one of the
59 // pre-defined ones below. See comments on traits below for details.
60 //
61 // NOTE: Some complexity is necessary in order to use Immutable<T>
62 // with forward-declared types. See comments on traits below for
63 // details.
64
65 #ifndef CHROME_BROWSER_SYNC_UTIL_IMMUTABLE_H_
66 #define CHROME_BROWSER_SYNC_UTIL_IMMUTABLE_H_
67 #pragma once
68
69 // For std::swap().
70 #include <algorithm>
71
72 #include "base/basictypes.h"
73 #include "base/memory/ref_counted.h"
74
75 namespace browser_sync {
76
77 namespace internal {
78 // This class is part of the Immutable implementation. DO NOT USE
79 // THIS CLASS DIRECTLY YOURSELF.
80
81 template <typename T, typename Traits>
82 class ImmutableCore
83 : public base::RefCountedThreadSafe<ImmutableCore<T, Traits> > {
84 public:
85 // container_ is always explicitly default-initialized to handle
86 // primitive types.
87
88 ImmutableCore() : container_() {
89 Traits::CreateAndDefaultInitialize(&container_);
90 }
91
92 explicit ImmutableCore(T* t) : container_() {
93 Traits::CreateAndDefaultInitialize(&container_);
94 Traits::Swap(Traits::UnwrapMutable(&container_), t);
95 }
96
97 const T& Get() const {
98 return Traits::Unwrap(container_);
99 }
100
101 private:
102 ~ImmutableCore() {
103 Traits::Destroy(&container_);
104 }
105 friend class base::RefCountedThreadSafe<ImmutableCore<T, Traits> >;
106
107 // This is semantically const, but we can't mark it a such as we
108 // modify it in the constructor.
109 typename Traits::Container container_;
110
111 DISALLOW_COPY_AND_ASSIGN(ImmutableCore);
112 };
113
114 } // namespace internal
115
116 // Traits usage notes
117 // ------------------
118 // The most common reason to use your own traits class is to provide
119 // your own swap method. First, consider the pre-defined traits
120 // classes HasSwapMemFn{ByRef,ByPtr} below. If neither of those work,
121 // then define your own traits class inheriting from
122 // DefaultImmutableTraits<YourType> (to pick up the defaults for
123 // everything else) and provide your own Swap() method.
124 //
125 // Another reason to use your own traits class is to be able to use
126 // Immutable<T> with a forward-declared type (important for protobuf
127 // classes, when you want to avoid headers pulling in generated
128 // headers). For example, if you want to do this:
Nicolas Zea 2011/09/15 23:39:46 I find the distinction between the immutable type
akalin 2011/09/16 00:59:59 Done.
129 //
130 // my_class.h
131 // ----------
132 // #include ".../immutable.h"
133 //
134 // // Forward declaration.
135 // class SomeOtherType;
136 //
137 // class MyClass {
138 // ...
139 // private:
140 // // Doesn't work, as defaults traits class needs SomeOtherType's
141 // // definition to be visible.
142 // Immutable<SomeOtherType> foo_;
143 // };
144 //
145 // You'll have to do this:
146 //
147 // my_class.h
148 // ----------
149 // #include ".../immutable.h"
150 //
151 // // Forward declaration.
152 // class SomeOtherType;
153 //
154 // class MyClass {
155 // ...
156 // private:
157 // struct ImmutableSomeOtherTypeTraits {
158 // // scoped_ptr<SomeOtherType> won't work here, either.
159 // typedef SomeOtherType* Container;
160 //
161 // static void CreateAndDefaultInitialize...
162 // ...
163 // };
164 //
165 // typedef Immutable<SomeOtherType, ImmutableSomeOtherTypeTraits>
166 // ImmutableSomeOtherType;
167 //
168 // ImmutableSomeOtherType foo_;
169 // };
170 //
171 // my_class.cc
172 // -----------
173 // #include ".../some_other_type.h"
174 //
175 // void MyClass::ImmutableSomeOtherTypeTraits::CreateAndDefaultInitialize(
176 // Container* t) {
177 // *t = new SomeOtherType();
178 // }
179 //
180 // void MyClass::ImmutableSomeOtherTypeTraits::Destroy(Container* t) {
181 // delete *t;
182 // }
183 //
184 // ...
185 //
186 // Also note that this incurs an additional memory allocation when you
187 // create an Immutable<SomeOtherType>.
188
189 template <typename T>
190 struct DefaultImmutableTraits {
191 typedef T Container;
192
193 // The container is already default-initialized, so do nothing.
194 static void CreateAndDefaultInitialize(Container* container) {}
195
196 // Since the container is automatically destroyed, no need to do
197 // anything.
198 static void Destroy(Container* container) {}
199
200 static const T& Unwrap(const Container& container) { return container; }
201
202 static T* UnwrapMutable(Container* container) { return container; }
203
204 static void Swap(T* t1, T* t2) {
205 // Uses ADL (see
206 // http://en.wikipedia.org/wiki/Argument-dependent_name_lookup).
207 using std::swap;
208 swap(*t1, *t2);
209 }
210 };
211
212 // Most STL containers have by-reference swap() member functions,
213 // although they usually already overload std::swap() to use those.
214 template <typename T>
215 struct HasSwapMemFnByRef : public DefaultImmutableTraits<T> {
216 static void Swap(T* t1, T* t2) {
217 t1->swap(*t2);
218 }
219 };
220
221 // Most Google-style objects have by-pointer Swap() member functions
222 // (for example, generated protocol buffer classes).
223 template <typename T>
224 struct HasSwapMemFnByPtr : public DefaultImmutableTraits<T> {
225 static void Swap(T* t1, T* t2) {
226 t1->Swap(t2);
227 }
228 };
229
230 template <typename T, typename Traits = DefaultImmutableTraits<T> >
231 class Immutable {
232 public:
233 // Puts the underlying object in a default-initialized state.
234 Immutable() : core_(new internal::ImmutableCore<T, Traits>()) {}
235
236 // Copy constructor and assignment welcome.
237
238 // Resets |t| to a default-initialized state.
239 explicit Immutable(T* t)
240 : core_(new internal::ImmutableCore<T, Traits>(t)) {}
241
242 const T& Get() const {
243 return core_->Get();
244 }
245
246 private:
247 scoped_refptr<const internal::ImmutableCore<T, Traits> > core_;
248 };
249
250 // Helper function to avoid having to write out template arguments.
251 template <typename T>
252 Immutable<T> MakeImmutable(T* t) {
253 return Immutable<T>(t);
254 }
255
256 } // namespace browser_sync
257
258 #endif // CHROME_BROWSER_SYNC_UTIL_IMMUTABLE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698