Caffe2 - C++ API
A deep learning, cross platform ML framework
module.cc
1 #include "caffe2/core/logging.h"
2 #include "caffe2/core/module.h"
3 
4 #ifndef _MSC_VER
5 #include <dlfcn.h>
6 #endif
7 
8 namespace caffe2 {
9 
10 static std::mutex& gModuleChangeMutex() {
11  static std::mutex m_;
12  return m_;
13 }
14 
15 static CaffeMap<string, const ModuleSchema*>& MutableCurrentModules() {
16  static CaffeMap<string, const ModuleSchema*> module_schema_map_;
17  return module_schema_map_;
18 }
19 
20 // Note(jiayq): I am not sure whether the module handles are going to be used
21 // as C2 uses modules via registration, but let's keep the handles at least.
22 static CaffeMap<string, void*> CurrentModuleHandles() {
23  static CaffeMap<string, void*> module_handle_map_;
24  return module_handle_map_;
25 }
26 
27 const CaffeMap<string, const ModuleSchema*>& CurrentModules() {
28  return MutableCurrentModules();
29 }
30 
31 ModuleSchema::ModuleSchema(const char* name, const char* description)
32  : name_(name), description_(description) {
33  std::lock_guard<std::mutex> guard(gModuleChangeMutex());
34  MutableCurrentModules().emplace(name, this);
35 }
36 
37 bool HasModule(const string& name) {
38  auto& modules = CurrentModules();
39  return (modules.find(name) != modules.end());
40 }
41 
42 #ifdef _MSC_VER
43 
44 void LoadModule(const string& name, const string& filename) {
45  CAFFE_ENFORCE(!HasModule(name),
46  "On Windows, LoadModule is currently not supported yet and you should "
47  "use static linking for any module that you intend to use.");
48 }
49 
50 #else
51 
52 void LoadModule(const string& name, const string& filename) {
53  CAFFE_ENFORCE(
54  name.size() > 0 || filename.size() > 0,
55  "You must provide at least one of name and filename.");
56  if (name.size() && HasModule(name)) {
57  VLOG(1) << "Module " << name << " already present. Skip loading.";
58  return;
59  }
60  void* handle = nullptr;
61  if (filename.size()) {
62  handle = dlopen(
63  filename.c_str(), RTLD_NOW | RTLD_GLOBAL);
64  CAFFE_ENFORCE(handle != nullptr,
65  "Cannot load module ",
66  name,
67  " (with given filename ",
68  filename,
69  "), are you sure it is correct?");
70  } else {
71  string inferred_name = string("lib") + name + ".so";
72  handle = dlopen(
73  inferred_name.c_str(), RTLD_NOW | RTLD_GLOBAL);
74 #ifdef __APPLE__
75  // For apple, we will also try the dylib extension.
76  if (!handle) {
77  string inferred_name = string("lib") + name + ".dylib";
78  handle = dlopen(
79  inferred_name.c_str(), RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
80  }
81 #endif
82  CAFFE_ENFORCE(handle != nullptr,
83  "Cannot load module ",
84  name,
85  " (with inferred filename ",
86  inferred_name,
87  "), are you sure it is in the dynamic linker search path?");
88  }
89  // After the module is loaded, we should check if it actually has the
90  // intended module name. If not, it might be that the module file name
91  // and the module name are inconsistent.
92  if (name.size()) {
93  string module_name_check = "gCaffe2ModuleSanityCheck" + name;
94  CAFFE_ENFORCE(dlsym(handle, module_name_check.c_str()),
95  "The loaded module ",
96  name,
97  " did not pass the module name sanity check. Is it built with the "
98  "right configs? Make sure the file name and the CAFFE2_MODULE name "
99  "are consistent.");
100  // After it passes the dlopen and dlsym check, we should add it to the
101  // current handles.
102  std::lock_guard<std::mutex> guard(gModuleChangeMutex());
103  CurrentModuleHandles()[name] = handle;
104  } else {
105  // If not, we issue a warning that one is recommended to use explicit
106  // module name.
107  LOG(WARNING)
108  << "Module file " << filename
109  << " was loaded without a proper module name. It is recommended "
110  "that one load a model with an explicit module name in addition "
111  "to the filename.";
112  // As a contingency, we will store the current module handle with the
113  // filename.
114  std::lock_guard<std::mutex> guard(gModuleChangeMutex());
115  CurrentModuleHandles()[filename] = handle;
116  }
117 }
118 
119 #endif // _MSC_VER
120 
121 } // namespace caffe2
122 
bool HasModule(const string &name)
Checks whether a module is already present in the current binary.
Definition: module.cc:37
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
Definition: blob.h:13
void LoadModule(const string &name, const string &filename)
Load a module.
Definition: module.cc:52
const CaffeMap< string, const ModuleSchema * > & CurrentModules()
Current Modules present in the Caffe2 runtime.
Definition: module.cc:27