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

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

Issue 9699057: [Sync] Move 'sync' target to sync/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Tim's comments Created 8 years, 9 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 // wrapper_ is always explicitly default-initialized to handle
86 // primitive types and the case where Traits::Wrapper == T.
87
88 ImmutableCore() : wrapper_() {
89 Traits::InitializeWrapper(&wrapper_);
90 }
91
92 explicit ImmutableCore(T* t) : wrapper_() {
93 Traits::InitializeWrapper(&wrapper_);
94 Traits::Swap(Traits::UnwrapMutable(&wrapper_), t);
95 }
96
97 const T& Get() const {
98 return Traits::Unwrap(wrapper_);
99 }
100
101 private:
102 ~ImmutableCore() {
103 Traits::DestroyWrapper(&wrapper_);
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::Wrapper wrapper_;
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). (This is why the Traits::Wrapper type exists; normally,
129 // Traits::Wrapper is just T itself, but that needs to be changed for
130 // forward-declared types.)
131 //
132 // For example, if you want to do this:
133 //
134 // my_class.h
135 // ----------
136 // #include ".../immutable.h"
137 //
138 // // Forward declaration.
139 // class SomeOtherType;
140 //
141 // class MyClass {
142 // ...
143 // private:
144 // // Doesn't work, as defaults traits class needs SomeOtherType's
145 // // definition to be visible.
146 // Immutable<SomeOtherType> foo_;
147 // };
148 //
149 // You'll have to do this:
150 //
151 // my_class.h
152 // ----------
153 // #include ".../immutable.h"
154 //
155 // // Forward declaration.
156 // class SomeOtherType;
157 //
158 // class MyClass {
159 // ...
160 // private:
161 // struct ImmutableSomeOtherTypeTraits {
162 // // scoped_ptr<SomeOtherType> won't work here, either.
163 // typedef SomeOtherType* Wrapper;
164 //
165 // static void InitializeWrapper(Wrapper* wrapper);
166 //
167 // static void DestroyWrapper(Wrapper* wrapper);
168 // ...
169 // };
170 //
171 // typedef Immutable<SomeOtherType, ImmutableSomeOtherTypeTraits>
172 // ImmutableSomeOtherType;
173 //
174 // ImmutableSomeOtherType foo_;
175 // };
176 //
177 // my_class.cc
178 // -----------
179 // #include ".../some_other_type.h"
180 //
181 // void MyClass::ImmutableSomeOtherTypeTraits::InitializeWrapper(
182 // Wrapper* wrapper) {
183 // *wrapper = new SomeOtherType();
184 // }
185 //
186 // void MyClass::ImmutableSomeOtherTypeTraits::DestroyWrapper(
187 // Wrapper* wrapper) {
188 // delete *wrapper;
189 // }
190 //
191 // ...
192 //
193 // Also note that this incurs an additional memory allocation when you
194 // create an Immutable<SomeOtherType>.
195
196 template <typename T>
197 struct DefaultImmutableTraits {
198 typedef T Wrapper;
199
200 static void InitializeWrapper(Wrapper* wrapper) {}
201
202 static void DestroyWrapper(Wrapper* wrapper) {}
203
204 static const T& Unwrap(const Wrapper& wrapper) { return wrapper; }
205
206 static T* UnwrapMutable(Wrapper* wrapper) { return wrapper; }
207
208 static void Swap(T* t1, T* t2) {
209 // Uses ADL (see
210 // http://en.wikipedia.org/wiki/Argument-dependent_name_lookup).
211 using std::swap;
212 swap(*t1, *t2);
213 }
214 };
215
216 // Most STL containers have by-reference swap() member functions,
217 // although they usually already overload std::swap() to use those.
218 template <typename T>
219 struct HasSwapMemFnByRef : public DefaultImmutableTraits<T> {
220 static void Swap(T* t1, T* t2) {
221 t1->swap(*t2);
222 }
223 };
224
225 // Most Google-style objects have by-pointer Swap() member functions
226 // (for example, generated protocol buffer classes).
227 template <typename T>
228 struct HasSwapMemFnByPtr : public DefaultImmutableTraits<T> {
229 static void Swap(T* t1, T* t2) {
230 t1->Swap(t2);
231 }
232 };
233
234 template <typename T, typename Traits = DefaultImmutableTraits<T> >
235 class Immutable {
236 public:
237 // Puts the underlying object in a default-initialized state.
238 Immutable() : core_(new internal::ImmutableCore<T, Traits>()) {}
239
240 // Copy constructor and assignment welcome.
241
242 // Resets |t| to a default-initialized state.
243 explicit Immutable(T* t)
244 : core_(new internal::ImmutableCore<T, Traits>(t)) {}
245
246 const T& Get() const {
247 return core_->Get();
248 }
249
250 private:
251 scoped_refptr<const internal::ImmutableCore<T, Traits> > core_;
252 };
253
254 // Helper function to avoid having to write out template arguments.
255 template <typename T>
256 Immutable<T> MakeImmutable(T* t) {
257 return Immutable<T>(t);
258 }
259
260 } // namespace browser_sync
261
262 #endif // CHROME_BROWSER_SYNC_UTIL_IMMUTABLE_H_
OLDNEW
« no previous file with comments | « chrome/browser/sync/util/get_session_name_win.cc ('k') | chrome/browser/sync/util/immutable_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698