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