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

Side by Side Diff: third_party/cld/base/callback.h

Issue 132032: [chromium-reviews] Add unit testing to CLD. In addition, remove files from cld/base which are no... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 6 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) 2006-2009 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 // Callback classes provides a generic interface for classes requiring
6 // callback from other classes.
7 // We support callbacks with 0, 1, 2, 3, and 4 arguments.
8 // Closure -- provides "void Run()"
9 // Callback1<T1> -- provides "void Run(T1)"
10 // Callback2<T1,T2> -- provides "void Run(T1, T2)"
11 // Callback3<T1,T2,T3> -- provides "void Run(T1, T2, T3)"
12 // Callback4<T1,T2,T3,T4> -- provides "void Run(T1, T2, T3, T4)"
13 //
14 // In addition, ResultCallback classes provide a generic interface for
15 // callbacks that return a value.
16 // ResultCallback<R> -- provides "R Run()"
17 // ResultCallback1<R,T1> -- provides "R Run(T1)"
18 // ResultCallback2<R,T1,T2> -- provides "R Run(T1, T2)"
19 // ResultCallback3<R,T1,T2,T3> -- provides "R Run(T1, T2, T3)"
20 // ResultCallback4<R,T1,T2,T3,T4> -- provides "R Run(T1, T2, T3, T4)"
21
22 // We provide a convenient mechanism, NewCallback, for generating one of these
23 // callbacks given an object pointer, a pointer to a member
24 // function with the appropriate signature in that object's class,
25 // and some optional arguments that can be bound into the callback
26 // object. The mechanism also works with just a function pointer.
27 //
28 // Note: there are two types of arguments passed to the callback method:
29 // * "pre-bound arguments" - supplied when the callback object is created
30 // * "call-time arguments" - supplied when the callback object is invoked
31 //
32 // These two types correspond to "early binding" and "late
33 // binding". An argument whose value is known when the callback is
34 // created ("early") can be pre-bound (a.k.a. "Curried"), You can
35 // combine pre-bound and call-time arguments in different ways. For
36 // example, invoking a callback with 3 pre-bound arguments and 1
37 // call-time argument will have the same effect as invoking a callback
38 // with 2 pre-bound arguments and 2 call-time arguments, or 4
39 // pre-bound arguments and no call-time arguments. This last case is
40 // often useful; a callback with no call-time arguments is a Closure;
41 // these are used in many places in the Google libraries, e.g., "done"
42 // closures. See the examples below.
43 //
44 // WARNING: In the current implementation (or perhaps with the current
45 // compiler) NewCallback() is pickier about the types of pre-bound arguments
46 // than you might expect. The types must match exactly, rather than merely
47 // being compatible.
48 // For example, if you pre-bind an argument with the "const" specifier,
49 // make sure that the actual parameter passed to NewCallback also has the
50 // const specifier. If you don't you'll get an error about
51 // passing a your function "as argument 1 of NewCallback(void (*)())".
52 // Using a method or function that has reference arguments among its pre-bound
53 // arguments may not always work.
54 //
55 // Examples:
56 //
57 // void Call0(Closure* cb) { cb->Run(); }
58 // void Call1(Callback1<int>* cb, int a) { cb->Run(a); }
59 // void Call2(Callback2<int, float>* cb, int a, float f) { cb->Run(a, f); }
60 // float Call3(ResultCallback1<float, int>* cb, int a) { return cb->Run(a); }
61 //
62 // class Foo {
63 // public:
64 // void A(int a);
65 // void B(int a, float f);
66 // void C(const char* label, int a, float f);
67 // float D(int a);
68 // };
69 // void F0(int a);
70 // void F1(int a, float f);
71 // void F2(const char *label, int a, float f);
72 // float F3(int a);
73 // float v;
74 //
75 // // Run stuff immediately
76 // // calling a method
77 // Foo* foo = new Foo;
78 //
79 // NewCallback(foo, &Foo::A) ->Run(10); // 0 [pre-bound] + 1 [call-tim e]
80 // == NewCallback(foo, &Foo::A, 10) ->Run(); // 1 + 0
81 // == foo->A(10);
82 //
83 // NewCallback(foo, &Foo::B) ->Run(10, 3.0f); // 0 + 2
84 // == NewCallback(foo, &Foo::B, 10) ->Run(3.0f); // 1 + 1
85 // == NewCallback(foo, &Foo::B, 10, 3.0f) ->Run(); // 2 + 0
86 // == foo->B(10, 3.0f);
87 //
88 // NewCallback(foo, &Foo::C) ->Run("Y", 10, 3.0f); // 0 + 3
89 // == NewCallback(foo, &Foo::C, "Y") ->Run(10, 3.0f); // 1 + 2
90 // == NewCallback(foo, &Foo::C, "Y", 10) ->Run(3.0f); // 2 + 1
91 // == NewCallback(foo, &Foo::C, "Y", 10, 3.0f) ->Run(); // 3 + 0
92 // == foo->C("Y", 10, 3.0f);
93 //
94 // v = NewCallback(foo, &Foo::D) ->Run(10); == v = foo->D(10)
95 //
96 // // calling a function
97 // NewCallback(F0) ->Run(10); // == F0(10) // 0 + 1
98 // NewCallback(F0, 10) ->Run(); // == F0(10) // 1 + 0
99 // NewCallback(F1) ->Run(10, 3.0f); // == F1(10, 3.0f)
100 // NewCallback(F2, "X") ->Run(10, 3.0f); // == F2("X", 10, 3.0f)
101 // NewCallback(F2, "Y") ->Run(10, 3.0f); // == F2("Y", 10, 3.0f)
102 // v = NewCallback(F3) ->Run(10); // == v = F3(10)
103 //
104 //
105 // // Pass callback object to somebody else, who runs it.
106 // // Calling a method:
107 // Call1(NewCallback(foo, &Foo::A), 10); // 0 + 1
108 // == Call0(NewCallback(foo, &Foo::A, 10) ); // 1 + 0
109 // == foo->A(10)
110 //
111 // Call2(NewCallback(foo, &Foo::B), 10, 3.0f); // 0 + 2
112 // == Call1(NewCallback(foo, &Foo::B, 10), 3.0f); // 1 + 1
113 // == Call0(NewCallback(foo, &Foo::B, 10, 30.f) ); // 2 + 0
114 // == foo->B(10, 3.0f)
115 //
116 // Call2(NewCallback(foo, &Foo::C, "X"), 10, 3.0f); == foo->C("X", 10, 3.0f)
117 // Call2(NewCallback(foo, &Foo::C, "Y"), 10, 3.0f); == foo->C("Y", 10, 3.0f)
118 //
119 // // Calling a function:
120 // Call1(NewCallback(F0), 10); // 0 + 1
121 // == Call0(NewCallback(F0, 10) ); // 1 + 0
122 // == F0(10);
123 //
124 // Call2(NewCallback(F1), 10, 3.0f); // == F1(10, 3.0f)
125 // Call2(NewCallback(F2, "X"), 10, 3.0f); // == F2("X", 10, 3.0f)
126 // Call2(NewCallback(F2, "Y"), 10, 3.0f); // == F2("Y", 10, 3.0f)
127 // v = Call3(NewCallback(F3), 10); // == v = F3(10)
128 //
129 // Example of a "done" closure:
130 //
131 // SelectServer ss;
132 // Closure* done = NewCallback(&ss, &SelectServer::MakeLoopExit);
133 // ProcessMyControlFlow(..., done);
134 // ss.Loop();
135 // ...
136 //
137 // The following WILL NOT WORK:
138 // NewCallback(F2, (char *) "Y") ->Run(10, 3.0f);
139 // It gets the error:
140 // passing `void (*)(const char *, int, float)' as argument 1 of
141 // `NewCallback(void (*)())'
142 // The problem is that "char *" is not an _exact_ match for
143 // "const char *", even though it's normally a legal implicit
144 // conversion.
145 //
146 //
147 // The callback objects generated by NewCallback are self-deleting:
148 // i.e., they call the member function, and then delete themselves.
149 // If you want a callback that does not delete itself every time
150 // it runs, use "NewPermanentCallback" instead of "NewCallback".
151 //
152 // All the callback/closure classes also provide
153 // virtual void CheckIsRepeatable() const;
154 // It crashes if (we know for sure that) the callback's Run method
155 // can not be called an arbitrary number of times (including 0).
156 // It crashes for all NewCallback() generated callbacks,
157 // does not crash for NewPermanentCallback() generated callbacks,
158 // and although by default it does not crash for all callback-derived classes,
159 // for these new types of callbacks, the callback writer is encouraged to
160 // redefine this method appropriately.
161 //
162 // CAVEAT: Interfaces that accept callback pointers should clearly document
163 // if they might call Run methods of those callbacks multiple times
164 // (and use "c->CheckIsRepeatable();" as an active precondition check),
165 // or if they call the callbacks exactly once or potentially not at all,
166 // as well as if they take ownership of the passed callbacks
167 // (i.e. might manually deallocate them without calling their Run methods).
168 // The clients can then provide properly allocated and behaving callbacks
169 // (e.g. choose between NewCallback, NewPermanentCallback, or a custom object).
170 // Obviously, one should also be careful to ensure that the data a callback
171 // points to and needs for its Run method is still live when
172 // the Run method might be called.
173 //
174 // MOTIVATION FOR CALLBACK OBJECTS
175 // -------------------------------
176 // It frees service providers from depending on service requestors by
177 // calling a generic callback other than a callback which depends on
178 // the service requestor (typically its member function). As a
179 // result, service provider classes can be developed independently.
180 //
181 // Typical usage: Suppose class A wants class B to do something and
182 // notify A when it is done. As part of the notification, it wants
183 // to be given a boolean that says what happened.
184 //
185 // class A {
186 // public:
187 // void RequestService(B* server) {
188 // ...
189 // server->StartService(NewCallback(this, &A::ServiceDone), other_args));
190 // // the new callback deletes itself after it runs
191 // }
192 // void ServiceDone(bool status) {...}
193 // };
194 //
195 // Class B {
196 // public:
197 // void StartService(Callback1<bool>* cb, other_args) : cb_(cb) { ...}
198 // void FinishService(bool result) { ...; cb_->Run(result); }
199 // private:
200 // Callback1<bool>* cb_;
201 // };
202 //
203 // As can be seen, B is completely independent of A. (Of course, they
204 // have to agree on callback data type.)
205 //
206 // The result of NewCallback() is thread-compatible. The result of
207 // NewPermanentCallback() is thread-safe if the call its Run() method
208 // represents is thread-safe and thread-compatible otherwise.
209 //
210 // Other modules associated with callbacks may be found in //util/callback
211 //
212 // USING CALLBACKS WITH TRACECONTEXT
213 // ---------------------------------
214 // Callbacks generated by NewCallback() automatically propagate trace
215 // context. Callbacks generated by NewPermanentCallback() do not. For
216 // manually-derived subclasses of Closure and CallbackN, you may decide
217 // to propagate TraceContext as follows.
218 //
219 // struct MyClosure : public Closure {
220 // MyClosure()
221 // : Closure(TraceContext::THREAD) { }
222 //
223 // void Run() {
224 // TraceContext *tc = TraceContext::Thread();
225 // tc->Swap(&trace_context_);
226 // DoMyOperation()
227 // tc->Swap(&trace_context_);
228 // delete this;
229 // }
230 // };
231
232 #ifndef _CALLBACK_H_
233 #define _CALLBACK_H_
234
235 #include <functional>
236
237 // The actual callback classes and various NewCallback() implementations
238 // are automatically generated by base/generate-callback-specializations.py.
239 // We include that output here.
240 #include "base/callback-specializations.h"
241
242 // A new barrier closure executes another closure after it has been
243 // invoked N times, and then deletes itself.
244 //
245 // If "N" is zero, the supplied closure is executed immediately.
246 // Barrier closures are thread-safe. They use an atomic operation to
247 // guarantee a correct count.
248 //
249 // REQUIRES N >= 0.
250 extern Closure* NewBarrierClosure(int N, Closure* done_closure);
251
252 // Function that does nothing; can be used to make new no-op closures:
253 // NewCallback(&DoNothing)
254 // NewPermanentCallback(&DoNothing)
255 // This is a replacement for the formerly available TheNoopClosure() primitive.
256 extern void DoNothing();
257
258 // AutoClosureRunner executes a closure upon deletion. This class
259 // is similar to scoped_ptr: it is typically stack-allocated and can be
260 // used to perform some type of cleanup upon exiting a block.
261 //
262 // Note: use of AutoClosureRunner with Closures that must be executed at
263 // specific points is discouraged, since the point at which the Closure
264 // executes is not explicitly marked. For example, consider a Closure
265 // that should execute after a mutex has been released. The following
266 // code looks correct, but executes the Closure too early (before release):
267 // {
268 // MutexLock l(...);
269 // AutoClosureRunner r(run_after_unlock);
270 // ...
271 // }
272 // AutoClosureRunner is primarily intended for cleanup operations that
273 // are relatively independent from other code.
274 //
275 // The Reset() method replaces the callback with a new callback. The new
276 // callback can be supplied as NULL to disable the AutoClosureRunner. This is
277 // intended as part of a strategy to execute a callback at all exit points of a
278 // method except where Reset() was called. This method must be used only with
279 // non-permanent callbacks. The Release() method disables and returns the
280 // callback, instead of deleting it.
281 class AutoClosureRunner {
282 private:
283 Closure* closure_;
284 public:
285 explicit AutoClosureRunner(Closure* c) : closure_(c) {}
286 ~AutoClosureRunner() { if (closure_) closure_->Run(); }
287 void Reset(Closure *c) { delete closure_; closure_ = c; }
288 Closure* Release() { Closure* c = closure_; closure_ = NULL; return c; }
289 private:
290 DISALLOW_EVIL_CONSTRUCTORS(AutoClosureRunner);
291 };
292
293 // DeletePointerClosure can be used to create a closure that calls delete
294 // on a pointer. Here is an example:
295 //
296 // thread->Add(DeletePointerClosure(expensive_to_delete));
297 //
298 template<typename T>
299 void DeletePointer(T* p) {
300 delete p;
301 }
302
303 template<typename T>
304 Closure* DeletePointerClosure(T* p) {
305 return NewCallback(&DeletePointer<T>, p);
306 }
307
308 #endif /* _CALLBACK_H_ */
OLDNEW
« no previous file with comments | « third_party/cld/bar/toolbar/cld/i18n/encodings/compact_lang_det/win/cld_google.h ('k') | third_party/cld/base/closure.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698