| #include "caffe2/core/init.h" |
| #include "caffe2/core/operator.h" // for StaticLinkingProtector |
| #include "caffe2/core/scope_guard.h" |
| |
| #include <iomanip> |
| #include <iostream> |
| #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; |
| // NOLINTNEXTLINE(modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays) |
| 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 |