fix a race in type registration

Summary:
Here's what's happening:
C++ only guarantees that static initialization is thread safe there: https://fburl.com/40wdmf1q
So TypeNameRegisterer<bool> can not be called concurrently with TypeNameRegisterer<bool> from another invocation

But there's no guarantees about different template specializations as
they declare separate variables. Thus TypeNameRegisterer<int> might
race with TypeNameRegisterer<bool>. And TypeNameRegisterer accesses
the global variable here: https://fburl.com/gv2mhi08

Thanks dzhulgakov for the investigation!

Reviewed By: Yangqing

Differential Revision: D5882913

fbshipit-source-id: 4db1080b11e6351ce8136373e2dfc52980642fbb
diff --git a/caffe2/core/typeid.cc b/caffe2/core/typeid.cc
index bc29f3f..896fd63 100644
--- a/caffe2/core/typeid.cc
+++ b/caffe2/core/typeid.cc
@@ -16,6 +16,11 @@
   return g_registered_type_names;
 }
 
+std::mutex& gCaffe2TypeRegistrationMutex() {
+  static std::mutex g_caffe2_type_registration_mutex;
+  return g_caffe2_type_registration_mutex;
+}
+
 #if defined(_MSC_VER)
 // Windows does not have cxxabi.h, so we will simply return the original.
 string Demangle(const char* name) {
diff --git a/caffe2/core/typeid.h b/caffe2/core/typeid.h
index 1cede63..ee68dd1 100644
--- a/caffe2/core/typeid.h
+++ b/caffe2/core/typeid.h
@@ -3,9 +3,9 @@
 
 #include <cassert>
 #include <cstdlib>
-
 #include <iostream>
 #include <map>
+#include <mutex>
 #include <type_traits>
 #ifdef __GXX_RTTI
 #include <set>
@@ -31,9 +31,12 @@
 // type before its what() content.
 string GetExceptionString(const std::exception& e);
 
+std::mutex& gCaffe2TypeRegistrationMutex();
+
 template <typename T>
 struct TypeNameRegisterer {
   explicit TypeNameRegisterer(CaffeTypeId id) {
+    std::lock_guard<std::mutex> guard(gCaffe2TypeRegistrationMutex());
 #ifdef __GXX_RTTI
     string name = Demangle(typeid(T).name());
     gTypeNames()[id] = name;