xref: /aosp_15_r20/external/libtextclassifier/native/lang_id/common/registry.h (revision 993b0882672172b81d12fad7a7ac0c3e5c824a12)
1*993b0882SAndroid Build Coastguard Worker /*
2*993b0882SAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*993b0882SAndroid Build Coastguard Worker  *
4*993b0882SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*993b0882SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*993b0882SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*993b0882SAndroid Build Coastguard Worker  *
8*993b0882SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*993b0882SAndroid Build Coastguard Worker  *
10*993b0882SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*993b0882SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*993b0882SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*993b0882SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*993b0882SAndroid Build Coastguard Worker  * limitations under the License.
15*993b0882SAndroid Build Coastguard Worker  */
16*993b0882SAndroid Build Coastguard Worker 
17*993b0882SAndroid Build Coastguard Worker // Mechanism to instantiate classes by name.
18*993b0882SAndroid Build Coastguard Worker //
19*993b0882SAndroid Build Coastguard Worker // This mechanism is useful if the concrete classes to be instantiated are not
20*993b0882SAndroid Build Coastguard Worker // statically known (e.g., if their names are read from a dynamically-provided
21*993b0882SAndroid Build Coastguard Worker // config).
22*993b0882SAndroid Build Coastguard Worker //
23*993b0882SAndroid Build Coastguard Worker // In that case, the first step is to define the API implemented by the
24*993b0882SAndroid Build Coastguard Worker // instantiated classes.  E.g.,
25*993b0882SAndroid Build Coastguard Worker //
26*993b0882SAndroid Build Coastguard Worker //  // In a header file function.h:
27*993b0882SAndroid Build Coastguard Worker //
28*993b0882SAndroid Build Coastguard Worker //  // Abstract function that takes a double and returns a double.
29*993b0882SAndroid Build Coastguard Worker //  class Function : public RegisterableClass<Function> {
30*993b0882SAndroid Build Coastguard Worker //   public:
31*993b0882SAndroid Build Coastguard Worker //    virtual ~Function() {}
32*993b0882SAndroid Build Coastguard Worker //    virtual double Evaluate(double x) = 0;
33*993b0882SAndroid Build Coastguard Worker //  };
34*993b0882SAndroid Build Coastguard Worker //
35*993b0882SAndroid Build Coastguard Worker //  // Should be inside namespace libtextclassifier3::mobile.
36*993b0882SAndroid Build Coastguard Worker //  SAFTM_DECLARE_CLASS_REGISTRY_NAME(Function);
37*993b0882SAndroid Build Coastguard Worker //
38*993b0882SAndroid Build Coastguard Worker // Notice the inheritance from RegisterableClass<Function>.  RegisterableClass
39*993b0882SAndroid Build Coastguard Worker // is defined by this file (registry.h).  Under the hood, this inheritanace
40*993b0882SAndroid Build Coastguard Worker // defines a "registry" that maps names (zero-terminated arrays of chars) to
41*993b0882SAndroid Build Coastguard Worker // factory methods that create Functions.  You should give a human-readable name
42*993b0882SAndroid Build Coastguard Worker // to this registry.  To do that, use the following macro in a .cc file (it has
43*993b0882SAndroid Build Coastguard Worker // to be a .cc file, as it defines some static data):
44*993b0882SAndroid Build Coastguard Worker //
45*993b0882SAndroid Build Coastguard Worker //  // Inside function.cc
46*993b0882SAndroid Build Coastguard Worker //  // Should be inside namespace libtextclassifier3::mobile.
47*993b0882SAndroid Build Coastguard Worker //  SAFTM_DEFINE_CLASS_REGISTRY_NAME("function", Function);
48*993b0882SAndroid Build Coastguard Worker //
49*993b0882SAndroid Build Coastguard Worker // Now, let's define a few concrete Functions: e.g.,
50*993b0882SAndroid Build Coastguard Worker //
51*993b0882SAndroid Build Coastguard Worker //   class Cos : public Function {
52*993b0882SAndroid Build Coastguard Worker //    public:
53*993b0882SAndroid Build Coastguard Worker //     double Evaluate(double x) override { return cos(x); }
54*993b0882SAndroid Build Coastguard Worker //     SAFTM_DEFINE_REGISTRATION_METHOD("cos", Cos);
55*993b0882SAndroid Build Coastguard Worker //   };
56*993b0882SAndroid Build Coastguard Worker //
57*993b0882SAndroid Build Coastguard Worker //   class Exp : public Function {
58*993b0882SAndroid Build Coastguard Worker //    public:
59*993b0882SAndroid Build Coastguard Worker //     double Evaluate(double x) override { return exp(x); }
60*993b0882SAndroid Build Coastguard Worker //     SAFTM_DEFINE_REGISTRATION_METHOD("sin", Sin);
61*993b0882SAndroid Build Coastguard Worker //   };
62*993b0882SAndroid Build Coastguard Worker //
63*993b0882SAndroid Build Coastguard Worker // Each concrete Function implementation should have (in the public section) the
64*993b0882SAndroid Build Coastguard Worker // macro
65*993b0882SAndroid Build Coastguard Worker //
66*993b0882SAndroid Build Coastguard Worker //   SAFTM_DEFINE_REGISTRATION_METHOD("name", implementation_class);
67*993b0882SAndroid Build Coastguard Worker //
68*993b0882SAndroid Build Coastguard Worker // This defines a RegisterClass static method that, when invoked, associates
69*993b0882SAndroid Build Coastguard Worker // "name" with a factory method that creates instances of implementation_class.
70*993b0882SAndroid Build Coastguard Worker //
71*993b0882SAndroid Build Coastguard Worker // Before instantiating Functions by name, we need to tell our system which
72*993b0882SAndroid Build Coastguard Worker // Functions we may be interested in.  This is done by calling the
73*993b0882SAndroid Build Coastguard Worker // Foo::RegisterClass() for each relevant Foo implementation of Function.  It is
74*993b0882SAndroid Build Coastguard Worker // ok to call Foo::RegisterClass() multiple times (even in parallel): only the
75*993b0882SAndroid Build Coastguard Worker // first call will perform something, the others will return immediately.
76*993b0882SAndroid Build Coastguard Worker //
77*993b0882SAndroid Build Coastguard Worker //   Cos::RegisterClass();
78*993b0882SAndroid Build Coastguard Worker //   Exp::RegisterClass();
79*993b0882SAndroid Build Coastguard Worker //
80*993b0882SAndroid Build Coastguard Worker // Now, let's instantiate a Function based on its name.  This get a lot more
81*993b0882SAndroid Build Coastguard Worker // interesting if the Function name is not statically known (i.e.,
82*993b0882SAndroid Build Coastguard Worker // read from an input proto:
83*993b0882SAndroid Build Coastguard Worker //
84*993b0882SAndroid Build Coastguard Worker //   std::unique_ptr<Function> f(Function::Create("cos"));
85*993b0882SAndroid Build Coastguard Worker //   double result = f->Evaluate(arg);
86*993b0882SAndroid Build Coastguard Worker //
87*993b0882SAndroid Build Coastguard Worker // NOTE: the same binary can use this mechanism for different APIs.  E.g., one
88*993b0882SAndroid Build Coastguard Worker // can also have (in the binary with Function, Sin, Cos, etc):
89*993b0882SAndroid Build Coastguard Worker //
90*993b0882SAndroid Build Coastguard Worker // class IntFunction : public RegisterableClass<IntFunction> {
91*993b0882SAndroid Build Coastguard Worker //  public:
92*993b0882SAndroid Build Coastguard Worker //   virtual ~IntFunction() {}
93*993b0882SAndroid Build Coastguard Worker //   virtual int Evaluate(int k) = 0;
94*993b0882SAndroid Build Coastguard Worker // };
95*993b0882SAndroid Build Coastguard Worker //
96*993b0882SAndroid Build Coastguard Worker // SAFTM_DECLARE_CLASS_REGISTRY_NAME(IntFunction);
97*993b0882SAndroid Build Coastguard Worker //
98*993b0882SAndroid Build Coastguard Worker // SAFTM_DEFINE_CLASS_REGISTRY_NAME("int function", IntFunction);
99*993b0882SAndroid Build Coastguard Worker //
100*993b0882SAndroid Build Coastguard Worker // class Inc : public IntFunction {
101*993b0882SAndroid Build Coastguard Worker //  public:
102*993b0882SAndroid Build Coastguard Worker //   int Evaluate(int k) override { return k + 1; }
103*993b0882SAndroid Build Coastguard Worker //   SAFTM_DEFINE_REGISTRATION_METHOD("inc", Inc);
104*993b0882SAndroid Build Coastguard Worker // };
105*993b0882SAndroid Build Coastguard Worker //
106*993b0882SAndroid Build Coastguard Worker // RegisterableClass<Function> and RegisterableClass<IntFunction> define their
107*993b0882SAndroid Build Coastguard Worker // own registries: each maps string names to implementation of the corresponding
108*993b0882SAndroid Build Coastguard Worker // API.
109*993b0882SAndroid Build Coastguard Worker //
110*993b0882SAndroid Build Coastguard Worker // NOTE: the mechanism described above requires you to explicitly call
111*993b0882SAndroid Build Coastguard Worker // RegisterClass() for all relevant classes before instantiating them.  You can
112*993b0882SAndroid Build Coastguard Worker // do this in the main() function or in any other function that is guaranteed to
113*993b0882SAndroid Build Coastguard Worker // run before the code that instantiates those classes.  Alternatively, you can
114*993b0882SAndroid Build Coastguard Worker // use the macro SAFTM_STATIC_REGISTRATION to perform this registration in a
115*993b0882SAndroid Build Coastguard Worker // decentralized fashion.  Just use that macro in a .cc file, outside any
116*993b0882SAndroid Build Coastguard Worker // function / class, e.g.,
117*993b0882SAndroid Build Coastguard Worker //
118*993b0882SAndroid Build Coastguard Worker // SAFTM_STATIC_REGISTRATION(Cos);
119*993b0882SAndroid Build Coastguard Worker //
120*993b0882SAndroid Build Coastguard Worker // and make sure you link in all symbols from that .cc file; e.g., in bazel, use
121*993b0882SAndroid Build Coastguard Worker // alwayslink = 1 for the corresponding cc_library.  Still, please be aware that
122*993b0882SAndroid Build Coastguard Worker // using alwayslink = 1 limits the ability of the linker to perform dead code
123*993b0882SAndroid Build Coastguard Worker // elimination.
124*993b0882SAndroid Build Coastguard Worker 
125*993b0882SAndroid Build Coastguard Worker #ifndef NLP_SAFT_COMPONENTS_COMMON_MOBILE_REGISTRY_H_
126*993b0882SAndroid Build Coastguard Worker #define NLP_SAFT_COMPONENTS_COMMON_MOBILE_REGISTRY_H_
127*993b0882SAndroid Build Coastguard Worker 
128*993b0882SAndroid Build Coastguard Worker #include <stdlib.h>
129*993b0882SAndroid Build Coastguard Worker #include <string.h>
130*993b0882SAndroid Build Coastguard Worker 
131*993b0882SAndroid Build Coastguard Worker #include <string>
132*993b0882SAndroid Build Coastguard Worker #include <vector>
133*993b0882SAndroid Build Coastguard Worker 
134*993b0882SAndroid Build Coastguard Worker #include "lang_id/common/lite_base/logging.h"
135*993b0882SAndroid Build Coastguard Worker #include "lang_id/common/lite_base/macros.h"
136*993b0882SAndroid Build Coastguard Worker 
137*993b0882SAndroid Build Coastguard Worker namespace libtextclassifier3 {
138*993b0882SAndroid Build Coastguard Worker namespace mobile {
139*993b0882SAndroid Build Coastguard Worker 
140*993b0882SAndroid Build Coastguard Worker namespace internal {
141*993b0882SAndroid Build Coastguard Worker // Registry that associates keys (zero-terminated array of chars) with values.
142*993b0882SAndroid Build Coastguard Worker // Values are pointers to type T (the template parameter).  This is used to
143*993b0882SAndroid Build Coastguard Worker // store the association between component names and factory methods that
144*993b0882SAndroid Build Coastguard Worker // produce those components; the error messages are focused on that case.
145*993b0882SAndroid Build Coastguard Worker //
146*993b0882SAndroid Build Coastguard Worker // Internally, this registry uses a linked list of (key, value) pairs.  We do
147*993b0882SAndroid Build Coastguard Worker // not use an STL map, list, etc because we aim for small code size.
148*993b0882SAndroid Build Coastguard Worker template <class T>
149*993b0882SAndroid Build Coastguard Worker class ComponentRegistry {
150*993b0882SAndroid Build Coastguard Worker  public:
ComponentRegistry(const char * name)151*993b0882SAndroid Build Coastguard Worker   explicit ComponentRegistry(const char *name) : name_(name), head_(nullptr) {}
152*993b0882SAndroid Build Coastguard Worker 
153*993b0882SAndroid Build Coastguard Worker   // Adds a the (key, value) pair to this registry (if the key does not already
154*993b0882SAndroid Build Coastguard Worker   // exists in this registry) and returns true.  If the registry already has a
155*993b0882SAndroid Build Coastguard Worker   // mapping for key, returns false and does not modify the registry.  NOTE: the
156*993b0882SAndroid Build Coastguard Worker   // error (false) case happens even if the existing value for key is equal with
157*993b0882SAndroid Build Coastguard Worker   // the new one.
158*993b0882SAndroid Build Coastguard Worker   //
159*993b0882SAndroid Build Coastguard Worker   // This method does not take ownership of key, nor of value.
Add(const char * key,T * value)160*993b0882SAndroid Build Coastguard Worker   bool Add(const char *key, T *value) {
161*993b0882SAndroid Build Coastguard Worker     const Cell *old_cell = FindCell(key);
162*993b0882SAndroid Build Coastguard Worker     if (old_cell != nullptr) {
163*993b0882SAndroid Build Coastguard Worker       SAFTM_LOG(ERROR) << "Duplicate component: " << key;
164*993b0882SAndroid Build Coastguard Worker       return false;
165*993b0882SAndroid Build Coastguard Worker     }
166*993b0882SAndroid Build Coastguard Worker     Cell *new_cell = new Cell(key, value, head_);
167*993b0882SAndroid Build Coastguard Worker     head_ = new_cell;
168*993b0882SAndroid Build Coastguard Worker     return true;
169*993b0882SAndroid Build Coastguard Worker   }
170*993b0882SAndroid Build Coastguard Worker 
171*993b0882SAndroid Build Coastguard Worker   // Returns the value attached to a key in this registry.  Returns nullptr on
172*993b0882SAndroid Build Coastguard Worker   // error (e.g., unknown key).
Lookup(const char * key)173*993b0882SAndroid Build Coastguard Worker   T *Lookup(const char *key) const {
174*993b0882SAndroid Build Coastguard Worker     const Cell *cell = FindCell(key);
175*993b0882SAndroid Build Coastguard Worker     if (cell == nullptr) {
176*993b0882SAndroid Build Coastguard Worker       SAFTM_LOG(ERROR) << "Unknown " << name() << " component: " << key;
177*993b0882SAndroid Build Coastguard Worker     }
178*993b0882SAndroid Build Coastguard Worker     return (cell == nullptr) ? nullptr : cell->value();
179*993b0882SAndroid Build Coastguard Worker   }
180*993b0882SAndroid Build Coastguard Worker 
Lookup(const std::string & key)181*993b0882SAndroid Build Coastguard Worker   T *Lookup(const std::string &key) const { return Lookup(key.c_str()); }
182*993b0882SAndroid Build Coastguard Worker 
183*993b0882SAndroid Build Coastguard Worker   // Returns name of this ComponentRegistry.
name()184*993b0882SAndroid Build Coastguard Worker   const char *name() const { return name_; }
185*993b0882SAndroid Build Coastguard Worker 
186*993b0882SAndroid Build Coastguard Worker   // Fills *names with names of all components registered in this
187*993b0882SAndroid Build Coastguard Worker   // ComponentRegistry.  Previous content of *names is cleared out.
GetComponentNames(std::vector<std::string> * names)188*993b0882SAndroid Build Coastguard Worker   void GetComponentNames(std::vector<std::string> *names) {
189*993b0882SAndroid Build Coastguard Worker     names->clear();
190*993b0882SAndroid Build Coastguard Worker     for (const Cell *c = head_; c!= nullptr; c = c->next()) {
191*993b0882SAndroid Build Coastguard Worker       names->emplace_back(c->key());
192*993b0882SAndroid Build Coastguard Worker     }
193*993b0882SAndroid Build Coastguard Worker   }
194*993b0882SAndroid Build Coastguard Worker 
195*993b0882SAndroid Build Coastguard Worker  private:
196*993b0882SAndroid Build Coastguard Worker   // Cell for the singly-linked list underlying this ComponentRegistry.  Each
197*993b0882SAndroid Build Coastguard Worker   // cell contains a key, the value for that key, as well as a pointer to the
198*993b0882SAndroid Build Coastguard Worker   // next Cell from the list.
199*993b0882SAndroid Build Coastguard Worker   class Cell {
200*993b0882SAndroid Build Coastguard Worker    public:
201*993b0882SAndroid Build Coastguard Worker     // Constructs a new Cell.
Cell(const char * key,T * value,Cell * next)202*993b0882SAndroid Build Coastguard Worker     Cell(const char *key, T *value, Cell *next)
203*993b0882SAndroid Build Coastguard Worker         : key_(key), value_(value), next_(next) {}
204*993b0882SAndroid Build Coastguard Worker 
key()205*993b0882SAndroid Build Coastguard Worker     const char *key() const { return key_; }
value()206*993b0882SAndroid Build Coastguard Worker     T *value() const { return value_; }
next()207*993b0882SAndroid Build Coastguard Worker     Cell *next() const { return next_; }
208*993b0882SAndroid Build Coastguard Worker 
209*993b0882SAndroid Build Coastguard Worker    private:
210*993b0882SAndroid Build Coastguard Worker     const char *const key_;
211*993b0882SAndroid Build Coastguard Worker     T *const value_;
212*993b0882SAndroid Build Coastguard Worker     Cell *const next_;
213*993b0882SAndroid Build Coastguard Worker   };
214*993b0882SAndroid Build Coastguard Worker 
215*993b0882SAndroid Build Coastguard Worker   // Finds Cell for indicated key in the singly-linked list pointed to by head_.
216*993b0882SAndroid Build Coastguard Worker   // Returns pointer to that first Cell with that key, or nullptr if no such
217*993b0882SAndroid Build Coastguard Worker   // Cell (i.e., unknown key).
218*993b0882SAndroid Build Coastguard Worker   //
219*993b0882SAndroid Build Coastguard Worker   // Caller does NOT own the returned pointer.
FindCell(const char * key)220*993b0882SAndroid Build Coastguard Worker   const Cell *FindCell(const char *key) const {
221*993b0882SAndroid Build Coastguard Worker     const Cell *c = head_;
222*993b0882SAndroid Build Coastguard Worker     while (c != nullptr && strcmp(key, c->key()) != 0) {
223*993b0882SAndroid Build Coastguard Worker       c = c->next();
224*993b0882SAndroid Build Coastguard Worker     }
225*993b0882SAndroid Build Coastguard Worker     return c;
226*993b0882SAndroid Build Coastguard Worker   }
227*993b0882SAndroid Build Coastguard Worker 
228*993b0882SAndroid Build Coastguard Worker   // Human-readable description for this ComponentRegistry.  For debug purposes.
229*993b0882SAndroid Build Coastguard Worker   const char *const name_;
230*993b0882SAndroid Build Coastguard Worker 
231*993b0882SAndroid Build Coastguard Worker   // Pointer to the first Cell from the underlying list of (key, value) pairs.
232*993b0882SAndroid Build Coastguard Worker   Cell *head_;
233*993b0882SAndroid Build Coastguard Worker };
234*993b0882SAndroid Build Coastguard Worker }  // namespace internal
235*993b0882SAndroid Build Coastguard Worker 
236*993b0882SAndroid Build Coastguard Worker // Base class for registerable classes.
237*993b0882SAndroid Build Coastguard Worker template <class T>
238*993b0882SAndroid Build Coastguard Worker class RegisterableClass {
239*993b0882SAndroid Build Coastguard Worker  public:
240*993b0882SAndroid Build Coastguard Worker   // Factory function type.
241*993b0882SAndroid Build Coastguard Worker   typedef T *(Factory)();
242*993b0882SAndroid Build Coastguard Worker 
243*993b0882SAndroid Build Coastguard Worker   // Registry type.
244*993b0882SAndroid Build Coastguard Worker   typedef internal::ComponentRegistry<Factory> Registry;
245*993b0882SAndroid Build Coastguard Worker 
246*993b0882SAndroid Build Coastguard Worker   // Creates a new instance of T.  Returns pointer to new instance or nullptr in
247*993b0882SAndroid Build Coastguard Worker   // case of errors (e.g., unknown component).
248*993b0882SAndroid Build Coastguard Worker   //
249*993b0882SAndroid Build Coastguard Worker   // Passes ownership of the returned pointer to the caller.
Create(const std::string & name)250*993b0882SAndroid Build Coastguard Worker   static T *Create(const std::string &name) {  // NOLINT
251*993b0882SAndroid Build Coastguard Worker     auto *factory = registry()->Lookup(name);
252*993b0882SAndroid Build Coastguard Worker     if (factory == nullptr) {
253*993b0882SAndroid Build Coastguard Worker       SAFTM_LOG(ERROR) << "Unknown RegisterableClass " << name;
254*993b0882SAndroid Build Coastguard Worker       return nullptr;
255*993b0882SAndroid Build Coastguard Worker     }
256*993b0882SAndroid Build Coastguard Worker     return factory();
257*993b0882SAndroid Build Coastguard Worker   }
258*993b0882SAndroid Build Coastguard Worker 
259*993b0882SAndroid Build Coastguard Worker   // Returns registry for class.
registry()260*993b0882SAndroid Build Coastguard Worker   static Registry *registry() {
261*993b0882SAndroid Build Coastguard Worker     static Registry *registry_for_type_t = new Registry(kRegistryName);
262*993b0882SAndroid Build Coastguard Worker     return registry_for_type_t;
263*993b0882SAndroid Build Coastguard Worker   }
264*993b0882SAndroid Build Coastguard Worker 
265*993b0882SAndroid Build Coastguard Worker  protected:
266*993b0882SAndroid Build Coastguard Worker   // Factory method for subclass ComponentClass.  Used internally by the static
267*993b0882SAndroid Build Coastguard Worker   // method RegisterClass() defined by SAFTM_DEFINE_REGISTRATION_METHOD.
268*993b0882SAndroid Build Coastguard Worker   template <class ComponentClass>
_internal_component_factory()269*993b0882SAndroid Build Coastguard Worker   static T *_internal_component_factory() {
270*993b0882SAndroid Build Coastguard Worker     return new ComponentClass();
271*993b0882SAndroid Build Coastguard Worker   }
272*993b0882SAndroid Build Coastguard Worker 
273*993b0882SAndroid Build Coastguard Worker  private:
274*993b0882SAndroid Build Coastguard Worker   // Human-readable name for the registry for this class.
275*993b0882SAndroid Build Coastguard Worker   static const char kRegistryName[];
276*993b0882SAndroid Build Coastguard Worker };
277*993b0882SAndroid Build Coastguard Worker 
278*993b0882SAndroid Build Coastguard Worker // Defines the static method component_class::RegisterClass() that should be
279*993b0882SAndroid Build Coastguard Worker // called before trying to instantiate component_class by name.  Should be used
280*993b0882SAndroid Build Coastguard Worker // inside the public section of the declaration of component_class.  See
281*993b0882SAndroid Build Coastguard Worker // comments at the top-level of this file.
282*993b0882SAndroid Build Coastguard Worker #define SAFTM_DEFINE_REGISTRATION_METHOD(component_name, component_class) \
283*993b0882SAndroid Build Coastguard Worker   static void RegisterClass() {                                         \
284*993b0882SAndroid Build Coastguard Worker     static bool once = registry()->Add(                                 \
285*993b0882SAndroid Build Coastguard Worker         component_name, &_internal_component_factory<component_class>); \
286*993b0882SAndroid Build Coastguard Worker     if (!once) {                                                        \
287*993b0882SAndroid Build Coastguard Worker       SAFTM_LOG(ERROR) << "Problem registering " << component_name;     \
288*993b0882SAndroid Build Coastguard Worker     }                                                                   \
289*993b0882SAndroid Build Coastguard Worker     SAFTM_DCHECK(once);                                                 \
290*993b0882SAndroid Build Coastguard Worker   }
291*993b0882SAndroid Build Coastguard Worker 
292*993b0882SAndroid Build Coastguard Worker // Defines the human-readable name of the registry associated with base_class.
293*993b0882SAndroid Build Coastguard Worker #define SAFTM_DECLARE_CLASS_REGISTRY_NAME(base_class)                   \
294*993b0882SAndroid Build Coastguard Worker   template <>                                                           \
295*993b0882SAndroid Build Coastguard Worker   const char ::libtextclassifier3::mobile::RegisterableClass<base_class>::kRegistryName[]
296*993b0882SAndroid Build Coastguard Worker 
297*993b0882SAndroid Build Coastguard Worker // Defines the human-readable name of the registry associated with base_class.
298*993b0882SAndroid Build Coastguard Worker #define SAFTM_DEFINE_CLASS_REGISTRY_NAME(registry_name, base_class)     \
299*993b0882SAndroid Build Coastguard Worker   template <>                                                           \
300*993b0882SAndroid Build Coastguard Worker   const char                                                            \
301*993b0882SAndroid Build Coastguard Worker   ::libtextclassifier3::mobile::RegisterableClass<base_class>::kRegistryName[]    \
302*993b0882SAndroid Build Coastguard Worker       = registry_name
303*993b0882SAndroid Build Coastguard Worker 
304*993b0882SAndroid Build Coastguard Worker // Register component_name, by calling component_class::RegisterClass() on
305*993b0882SAndroid Build Coastguard Worker // program start-up, before main.  NOTE: this macro should be used in
306*993b0882SAndroid Build Coastguard Worker // conjunction with something like alwayslink = 1 from bazel.  That is
307*993b0882SAndroid Build Coastguard Worker // discouraged, as it prevents the linker from doing dead code elimination, so
308*993b0882SAndroid Build Coastguard Worker // please use this macro only in special cases.  Instead, if you care about code
309*993b0882SAndroid Build Coastguard Worker // size, then you should aim to explicitly call RegisterClass from your code
310*993b0882SAndroid Build Coastguard Worker // (e.g., from the main method, or from the constructor of the class that may
311*993b0882SAndroid Build Coastguard Worker // need those registered components).
312*993b0882SAndroid Build Coastguard Worker #define SAFTM_STATIC_REGISTRATION(component_class)                  \
313*993b0882SAndroid Build Coastguard Worker   static bool SAFTM_UNIQUE_ID(_kRegistrationDummy) = [] {           \
314*993b0882SAndroid Build Coastguard Worker     component_class::RegisterClass();                               \
315*993b0882SAndroid Build Coastguard Worker     return true;                                                    \
316*993b0882SAndroid Build Coastguard Worker   }()
317*993b0882SAndroid Build Coastguard Worker 
318*993b0882SAndroid Build Coastguard Worker }  // namespace mobile
319*993b0882SAndroid Build Coastguard Worker }  // namespace nlp_saft
320*993b0882SAndroid Build Coastguard Worker 
321*993b0882SAndroid Build Coastguard Worker #endif  // NLP_SAFT_COMPONENTS_COMMON_MOBILE_REGISTRY_H_
322