diff options
Diffstat (limited to 'third_party/cld/base/googleinit.h')
-rw-r--r-- | third_party/cld/base/googleinit.h | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/third_party/cld/base/googleinit.h b/third_party/cld/base/googleinit.h new file mode 100644 index 0000000..0ccef8b --- /dev/null +++ b/third_party/cld/base/googleinit.h @@ -0,0 +1,384 @@ +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_GOOGLEINIT_H_ +#define BASE_GOOGLEINIT_H_ + +//------------------------------------------------------------------------ + +// Initialization sequence in C++ and Google. +// +// This library provides helpers to arrange pieces of initialization code +// for some global objects/state to be executed at well-defined +// moment in time and in a well-defined order. +// +// This library is flexible enough and should be used to do all +// initialization for global/static objects +// except maybe for a few very-low level libraries (mainly inside //base). +// Comments in googleinit.cc discuss the reasons for this. +// +// For the default *MODULE* macros provided below, +// the initialization happens automatically +// during execution of InitGoogle() -- see google.h, +// a call to which should normally be the first statement of main(). +// +// A module can register code to be executed by InitGoogle(). +// For example, one could place the following in common/hostname.cc: +// +// static const char* my_hostname = NULL; +// REGISTER_MODULE_INITIALIZER(hostname, { +// // Code to initialize "my_hostname" +// }); +// +// (Note that, due to preprocessor weirdness, there may be issues with +// the use of commas in your initialization code. If you run into them, +// try using parens around the commas, or use a helper function as follows: +// +// static const char* my_hostname = NULL; +// static void InitMyHostname() { +// // Code to initialize "my_hostname" +// } +// REGISTER_MODULE_INITIALIZER(my_hostname, InitMyHostname()); +// +// This also helps the compiler to accurately attribute compilation errors +// to pieces of your initialization code. +// +// Note that each piece of registered initialized code is tagged +// with an identifier ('my_hostname' in the previous example). This +// is useful to control the order of initialization. For example, +// if we want file initialization to occur after hostname +// initialization, we can place the following in file/base/file.cc: +// +// REGISTER_MODULE_INITIALIZER(file, { +// // File initialization goes here +// }); +// REGISTER_MODULE_INITIALIZER_SEQUENCE(my_hostname, file); +// // requires my_hostname's initializer to run before file's +// +// Alternatively the following *deprecated* method is also supported +// to accomplish the same ordering of initialization: +// +// REGISTER_MODULE_INITIALIZER(file, { +// REQUIRE_MODULE_INITIALIZED(my_hostname); +// // File initialization goes here +// }); +// +// REQUIRE_MODULE_INITIALIZED should really be used only when +// REGISTER_MODULE_INITIALIZER_SEQUENCE can not be e.g. to explicitly make +// a subset of initializers executed from some non-initializer code or +// to define run-time-dependent module dependencies. +// +// For either of the above to compile we should also place the following +// into common/hostname.h and #include that file into file/base/file.cc: +// +// DECLARE_MODULE_INITIALIZER(my_hostname); +// +// Initialization dependencies defined via REGISTER_MODULE_INITIALIZER_SEQUENCE +// are more flexible: unlike with REQUIRE_MODULE_INITIALIZED, one can also +// require that the initialization code defined in the current .cc file +// be executed before some other initializer, e.g.: +// +// In foo_factory.h: +// DECLARE_MODULE_INITIALIZER(foo_factory_init); +// DECLARE_MODULE_INITIALIZER(foo_factory); +// +// In foo_factory.cc: +// static FooFactory* foo_factory = NULL +// REGISTER_MODULE_INITIALIZER(foo_factory_init, { +// foo_factory = new FooFactory(...); +// }); +// REGISTER_MODULE_INITIALIZER(foo_factory, { +// // e.g. code for some final assimilation of all things registered +// // with foo_factory can go here +// }); +// REGISTER_MODULE_INITIALIZER_SEQUENCE(foo_factory_init, foo_factory); +// +// In my_foo_maker.cc: +// REGISTER_MODULE_INITIALIZER(my_registerer, { +// // registration of some my_method with foo_factory goes here +// }); +// REGISTER_MODULE_INITIALIZER_SEQUENCE_3( +// foo_factory_init, my_registerer, foo_factory); +// // my_registerer runs after foo_factory_init, but before foo_factory +// +// In foo_factory_user.cc: +// REGISTER_MODULE_INITIALIZER(foo_user, { +// // use of foo_factory goes here +// }); +// REGISTER_MODULE_INITIALIZER_SEQUENCE(foo_factory, foo_user); +// +// In the above example the initializer execution order will be +// foo_factory_init, my_registerer, foo_factory, foo_user +// even though both foo_factory.cc and foo_factory_user.cc do not have +// explicit dependencies on my_foo_maker.cc (they do not have to know/care +// if it exists). +// +// It is an error to introduce cycles in the initialization +// dependencies. The program will die with an error message +// if the initialization code encounters cyclic dependencies. +// +// Normally all the registered initializers are executed after +// command-line flags have been parsed. +// If you need your initializer to run before parsing of the command-line flags, +// e.g. to adjust the (default) value of certain flags, then include google.h +// and add a directive like this to your .cc file: +// +// REGISTER_MODULE_INITIALIZER_SEQUENCE( +// my_foo_init, command_line_flags_parsing); +// +// Note that you can't instead call +// REQUIRE_MODULE_INITIALIZED(command_line_flags_parsing); +// in the code of your initializer: actual command-line parsing +// is executed by InitGoogle() not in a registered initializer. +// +// A piece of code can declare a dependency on a module using the +// REQUIRE_MODULE macro. This macro creates a link time dependency +// between the .o which the macro is compiled in and the specified +// module. This can be useful in making link time dependencies +// explicit in the code instead of relying on the correctness of the +// BUILD files. For example, foo.cc can declare (see +// file/base/file.h for the REQUIRE_FILE_MODULE definition): +// +// REQUIRE_FILE_MODULE(localfile); +// +// Similarly to other uses, DECLARE_FILE_INITIALIZER(localfile) +// should be #include-d for the above to compile. +// The above will guarantee that the localfile module will be linked into +// an application which foo.cc is linked into. Specifically, a link +// error will occur if the localfile module is not linked in. The +// preferred usage of REQUIRE_*_MODULE is for the module writer to +// provide an external .h which contains the REQUIRE_* macro. In the +// above example, the localfile module writer would provide localfile.h: +// +// #ifndef FILE_LOCALFILE_H_ +// #define FILE_LOCALFILE_H_ +// +// #include "file/base/file.h" +// +// DECLARE_FILE_INITIALIZER(localfile); +// REQUIRE_FILE_MODULE(localfile); +// +// #endif // FILE_LOCALFILE_H_ +// +// Now a user of localfile can declare their dependence on it by +// #including "localfile.h". + +//------------------------------------------------------------------------ + +// The following code is mostly ugly details about how the +// initialization is implemented, and can be safely ignored +// by users of the initialization facility. + +#include <string> + +#include "base/basictypes.h" + +// A static instance of 'GoogleInitializer' is declared for every +// piece of initialization code. The constructor registers the +// code in the initialization table. This class is thread-safe. +class GoogleInitializer { + public: + typedef void (*Initializer)(); + + // Register the specified initialization "function" as the + // initialization code for "name". The "type" parameter controls + // which initializer set this initializer will added to. Note that + // an initializer might end up being run from a different set if it + // is required using the REQUIRE_GOOGLE_INITIALIZED macro. Normally + // the type parameter is "module". Its existence allows the + // specification of other "initializer sets." See file/base/file.h + // and File::Init() for an example of such a set. It's unlikely this + // additional functionality will be used very often. + GoogleInitializer(const char* type, const char* name, Initializer function); + + // Invoke all registered initializers that have not yet been + // executed. The "type" parameter specifies which set of + // initializers to run. The initializers are invoked in + // lexicographically increasing order by name, except as necessary + // to satisfy dependencies. This routine is invoked by InitGoogle(), + // so application code should not call it except in special + // circumstances. + static void RunInitializers(const char* type); + + // If this initialization has not yet been executed, runs it + // right after running all the initializers registered to come before it, + // these initializers are invoked in lexicographically increasing order + // by name, except as necessary to satisfy dependencies. + // It is an error to call this method if the corresponding + // initializer method is currently active (i.e., we do not + // allow cycles in the requirement graph). + void Require(); + + // Helper data-holder struct that is passed into + // DependencyRegisterer's c-tor below. + struct Dependency { + Dependency(const char* n, GoogleInitializer* i) : name(n), initializer(i) {} + const char* const name; + GoogleInitializer* const initializer; + }; + + // A static instance of 'DependencyRegisterer' is declared for every + // piece of initializer ordering definition. The constructor registers the + // ordering relation in the initialization table. This class is thread-safe. + struct DependencyRegisterer { + // Ask to run initializer specified by 'dependency' + // before the 'initializer' with 'name'. + // Both initializers are supposed to be of type 'type'. + DependencyRegisterer(const char* type, + const char* name, + GoogleInitializer* initializer, + const Dependency& dependency); + private: + void SharedConstructorCode(const char* type, + const char* name, + GoogleInitializer* initializer, + const Dependency& dependency); + + DISALLOW_EVIL_CONSTRUCTORS(DependencyRegisterer); + }; + + // Side note: If we happen to decide that connecting all initializers into an + // explicit DAG with one/few sink node(s) that depend on everything else + // is important (to explicitly specify in code all the + // required initializers of a binary) we can provide something like + // static bool DoneAllInitializers(const char *type); + // to check that all registered initializers have been executed. + // Going this route does not seem worth it though: + // it's equivalent to mandating creation of a third complete + // module dependency DAG, the first two being via #include-s and BUILD + // dependencies. + + // Helper structs in .cc; public to declare file-level globals. + struct InitializerData; + struct TypeData; + + private: + void SharedConstructorCode(const char* type, + const char* name, + Initializer function); + + const string type_; // Initializer type + const string name_; // Initializer name + Initializer function_; // The actual initializer + bool done_; // Finished initializing? + bool is_active_; // Is currently running + + // Implementation helper for Require() and RunInitializers: + // Runs initializer *this and all its dependencies + // if that has not happened yet. + // Assumes table_lock is reader-held and TypeData::lock for type_ is held. + void RunIfNecessary_Locked(); + + // Helper to initialize/create and return data for a given initializer type. + static TypeData* InitializerTypeData(const char* type); + + DISALLOW_EVIL_CONSTRUCTORS(GoogleInitializer); +}; + +//------------------------------------------------------------------------ + +// Implementation Internals (most users should ignore) +// +// The *_GOOGLE_* macros are used to make separate initializer +// sets. They should not be used directly by application code, but are +// useful to library writers who want to create a new registration +// mechanism. (See google2file.h and the *_FILE_* macros for an +// example). + +// TODO(maxim): When DECLARE_GOOGLE_INITIALIZER is not used in +// REQUIRE_GOOGLE_INITIALIZED and REQUIRE_GOOGLE_MODULE +// put google_initializer_##type##_##name (and google_init_##type##_##name) +// into a gI##type namespace to force our users to use +// DECLARE_GOOGLE_INITIALIZER not reimplement it +// to manually declare an initializer. + +#define DECLARE_GOOGLE_INITIALIZER(type, name) \ + extern GoogleInitializer google_initializer_##type##_##name + +#define REGISTER_GOOGLE_INITIALIZER(type, name, body) \ + static void google_init_##type##_##name() { body; } \ + GoogleInitializer google_initializer_##type##_##name( \ + #type, #name, google_init_##type##_##name) + +// Require initializer name1 of 'type' to run before initializer +// initializer name2 of same 'type' (i.e. in the order they are written out). +// "Sequence" only means ordering, not direct executions sequence +// without any other initializer executed in between. +// Initializers for both modules must be declared +// with DECLARE_GOOGLE_INITIALIZER at this point. +#define REGISTER_GOOGLE_INITIALIZER_SEQUENCE(type, name1, name2) \ + namespace { \ + static GoogleInitializer::DependencyRegisterer \ + google_initializer_dependency_##type##_##name1##_##name2( \ + #type, #name2, &google_initializer_##type##_##name2, \ + GoogleInitializer::Dependency( \ + #name1, &google_initializer_##type##_##name1)); \ + } +// Require initializers name1, name2, name3 of 'type' to run in the above order. +// Added to support this frequent use case more conveniently. +#define REGISTER_GOOGLE_INITIALIZER_SEQUENCE_3(type, name1, name2, name3) \ + REGISTER_GOOGLE_INITIALIZER_SEQUENCE(type, name1, name2); \ + REGISTER_GOOGLE_INITIALIZER_SEQUENCE(type, name2, name3) + +// Calling REQUIRE_GOOGLE_INITIALIZED(type, foo) means to make sure intializer +// for foo and everything it depends on have executed, and as such +// it can be used to e.g. pre-execute subsets of initializers +// e.g. before everything is executed via RUN_GOGLE_INITIALIZERS(type). +// The initializer must be declared with DECLARE_GOOGLE_INITIALIZER(type, name). +// TODO : remove DECLARE_GOOGLE_INITIALIZER here +// when all old code makes use of DECLARE_GOOGLE_INITIALIZER. +#define REQUIRE_GOOGLE_INITIALIZED(type, name) \ + do { \ + DECLARE_GOOGLE_INITIALIZER(type, name); \ + google_initializer_##type##_##name.Require(); \ + } while (0) + +#define RUN_GOOGLE_INITIALIZERS(type) \ + do { \ + GoogleInitializer::RunInitializers(#type); \ + } while (0) + +// We force the dependant module to be loaded by taking the +// address of an object inside the dependency +// (created by REGISTER_GOOGLE_INITIALIZER). The rest +// is required to avoid warnings about unused variables and +// make sure gcc doesn't optimize it out of existence. +// The initializer must be declared with DECLARE_GOOGLE_INITIALIZER(type, name). +// TODO : remove DECLARE_GOOGLE_INITIALIZER here +// when all old code makes use of DECLARE_GOOGLE_INITIALIZER. +#define REQUIRE_GOOGLE_MODULE(type, name) \ + DECLARE_GOOGLE_INITIALIZER(type, name); \ + static struct GoogleModuleRef_##name { \ + GoogleModuleRef_##name(GoogleInitializer* r) : ref(r) {} \ + GoogleInitializer* ref; \ + } google_module_ref_##name(&google_initializer_##type##_##name) + + +// External Interface (most users should use these macros) + +#define DECLARE_MODULE_INITIALIZER(name) \ + DECLARE_GOOGLE_INITIALIZER(module, name) + +#define REGISTER_MODULE_INITIALIZER(name, body) \ + REGISTER_GOOGLE_INITIALIZER(module, name, body) + +#define REGISTER_MODULE_INITIALIZER_SEQUENCE(name1, name2) \ + REGISTER_GOOGLE_INITIALIZER_SEQUENCE(module, name1, name2) + +#define REGISTER_MODULE_INITIALIZER_SEQUENCE_3(name1, name2, name3) \ + REGISTER_GOOGLE_INITIALIZER_SEQUENCE_3(module, name1, name2, name3) + +#define REQUIRE_MODULE_INITIALIZED(name) \ + REQUIRE_GOOGLE_INITIALIZED(module, name) + +#define RUN_MODULE_INITIALIZERS() \ + RUN_GOOGLE_INITIALIZERS(module) + +// TODO : maybe rename this as REQUIRE_MODULE_LINKED +#define REQUIRE_MODULE(name) \ + REQUIRE_GOOGLE_MODULE(module, name) + +//------------------------------------------------------------------------ + +#endif // BASE_GOOGLEINIT_H_ |