1f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 2f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Licensed under the Apache License, Version 2.0 (the "License"); 3f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// you may not use this file except in compliance with the License. 4f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// You may obtain a copy of the License at 5f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 6f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// http://www.apache.org/licenses/LICENSE-2.0 7f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 8f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Unless required by applicable law or agreed to in writing, software 9f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// distributed under the License is distributed on an "AS IS" BASIS, 10f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// See the License for the specific language governing permissions and 12f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// limitations under the License. 13f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 14f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Copyright 2005-2010 Google, Inc. 15f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Author: jpr@google.com (Jake Ratkiewicz) 16f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 17f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#ifndef FST_LIB_GENERIC_REGISTER_H_ 18f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#define FST_LIB_GENERIC_REGISTER_H_ 19f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 20f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <map> 21f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <string> 22f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 23f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/compat.h> 24f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/types.h> 25f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 26f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Generic class representing a globally-stored correspondence between 27f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// objects of KeyType and EntryType. 28f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// KeyType must: 29f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// a) be such as can be stored as a key in a map<> 30f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// b) be concatenable with a const char* with the + operator 31f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// (or you must subclass and redefine LoadEntryFromSharedObject) 32f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// EntryType must be default constructible. 33f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 34f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// The third template parameter should be the type of a subclass of this class 35f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// (think CRTP). This is to allow GetRegister() to instantiate and return 36f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// an object of the appropriate type. 37f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 38f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonnamespace fst { 39f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 40f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class KeyType, class EntryType, class RegisterType> 41f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass GenericRegister { 42f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public: 43f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef KeyType Key; 44f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef EntryType Entry; 45f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 46f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson static RegisterType *GetRegister() { 47f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson FstOnceInit(®ister_init_, 48f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson &RegisterType::Init); 49f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 50f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return register_; 51f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 52f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 53f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void SetEntry(const KeyType &key, 54f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const EntryType &entry) { 55f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson MutexLock l(register_lock_); 56f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 57f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson register_table_.insert(make_pair(key, entry)); 58f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 59f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 60f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson EntryType GetEntry(const KeyType &key) const { 61f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const EntryType *entry = LookupEntry(key); 62f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (entry) { 63f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return *entry; 64f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } else { 65f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return LoadEntryFromSharedObject(key); 66f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 67f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 68f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 69f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson virtual ~GenericRegister() { } 70f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 71f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson protected: 72f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Override this if you want to be able to load missing definitions from 73f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // shared object files. 74f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson virtual EntryType LoadEntryFromSharedObject(const KeyType &key) const { 75f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson string so_filename = ConvertKeyToSoFilename(key); 76f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 77f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void *handle = dlopen(so_filename.c_str(), RTLD_LAZY); 78f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (handle == 0) { 79f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson LOG(ERROR) << "GenericRegister::GetEntry : " << dlerror(); 80f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return EntryType(); 81f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 82f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 83f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // We assume that the DSO constructs a static object in its global 84f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // scope that does the registration. Thus we need only load it, not 85f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // call any methods. 86f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const EntryType *entry = this->LookupEntry(key); 87f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (entry == 0) { 88f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson LOG(ERROR) << "GenericRegister::GetEntry : " 89f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson << "lookup failed in shared object: " << so_filename; 90f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return EntryType(); 91f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 92f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return *entry; 93f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 94f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 95f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Override this to define how to turn a key into an SO filename. 96f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson virtual string ConvertKeyToSoFilename(const KeyType& key) const = 0; 97f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 98f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson virtual const EntryType *LookupEntry( 99f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const KeyType &key) const { 100f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson MutexLock l(register_lock_); 101f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 102f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typename RegisterMapType::const_iterator it = register_table_.find(key); 103f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 104f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (it != register_table_.end()) { 105f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return &it->second; 106f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } else { 107f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return 0; 108f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 109f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 110f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 111f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private: 112f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef map<KeyType, EntryType> RegisterMapType; 113f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 114f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson static void Init() { 115f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson register_lock_ = new Mutex; 116f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson register_ = new RegisterType; 117f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 118f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 119f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson static FstOnceType register_init_; 120f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson static Mutex *register_lock_; 121f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson static RegisterType *register_; 122f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 123f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson RegisterMapType register_table_; 124f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}; 125f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 126f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class KeyType, class EntryType, class RegisterType> 127f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian HodsonFstOnceType GenericRegister<KeyType, EntryType, 128f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson RegisterType>::register_init_ = FST_ONCE_INIT; 129f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 130f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class KeyType, class EntryType, class RegisterType> 131f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian HodsonMutex *GenericRegister<KeyType, EntryType, RegisterType>::register_lock_ = 0; 132f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 133f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class KeyType, class EntryType, class RegisterType> 134f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian HodsonRegisterType *GenericRegister<KeyType, EntryType, RegisterType>::register_ = 0; 135f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 136f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 137f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// GENERIC REGISTRATION 138f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 139f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 140f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Generic register-er class capable of creating new register entries in the 141f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// given RegisterType template parameter. This type must define types Key 142f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// and Entry, and have appropriate static GetRegister() and instance 143f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// SetEntry() functions. An easy way to accomplish this is to have RegisterType 144f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// be the type of a subclass of GenericRegister. 145f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate<class RegisterType> 146f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass GenericRegisterer { 147f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public: 148f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename RegisterType::Key Key; 149f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename RegisterType::Entry Entry; 150f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 151f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson GenericRegisterer(Key key, Entry entry) { 152f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson RegisterType *reg = RegisterType::GetRegister(); 153f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson reg->SetEntry(key, entry); 154f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 155f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}; 156f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 157f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson} // namespace fst 158f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 159f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#endif // FST_LIB_GENERIC_REGISTER_H_ 160