| #include "caffe2/core/init.h" | |
| #include "caffe2/core/operator.h" // for StaticLinkingProtector | |
| #include "caffe2/core/scope_guard.h" | |
| #include <iomanip> | |
| #include <mutex> | |
| C10_DEFINE_bool( | |
| caffe2_version, | |
| false, | |
| "Print Caffe2 version and build options on startup"); | |
| namespace caffe2 { | |
| namespace internal { | |
| // Keep track of stages of initialization to differentiate between | |
| // (a) Re-entrant calls to GlobalInit (e.g. caller registers a Caffe2 init | |
| // function which might in turn indirectly invoke GlobalInit). | |
| // (b) Successive calls to GlobalInit, which are handled as documented in | |
| // init.h. | |
| // Note that this is NOT attempting to address thread-safety, see comments | |
| // in init.h. | |
| enum class State { | |
| Uninitialized, | |
| Initializing, | |
| Initialized, | |
| }; | |
| Caffe2InitializeRegistry* Caffe2InitializeRegistry::Registry() { | |
| static Caffe2InitializeRegistry gRegistry; | |
| return &gRegistry; | |
| } | |
| State& GlobalInitState() { | |
| static State state = State::Uninitialized; | |
| return state; | |
| } | |
| } // namespace internal | |
| bool GlobalInitAlreadyRun() { | |
| return internal::GlobalInitState() == internal::State::Initialized; | |
| } | |
| bool GlobalInit(int* pargc, char*** pargv) { | |
| C10_LOG_API_USAGE_ONCE("caffe2.global_init"); | |
| static std::recursive_mutex init_mutex; | |
| std::lock_guard<std::recursive_mutex> guard(init_mutex); | |
| internal::State& init_state = internal::GlobalInitState(); | |
| static StaticLinkingProtector g_protector; | |
| bool success = true; | |
| // NOTE: if init_state == internal::State::Initializing at this point, do | |
| // nothing because that indicates a re-entrant call | |
| if (init_state == internal::State::Initialized) { | |
| VLOG(1) << "GlobalInit has already been called: re-parsing gflags only."; | |
| // Reparse command line flags | |
| success &= c10::ParseCommandLineFlags(pargc, pargv); | |
| UpdateLoggingLevelsFromFlags(); | |
| } else if (init_state == internal::State::Uninitialized) { | |
| init_state = internal::State::Initializing; | |
| auto init_state_guard = MakeGuard([&] { | |
| // If an exception is thrown, go back to Uninitialized state | |
| if (init_state == internal::State::Initializing) { | |
| init_state = internal::State::Uninitialized; | |
| } | |
| }); | |
| success &= internal::Caffe2InitializeRegistry::Registry() | |
| ->RunRegisteredEarlyInitFunctions(pargc, pargv); | |
| CAFFE_ENFORCE( | |
| success, "Failed to run some early init functions for caffe2."); | |
| success &= c10::ParseCommandLineFlags(pargc, pargv); | |
| success &= InitCaffeLogging(pargc, *pargv); | |
| // Print out the current build version. Using cerr as LOG(INFO) might be off | |
| if (FLAGS_caffe2_version) { | |
| std::cerr << "Caffe2 build configuration: " << std::endl; | |
| for (const auto& it : GetBuildOptions()) { | |
| std::cerr << " " << std::setw(25) << std::left << it.first << " : " | |
| << it.second << std::endl; | |
| } | |
| } | |
| // All other initialization functions. | |
| success &= internal::Caffe2InitializeRegistry::Registry() | |
| ->RunRegisteredInitFunctions(pargc, pargv); | |
| init_state = | |
| success ? internal::State::Initialized : internal::State::Uninitialized; | |
| } | |
| CAFFE_ENFORCE(success, "Failed to run some init functions for caffe2."); | |
| // TODO: if we fail GlobalInit(), should we continue? | |
| return success; | |
| } | |
| bool GlobalInit() { | |
| // This is a version of the GlobalInit where no argument is passed in. | |
| // On mobile devices, use this global init, since we cannot pass the | |
| // command line options to caffe2, no arguments are passed. | |
| int mobile_argc = 1; | |
| static char caffe2_name[] = "caffe2"; | |
| char* mobile_name = &caffe2_name[0]; | |
| char** mobile_argv = &mobile_name; | |
| return ::caffe2::GlobalInit(&mobile_argc, &mobile_argv); | |
| } | |
| bool unsafeRunCaffe2InitFunction(const char* name, int* pargc, char*** pargv) { | |
| return internal::Caffe2InitializeRegistry::Registry()->RunNamedFunction( | |
| name, pargc, pargv); | |
| } | |
| } // namespace caffe2 |