/** * @brief A layer factory that allows one to register layers. * During runtime, registered layers could be called by passing a LayerParameter * protobuffer to the CreateLayer function: * * LayerRegistry::CreateLayer(param); * * There are two ways to register a layer. Assuming that we have a layer like: * * template * class MyAwesomeLayer : public Layer { * // your implementations * }; * * and its type is its C++ class name, but without the "Layer" at the end * ("MyAwesomeLayer" -> "MyAwesome"). * * If the layer is going to be created simply by its constructor, in your c++ * file, add the following line: * * REGISTER_LAYER_CLASS(MyAwesome); * * Or, if the layer is going to be created by another creator function, in the * format of: * * template * Layer GetMyAwesomeLayer(const LayerParameter& param) { * // your implementation * } * * (for example, when your layer has multiple backends, see GetConvolutionLayer * for a use case), then you can register the creator function instead, like * * REGISTER_LAYER_CREATOR(MyAwesome, GetMyAwesomeLayer) * * Note that each layer type should only be registered once. */ #ifndef CAFFE_LAYER_FACTORY_H_ #define CAFFE_LAYER_FACTORY_H_ #include #include #include "caffe/common.hpp" #include "caffe/proto/caffe.pb.h" namespace caffe { template class Layer; template class LayerRegistry { public: typedef shared_ptr > (*Creator)(const LayerParameter&); typedef std::map CreatorRegistry; static CreatorRegistry& Registry() { static CreatorRegistry* g_registry_ = new CreatorRegistry(); return *g_registry_; } // Adds a creator. static void AddCreator(const string& type, Creator creator) { CreatorRegistry& registry = Registry(); CHECK_EQ(registry.count(type), 0) << "Layer type " << type << " already registered."; registry[type] = creator; } // Get a layer using a LayerParameter. static shared_ptr > CreateLayer(const LayerParameter& param) { if (Caffe::root_solver()) { LOG(INFO) << "Creating layer " << param.name(); } const string& type = param.type(); CreatorRegistry& registry = Registry(); CHECK_EQ(registry.count(type), 1) << "Unknown layer type: " << type << " (known types: " << LayerTypeList() << ")"; return registry[type](param); } private: // Layer registry should never be instantiated - everything is done with its // static variables. LayerRegistry() {} static string LayerTypeList() { CreatorRegistry& registry = Registry(); string layer_types; for (typename CreatorRegistry::iterator iter = registry.begin(); iter != registry.end(); ++iter) { if (iter != registry.begin()) { layer_types += ", "; } layer_types += iter->first; } return layer_types; } }; template class LayerRegisterer { public: LayerRegisterer(const string& type, shared_ptr > (*creator)(const LayerParameter&)) { // LOG(INFO) << "Registering layer type: " << type; LayerRegistry::AddCreator(type, creator); } }; #define REGISTER_LAYER_CREATOR(type, creator) \ static LayerRegisterer g_creator_f_##type(#type, creator); \ static LayerRegisterer g_creator_d_##type(#type, creator) \ #define REGISTER_LAYER_CLASS(type) \ template \ shared_ptr > Creator_##type##Layer(const LayerParameter& param) \ { \ return shared_ptr >(new type##Layer(param)); \ } \ REGISTER_LAYER_CREATOR(type, Creator_##type##Layer) } // namespace caffe #endif // CAFFE_LAYER_FACTORY_H_