Files
paddlepaddle--paddle/paddle/cinn/utils/registry.h
T
2026-07-13 12:40:42 +08:00

215 lines
6.3 KiB
C++

/**
* This file is copied from dmlc-core project, all the rights are resolved by
* original project. Following are the original header comment. Copyright (c)
* 2015 by Contributors
* @file registry.h
* \brief Registry utility that helps to build registry singletons.
*/
#pragma once
#include <map>
#include <string>
#include <vector>
/**
* \brief Registry class.
* Registry can be used to register global singletons.
* The most commonly use case are factory functions.
*
* @tparam EntryType Type of Registry entries,
* EntryType need to name a name field.
*/
template <typename EntryType>
class Registry {
public:
/** @return list of entries in the registry(excluding alias) */
inline const std::vector<const EntryType *> &List() { return const_list_; }
/** @return list all names registered in the registry, including alias */
inline std::vector<std::string> ListAllNames() {
std::vector<std::string> names;
for (auto p = fmap_.begin(); p != fmap_.end(); ++p) {
names.push_back(p->first);
}
return names;
}
/**
* \brief Find the entry with corresponding name.
* @param name name of the function
* @return the corresponding function, can be NULL
*/
inline const EntryType *Find(const std::string &name) {
typename std::map<std::string, EntryType *>::const_iterator p =
fmap_.find(name);
if (p != fmap_.end()) {
return p->second;
} else {
return nullptr;
}
}
/**
* \brief Add alias to the key_name
* @param key_name The original entry key
* @param alias The alias key.
*/
/* inline void AddAlias(const std::string &key_name, const std::string
&alias) { EntryType *e = fmap_.at(key_name); if (fmap_.count(alias)) {
CHECK_EQ(e, fmap_.at(alias)) << "Trying to register alias " << alias <<
" for key " << key_name << " but "
<< alias << " is already taken";
} else {
fmap_[alias] = e;
}
} */
/**
* \brief Internal function to register a name function under name.
* @param name name of the function
* @return ref to the registered entry, used to set properties
*/
inline EntryType &__REGISTER__(const std::string &name) {
std::lock_guard<std::mutex> guard(registering_mutex);
if (fmap_.count(name)) {
return *fmap_[name];
}
EntryType *e = new EntryType();
e->name = name;
fmap_[name] = e;
const_list_.push_back(e);
entry_list_.push_back(e);
return *e;
}
/**
* \brief Internal function to either register or get registered entry
* @param name name of the function
* @return ref to the registered entry, used to set properties
*/
inline EntryType &__REGISTER_OR_GET__(const std::string &name) {
// Here if we use VLOG, we will get Seg Fault. Todo: Add VLOG and fix this.
// @Haoze
if (!fmap_.count(name)) {
return __REGISTER__(name);
} else {
return *fmap_.at(name);
}
}
/**
* \brief get a singleton of the Registry.
* This function can be defined by CINN_REGISTRY_ENABLE.
* @return get a singleton
*/
static Registry *Global() {
static Registry<EntryType> inst;
return &inst;
}
Registry() = default;
~Registry() {
for (size_t i = 0; i < entry_list_.size(); ++i) {
delete entry_list_[i];
}
}
protected:
/** \brief list of entry types */
std::vector<EntryType *> entry_list_;
/** \brief list of entry types */
std::vector<const EntryType *> const_list_;
/** \brief map of name->function */
std::map<std::string, EntryType *> fmap_;
/** \brief lock guarding the registering*/
std::mutex registering_mutex;
/** \brief constructor */
/** \brief destructor */
};
/**
* \brief Common base class for function registry.
*
* \code
* // This example demonstrates how to use Registry to create a factory of
* trees. struct TreeFactory : public FunctionRegEntryBase<TreeFactory,
* std::function<Tree*()> > {
* };
*
* // in a independent cc file
* namespace cinn {
* CINN_REGISTRY_ENABLE(TreeFactory);
* }
* // register binary tree constructor into the registry.
* CINN_REGISTRY_REGISTER(TreeFactory, TreeFactory, BinaryTree)
* .describe("Constructor of BinaryTree")
* .set_body([]() { return new BinaryTree(); });
* \endcode
*
* @tparam EntryType The type of subclass that inherit the base.
* @tparam FunctionType The function type this registry is registered.
*/
template <typename EntryType, typename FunctionType>
class FunctionRegEntryBase {
public:
/** \brief name of the entry */
std::string name;
/** \brief description of the entry */
std::string description;
/** \brief additional arguments to the factory function */
// std::vector<ParamFieldInfo> arguments;
/** \brief Function body to create ProductType */
FunctionType body;
/** \brief Return type of the function */
std::string return_type;
/**
* \brief Set the function body.
* @param body Function body to set.
* @return reference to self.
*/
inline EntryType &set_body(FunctionType body) {
this->body = body;
return this->self();
}
/**
* \brief Describe the function.
* @param description The description of the factory function.
* @return reference to self.
*/
inline EntryType &describe(const std::string &description) {
this->description = description;
return this->self();
}
/**
* \brief Set the return type.
* @param type Return type of the function, could be Symbol or Symbol[]
* @return reference to self.
*/
inline EntryType &set_return_type(const std::string &type) {
return_type = type;
return this->self();
}
protected:
/**
* @return reference of self as derived type
*/
inline EntryType &self() { return *(static_cast<EntryType *>(this)); }
};
/**
* \brief Generic macro to register an EntryType
* There is a complete example in FactoryRegistryEntryBase.
*
* @param EntryType The type of registry entry.
* @param EntryTypeName The typename of EntryType, must do not contain namespace
* :: .
* @param Name The name to be registered.
* @sa FactoryRegistryEntryBase
*/
#define CINN_REGISTRY_REGISTER(EntryType, EntryTypeName, Name) \
static EntryType &__make_##EntryTypeName##_##Name##__ = \
::Registry<EntryType>::Global()->__REGISTER__(#Name)
#define CINN_STR_CONCAT_(__x, __y) __x##__y
#define CINN_STR_CONCAT(__x, __y) CINN_STR_CONCAT_(__x, __y)