1 // fst-register.h 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // 16 // \file 17 // Classes for registering derived Fsts for generic reading 18 // 19 20 #ifndef FST_LIB_REGISTER_H__ 21 #define FST_LIB_REGISTER_H__ 22 23 #include <map> 24 25 #include <dlfcn.h> 26 #include <pthread.h> 27 28 #include "fst/lib/compat.h" 29 30 extern "C" { 31 typedef void (*FstInitFunc)(); 32 } 33 34 namespace fst { 35 36 template <class A> class Fst; 37 struct FstReadOptions; 38 39 // This class holds the mapping from Fst name string to its reader 40 // and converter. 41 template <class A> 42 class FstRegister { 43 public: 44 typedef Fst<A> *(*Reader)(istream &strm, const FstReadOptions &opts); 45 typedef Fst<A> *(*Converter)(const Fst<A> &fst); 46 47 struct Entry { 48 Reader reader; 49 Converter converter; 50 Entry() : reader(0), converter(0) {} 51 }; 52 53 static FstRegister<A> *GetRegister() { 54 pthread_once(®ister_init_, &FstRegister<A>::Init); 55 return register_; 56 } 57 58 Reader GetReader(const string &type) const { 59 return GetEntry(type).reader; 60 } 61 62 Converter GetConverter(const string &type) const { 63 return GetEntry(type).converter; 64 } 65 66 void SetEntry(const string &type, const Entry &entry) { 67 MutexLock l(register_lock_); 68 fst_table_.insert(make_pair(type, entry)); 69 } 70 71 private: 72 static void Init() { 73 register_lock_ = new Mutex; 74 register_ = new FstRegister<A>; 75 } 76 77 Entry LookupEntry(const string &type) const { 78 MutexLock l(register_lock_); 79 typename map<string, Entry>::const_iterator it = fst_table_.find(type); 80 if (it != fst_table_.end()) 81 return it->second; 82 else 83 return Entry(); 84 } 85 86 Entry GetEntry(const string &type) const { 87 #ifdef FST_DL 88 Entry entry = LookupEntry(type); 89 if (entry.reader) 90 return entry; 91 string so_file = type + "-fst.so"; 92 void *handle = dlopen(so_file.c_str(), RTLD_LAZY); 93 if (handle == 0) { 94 LOG(ERROR) << "FstRegister::GetEntry: " << dlerror(); 95 return entry; 96 } 97 string init_name = type + "_fst_init"; 98 FstInitFunc init_func = 99 bit_cast<FstInitFunc>(dlsym(handle, init_name.c_str())); 100 if (init_func == 0) { 101 LOG(ERROR) << "FstRegister::GetEntry: " << dlerror(); 102 return entry; 103 } 104 (*init_func)(); 105 #endif // FST_DL 106 return LookupEntry(type); 107 } 108 109 static pthread_once_t register_init_; // ensures only called once 110 static Mutex* register_lock_; // multithreading lock 111 static FstRegister<A> *register_; 112 113 map<string, Entry> fst_table_; 114 }; 115 116 template <class A> 117 pthread_once_t FstRegister<A>::register_init_ = PTHREAD_ONCE_INIT; 118 119 template <class A> 120 Mutex *FstRegister<A>::register_lock_ = 0; 121 122 template <class A> 123 FstRegister<A> *FstRegister<A>::register_ = 0; 124 125 // This class registers an Fst type for generic reading and creating. 126 // The Fst type must have a default constructor and a copy constructor 127 // from 'Fst<Arc>' for this to work. 128 template <class F> 129 class FstRegisterer { 130 public: 131 typedef typename F::Arc Arc; 132 typedef typename FstRegister<Arc>::Entry Entry; 133 typedef typename FstRegister<Arc>::Reader Reader; 134 135 FstRegisterer() { 136 F fst; 137 F *(*reader)(istream &strm, 138 const FstReadOptions &opts) = &F::Read; 139 Entry entry; 140 entry.reader = reinterpret_cast<Reader>(reader); 141 entry.converter = &FstRegisterer<F>::Convert; 142 FstRegister<Arc> *registr = FstRegister<Arc>::GetRegister(); 143 registr->SetEntry(fst.Type(), entry); 144 } 145 146 private: 147 static Fst<Arc> *Convert(const Fst<Arc> &fst) { return new F(fst); } 148 }; 149 150 151 // Convenience macro to generate static FstRegisterer instance. 152 #define REGISTER_FST(F, A) \ 153 static fst::FstRegisterer< F<A> > F ## _ ## A ## _registerer 154 155 156 // Converts an fst to type 'type'. 157 template <class A> 158 Fst<A> *Convert(const Fst<A> &fst, const string &ftype) { 159 FstRegister<A> *registr = FstRegister<A>::GetRegister(); 160 const typename FstRegister<A>::Converter 161 converter = registr->GetConverter(ftype); 162 if (!converter) { 163 string atype = A::Type(); 164 LOG(ERROR) << "Fst::Convert: Unknown FST type \"" << ftype 165 << "\" (arc type = \"" << atype << "\")"; 166 return 0; 167 } 168 return converter(fst); 169 } 170 171 } // namespace fst; 172 173 #endif // FST_LIB_REGISTER_H__ 174