FST  openfst-1.7.2
OpenFst Library
generic-register.h
Go to the documentation of this file.
1 // See www.openfst.org for extensive documentation on this weighted
2 // finite-state transducer library.
3 
4 #ifndef FST_GENERIC_REGISTER_H_
5 #define FST_GENERIC_REGISTER_H_
6 
7 #include <fst/compat.h>
8 #ifndef FST_NO_DYNAMIC_LINKING
9 #include <dlfcn.h>
10 #endif
11 #include <map>
12 #include <string>
13 
14 #include <fst/types.h>
15 #include <fst/log.h>
16 
17 // Generic class representing a globally-stored correspondence between
18 // objects of KeyType and EntryType.
19 //
20 // KeyType must:
21 //
22 // * be such as can be stored as a key in a std::map<>.
23 // * be concatenable with a const char* with the + operator
24 // (or you must subclass and redefine LoadEntryFromSharedObject)
25 //
26 // EntryType must be default constructible.
27 //
28 // The third template parameter should be the type of a subclass of this class
29 // (think CRTP). This is to allow GetRegister() to instantiate and return an
30 // object of the appropriate type.
31 
32 namespace fst {
33 
34 template <class KeyType, class EntryType, class RegisterType>
36  public:
37  using Key = KeyType;
38  using Entry = EntryType;
39 
40  static RegisterType *GetRegister() {
41  static auto reg = new RegisterType;
42  return reg;
43  }
44 
45  void SetEntry(const KeyType &key, const EntryType &entry) {
46  MutexLock l(&register_lock_);
47  register_table_.insert(std::make_pair(key, entry));
48  }
49 
50  EntryType GetEntry(const KeyType &key) const {
51  const auto *entry = LookupEntry(key);
52  if (entry) {
53  return *entry;
54  } else {
55  return LoadEntryFromSharedObject(key);
56  }
57  }
58 
59  virtual ~GenericRegister() {}
60 
61  protected:
62  // Override this if you want to be able to load missing definitions from
63  // shared object files.
64  virtual EntryType LoadEntryFromSharedObject(const KeyType &key) const {
65 #ifdef FST_NO_DYNAMIC_LINKING
66  return EntryType();
67 #else
68  const auto so_filename = ConvertKeyToSoFilename(key);
69  void *handle = dlopen(so_filename.c_str(), RTLD_LAZY);
70  if (handle == nullptr) {
71  LOG(ERROR) << "GenericRegister::GetEntry: " << dlerror();
72  return EntryType();
73  }
74 #ifdef RUN_MODULE_INITIALIZERS
75  RUN_MODULE_INITIALIZERS();
76 #endif
77  // We assume that the DSO constructs a static object in its global scope
78  // that does the registration. Thus we need only load it, not call any
79  // methods.
80  const auto *entry = this->LookupEntry(key);
81  if (entry == nullptr) {
82  LOG(ERROR) << "GenericRegister::GetEntry: "
83  << "lookup failed in shared object: " << so_filename;
84  return EntryType();
85  }
86  return *entry;
87 #endif // FST_NO_DYNAMIC_LINKING
88  }
89 
90  // Override this to define how to turn a key into an SO filename.
91  virtual string ConvertKeyToSoFilename(const KeyType &key) const = 0;
92 
93  virtual const EntryType *LookupEntry(const KeyType &key) const {
94  MutexLock l(&register_lock_);
95  const auto it = register_table_.find(key);
96  if (it != register_table_.end()) {
97  return &it->second;
98  } else {
99  return nullptr;
100  }
101  }
102 
103  private:
104  mutable Mutex register_lock_;
105  std::map<KeyType, EntryType> register_table_;
106 };
107 
108 // Generic register-er class capable of creating new register entries in the
109 // given RegisterType template parameter. This type must define types Key and
110 // Entry, and have appropriate static GetRegister() and instance SetEntry()
111 // functions. An easy way to accomplish this is to have RegisterType be the
112 // type of a subclass of GenericRegister.
113 template <class RegisterType>
115  public:
116  using Key = typename RegisterType::Key;
117  using Entry = typename RegisterType::Entry;
118 
120  RegisterType::GetRegister()->SetEntry(key, entry);
121  }
122 };
123 
124 } // namespace fst
125 
126 #endif // FST_GENERIC_REGISTER_H_
typename FstRegister< FST::Arc >::Key Key
virtual string ConvertKeyToSoFilename(const KeyType &key) const =0
GenericRegisterer(Key key, Entry entry)
#define LOG(type)
Definition: log.h:48
virtual EntryType LoadEntryFromSharedObject(const KeyType &key) const
static RegisterType * GetRegister()
void SetEntry(const KeyType &key, const EntryType &entry)
EntryType GetEntry(const KeyType &key) const
typename FstRegister< FST::Arc >::Entry Entry
virtual const EntryType * LookupEntry(const KeyType &key) const