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

Side by Side Diff: third_party/cld/base/googleinit.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
« no previous file with comments | « third_party/cld/base/google.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #ifndef BASE_GOOGLEINIT_H_
6 #define BASE_GOOGLEINIT_H_
7
8 //------------------------------------------------------------------------
9
10 // Initialization sequence in C++ and Google.
11 //
12 // This library provides helpers to arrange pieces of initialization code
13 // for some global objects/state to be executed at well-defined
14 // moment in time and in a well-defined order.
15 //
16 // This library is flexible enough and should be used to do all
17 // initialization for global/static objects
18 // except maybe for a few very-low level libraries (mainly inside //base).
19 // Comments in googleinit.cc discuss the reasons for this.
20 //
21 // For the default *MODULE* macros provided below,
22 // the initialization happens automatically
23 // during execution of InitGoogle() -- see google.h,
24 // a call to which should normally be the first statement of main().
25 //
26 // A module can register code to be executed by InitGoogle().
27 // For example, one could place the following in common/hostname.cc:
28 //
29 // static const char* my_hostname = NULL;
30 // REGISTER_MODULE_INITIALIZER(hostname, {
31 // // Code to initialize "my_hostname"
32 // });
33 //
34 // (Note that, due to preprocessor weirdness, there may be issues with
35 // the use of commas in your initialization code. If you run into them,
36 // try using parens around the commas, or use a helper function as follows:
37 //
38 // static const char* my_hostname = NULL;
39 // static void InitMyHostname() {
40 // // Code to initialize "my_hostname"
41 // }
42 // REGISTER_MODULE_INITIALIZER(my_hostname, InitMyHostname());
43 //
44 // This also helps the compiler to accurately attribute compilation errors
45 // to pieces of your initialization code.
46 //
47 // Note that each piece of registered initialized code is tagged
48 // with an identifier ('my_hostname' in the previous example). This
49 // is useful to control the order of initialization. For example,
50 // if we want file initialization to occur after hostname
51 // initialization, we can place the following in file/base/file.cc:
52 //
53 // REGISTER_MODULE_INITIALIZER(file, {
54 // // File initialization goes here
55 // });
56 // REGISTER_MODULE_INITIALIZER_SEQUENCE(my_hostname, file);
57 // // requires my_hostname's initializer to run before file's
58 //
59 // Alternatively the following *deprecated* method is also supported
60 // to accomplish the same ordering of initialization:
61 //
62 // REGISTER_MODULE_INITIALIZER(file, {
63 // REQUIRE_MODULE_INITIALIZED(my_hostname);
64 // // File initialization goes here
65 // });
66 //
67 // REQUIRE_MODULE_INITIALIZED should really be used only when
68 // REGISTER_MODULE_INITIALIZER_SEQUENCE can not be e.g. to explicitly make
69 // a subset of initializers executed from some non-initializer code or
70 // to define run-time-dependent module dependencies.
71 //
72 // For either of the above to compile we should also place the following
73 // into common/hostname.h and #include that file into file/base/file.cc:
74 //
75 // DECLARE_MODULE_INITIALIZER(my_hostname);
76 //
77 // Initialization dependencies defined via REGISTER_MODULE_INITIALIZER_SEQUENCE
78 // are more flexible: unlike with REQUIRE_MODULE_INITIALIZED, one can also
79 // require that the initialization code defined in the current .cc file
80 // be executed before some other initializer, e.g.:
81 //
82 // In foo_factory.h:
83 // DECLARE_MODULE_INITIALIZER(foo_factory_init);
84 // DECLARE_MODULE_INITIALIZER(foo_factory);
85 //
86 // In foo_factory.cc:
87 // static FooFactory* foo_factory = NULL
88 // REGISTER_MODULE_INITIALIZER(foo_factory_init, {
89 // foo_factory = new FooFactory(...);
90 // });
91 // REGISTER_MODULE_INITIALIZER(foo_factory, {
92 // // e.g. code for some final assimilation of all things registered
93 // // with foo_factory can go here
94 // });
95 // REGISTER_MODULE_INITIALIZER_SEQUENCE(foo_factory_init, foo_factory);
96 //
97 // In my_foo_maker.cc:
98 // REGISTER_MODULE_INITIALIZER(my_registerer, {
99 // // registration of some my_method with foo_factory goes here
100 // });
101 // REGISTER_MODULE_INITIALIZER_SEQUENCE_3(
102 // foo_factory_init, my_registerer, foo_factory);
103 // // my_registerer runs after foo_factory_init, but before foo_factory
104 //
105 // In foo_factory_user.cc:
106 // REGISTER_MODULE_INITIALIZER(foo_user, {
107 // // use of foo_factory goes here
108 // });
109 // REGISTER_MODULE_INITIALIZER_SEQUENCE(foo_factory, foo_user);
110 //
111 // In the above example the initializer execution order will be
112 // foo_factory_init, my_registerer, foo_factory, foo_user
113 // even though both foo_factory.cc and foo_factory_user.cc do not have
114 // explicit dependencies on my_foo_maker.cc (they do not have to know/care
115 // if it exists).
116 //
117 // It is an error to introduce cycles in the initialization
118 // dependencies. The program will die with an error message
119 // if the initialization code encounters cyclic dependencies.
120 //
121 // Normally all the registered initializers are executed after
122 // command-line flags have been parsed.
123 // If you need your initializer to run before parsing of the command-line flags,
124 // e.g. to adjust the (default) value of certain flags, then include google.h
125 // and add a directive like this to your .cc file:
126 //
127 // REGISTER_MODULE_INITIALIZER_SEQUENCE(
128 // my_foo_init, command_line_flags_parsing);
129 //
130 // Note that you can't instead call
131 // REQUIRE_MODULE_INITIALIZED(command_line_flags_parsing);
132 // in the code of your initializer: actual command-line parsing
133 // is executed by InitGoogle() not in a registered initializer.
134 //
135 // A piece of code can declare a dependency on a module using the
136 // REQUIRE_MODULE macro. This macro creates a link time dependency
137 // between the .o which the macro is compiled in and the specified
138 // module. This can be useful in making link time dependencies
139 // explicit in the code instead of relying on the correctness of the
140 // BUILD files. For example, foo.cc can declare (see
141 // file/base/file.h for the REQUIRE_FILE_MODULE definition):
142 //
143 // REQUIRE_FILE_MODULE(localfile);
144 //
145 // Similarly to other uses, DECLARE_FILE_INITIALIZER(localfile)
146 // should be #include-d for the above to compile.
147 // The above will guarantee that the localfile module will be linked into
148 // an application which foo.cc is linked into. Specifically, a link
149 // error will occur if the localfile module is not linked in. The
150 // preferred usage of REQUIRE_*_MODULE is for the module writer to
151 // provide an external .h which contains the REQUIRE_* macro. In the
152 // above example, the localfile module writer would provide localfile.h:
153 //
154 // #ifndef FILE_LOCALFILE_H_
155 // #define FILE_LOCALFILE_H_
156 //
157 // #include "file/base/file.h"
158 //
159 // DECLARE_FILE_INITIALIZER(localfile);
160 // REQUIRE_FILE_MODULE(localfile);
161 //
162 // #endif // FILE_LOCALFILE_H_
163 //
164 // Now a user of localfile can declare their dependence on it by
165 // #including "localfile.h".
166
167 //------------------------------------------------------------------------
168
169 // The following code is mostly ugly details about how the
170 // initialization is implemented, and can be safely ignored
171 // by users of the initialization facility.
172
173 #include <string>
174
175 #include "base/basictypes.h"
176
177 // A static instance of 'GoogleInitializer' is declared for every
178 // piece of initialization code. The constructor registers the
179 // code in the initialization table. This class is thread-safe.
180 class GoogleInitializer {
181 public:
182 typedef void (*Initializer)();
183
184 // Register the specified initialization "function" as the
185 // initialization code for "name". The "type" parameter controls
186 // which initializer set this initializer will added to. Note that
187 // an initializer might end up being run from a different set if it
188 // is required using the REQUIRE_GOOGLE_INITIALIZED macro. Normally
189 // the type parameter is "module". Its existence allows the
190 // specification of other "initializer sets." See file/base/file.h
191 // and File::Init() for an example of such a set. It's unlikely this
192 // additional functionality will be used very often.
193 GoogleInitializer(const char* type, const char* name, Initializer function);
194
195 // Invoke all registered initializers that have not yet been
196 // executed. The "type" parameter specifies which set of
197 // initializers to run. The initializers are invoked in
198 // lexicographically increasing order by name, except as necessary
199 // to satisfy dependencies. This routine is invoked by InitGoogle(),
200 // so application code should not call it except in special
201 // circumstances.
202 static void RunInitializers(const char* type);
203
204 // If this initialization has not yet been executed, runs it
205 // right after running all the initializers registered to come before it,
206 // these initializers are invoked in lexicographically increasing order
207 // by name, except as necessary to satisfy dependencies.
208 // It is an error to call this method if the corresponding
209 // initializer method is currently active (i.e., we do not
210 // allow cycles in the requirement graph).
211 void Require();
212
213 // Helper data-holder struct that is passed into
214 // DependencyRegisterer's c-tor below.
215 struct Dependency {
216 Dependency(const char* n, GoogleInitializer* i) : name(n), initializer(i) {}
217 const char* const name;
218 GoogleInitializer* const initializer;
219 };
220
221 // A static instance of 'DependencyRegisterer' is declared for every
222 // piece of initializer ordering definition. The constructor registers the
223 // ordering relation in the initialization table. This class is thread-safe.
224 struct DependencyRegisterer {
225 // Ask to run initializer specified by 'dependency'
226 // before the 'initializer' with 'name'.
227 // Both initializers are supposed to be of type 'type'.
228 DependencyRegisterer(const char* type,
229 const char* name,
230 GoogleInitializer* initializer,
231 const Dependency& dependency);
232 private:
233 void SharedConstructorCode(const char* type,
234 const char* name,
235 GoogleInitializer* initializer,
236 const Dependency& dependency);
237
238 DISALLOW_EVIL_CONSTRUCTORS(DependencyRegisterer);
239 };
240
241 // Side note: If we happen to decide that connecting all initializers into an
242 // explicit DAG with one/few sink node(s) that depend on everything else
243 // is important (to explicitly specify in code all the
244 // required initializers of a binary) we can provide something like
245 // static bool DoneAllInitializers(const char *type);
246 // to check that all registered initializers have been executed.
247 // Going this route does not seem worth it though:
248 // it's equivalent to mandating creation of a third complete
249 // module dependency DAG, the first two being via #include-s and BUILD
250 // dependencies.
251
252 // Helper structs in .cc; public to declare file-level globals.
253 struct InitializerData;
254 struct TypeData;
255
256 private:
257 void SharedConstructorCode(const char* type,
258 const char* name,
259 Initializer function);
260
261 const string type_; // Initializer type
262 const string name_; // Initializer name
263 Initializer function_; // The actual initializer
264 bool done_; // Finished initializing?
265 bool is_active_; // Is currently running
266
267 // Implementation helper for Require() and RunInitializers:
268 // Runs initializer *this and all its dependencies
269 // if that has not happened yet.
270 // Assumes table_lock is reader-held and TypeData::lock for type_ is held.
271 void RunIfNecessary_Locked();
272
273 // Helper to initialize/create and return data for a given initializer type.
274 static TypeData* InitializerTypeData(const char* type);
275
276 DISALLOW_EVIL_CONSTRUCTORS(GoogleInitializer);
277 };
278
279 //------------------------------------------------------------------------
280
281 // Implementation Internals (most users should ignore)
282 //
283 // The *_GOOGLE_* macros are used to make separate initializer
284 // sets. They should not be used directly by application code, but are
285 // useful to library writers who want to create a new registration
286 // mechanism. (See google2file.h and the *_FILE_* macros for an
287 // example).
288
289 // TODO(maxim): When DECLARE_GOOGLE_INITIALIZER is not used in
290 // REQUIRE_GOOGLE_INITIALIZED and REQUIRE_GOOGLE_MODULE
291 // put google_initializer_##type##_##name (and google_init_##type##_##name)
292 // into a gI##type namespace to force our users to use
293 // DECLARE_GOOGLE_INITIALIZER not reimplement it
294 // to manually declare an initializer.
295
296 #define DECLARE_GOOGLE_INITIALIZER(type, name) \
297 extern GoogleInitializer google_initializer_##type##_##name
298
299 #define REGISTER_GOOGLE_INITIALIZER(type, name, body) \
300 static void google_init_##type##_##name() { body; } \
301 GoogleInitializer google_initializer_##type##_##name( \
302 #type, #name, google_init_##type##_##name)
303
304 // Require initializer name1 of 'type' to run before initializer
305 // initializer name2 of same 'type' (i.e. in the order they are written out).
306 // "Sequence" only means ordering, not direct executions sequence
307 // without any other initializer executed in between.
308 // Initializers for both modules must be declared
309 // with DECLARE_GOOGLE_INITIALIZER at this point.
310 #define REGISTER_GOOGLE_INITIALIZER_SEQUENCE(type, name1, name2) \
311 namespace { \
312 static GoogleInitializer::DependencyRegisterer \
313 google_initializer_dependency_##type##_##name1##_##name2( \
314 #type, #name2, &google_initializer_##type##_##name2, \
315 GoogleInitializer::Dependency( \
316 #name1, &google_initializer_##type##_##name1)); \
317 }
318 // Require initializers name1, name2, name3 of 'type' to run in the above order.
319 // Added to support this frequent use case more conveniently.
320 #define REGISTER_GOOGLE_INITIALIZER_SEQUENCE_3(type, name1, name2, name3) \
321 REGISTER_GOOGLE_INITIALIZER_SEQUENCE(type, name1, name2); \
322 REGISTER_GOOGLE_INITIALIZER_SEQUENCE(type, name2, name3)
323
324 // Calling REQUIRE_GOOGLE_INITIALIZED(type, foo) means to make sure intializer
325 // for foo and everything it depends on have executed, and as such
326 // it can be used to e.g. pre-execute subsets of initializers
327 // e.g. before everything is executed via RUN_GOGLE_INITIALIZERS(type).
328 // The initializer must be declared with DECLARE_GOOGLE_INITIALIZER(type, name).
329 // TODO : remove DECLARE_GOOGLE_INITIALIZER here
330 // when all old code makes use of DECLARE_GOOGLE_INITIALIZER.
331 #define REQUIRE_GOOGLE_INITIALIZED(type, name) \
332 do { \
333 DECLARE_GOOGLE_INITIALIZER(type, name); \
334 google_initializer_##type##_##name.Require(); \
335 } while (0)
336
337 #define RUN_GOOGLE_INITIALIZERS(type) \
338 do { \
339 GoogleInitializer::RunInitializers(#type); \
340 } while (0)
341
342 // We force the dependant module to be loaded by taking the
343 // address of an object inside the dependency
344 // (created by REGISTER_GOOGLE_INITIALIZER). The rest
345 // is required to avoid warnings about unused variables and
346 // make sure gcc doesn't optimize it out of existence.
347 // The initializer must be declared with DECLARE_GOOGLE_INITIALIZER(type, name).
348 // TODO : remove DECLARE_GOOGLE_INITIALIZER here
349 // when all old code makes use of DECLARE_GOOGLE_INITIALIZER.
350 #define REQUIRE_GOOGLE_MODULE(type, name) \
351 DECLARE_GOOGLE_INITIALIZER(type, name); \
352 static struct GoogleModuleRef_##name { \
353 GoogleModuleRef_##name(GoogleInitializer* r) : ref(r) {} \
354 GoogleInitializer* ref; \
355 } google_module_ref_##name(&google_initializer_##type##_##name)
356
357
358 // External Interface (most users should use these macros)
359
360 #define DECLARE_MODULE_INITIALIZER(name) \
361 DECLARE_GOOGLE_INITIALIZER(module, name)
362
363 #define REGISTER_MODULE_INITIALIZER(name, body) \
364 REGISTER_GOOGLE_INITIALIZER(module, name, body)
365
366 #define REGISTER_MODULE_INITIALIZER_SEQUENCE(name1, name2) \
367 REGISTER_GOOGLE_INITIALIZER_SEQUENCE(module, name1, name2)
368
369 #define REGISTER_MODULE_INITIALIZER_SEQUENCE_3(name1, name2, name3) \
370 REGISTER_GOOGLE_INITIALIZER_SEQUENCE_3(module, name1, name2, name3)
371
372 #define REQUIRE_MODULE_INITIALIZED(name) \
373 REQUIRE_GOOGLE_INITIALIZED(module, name)
374
375 #define RUN_MODULE_INITIALIZERS() \
376 RUN_GOOGLE_INITIALIZERS(module)
377
378 // TODO : maybe rename this as REQUIRE_MODULE_LINKED
379 #define REQUIRE_MODULE(name) \
380 REQUIRE_GOOGLE_MODULE(module, name)
381
382 //------------------------------------------------------------------------
383
384 #endif // BASE_GOOGLEINIT_H_
OLDNEW
« no previous file with comments | « third_party/cld/base/google.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698