summaryrefslogtreecommitdiff
path: root/kaldi_io/src/tools/openfst/include/fst/generic-register.h
diff options
context:
space:
mode:
Diffstat (limited to 'kaldi_io/src/tools/openfst/include/fst/generic-register.h')
-rw-r--r--kaldi_io/src/tools/openfst/include/fst/generic-register.h159
1 files changed, 159 insertions, 0 deletions
diff --git a/kaldi_io/src/tools/openfst/include/fst/generic-register.h b/kaldi_io/src/tools/openfst/include/fst/generic-register.h
new file mode 100644
index 0000000..4f8b512
--- /dev/null
+++ b/kaldi_io/src/tools/openfst/include/fst/generic-register.h
@@ -0,0 +1,159 @@
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Copyright 2005-2010 Google, Inc.
+// Author: jpr@google.com (Jake Ratkiewicz)
+
+#ifndef FST_LIB_GENERIC_REGISTER_H_
+#define FST_LIB_GENERIC_REGISTER_H_
+
+#include <map>
+#include <string>
+
+#include <fst/compat.h>
+#include <fst/types.h>
+
+// Generic class representing a globally-stored correspondence between
+// objects of KeyType and EntryType.
+// KeyType must:
+// a) be such as can be stored as a key in a map<>
+// b) be concatenable with a const char* with the + operator
+// (or you must subclass and redefine LoadEntryFromSharedObject)
+// EntryType must be default constructible.
+//
+// The third template parameter should be the type of a subclass of this class
+// (think CRTP). This is to allow GetRegister() to instantiate and return
+// an object of the appropriate type.
+
+namespace fst {
+
+template<class KeyType, class EntryType, class RegisterType>
+class GenericRegister {
+ public:
+ typedef KeyType Key;
+ typedef EntryType Entry;
+
+ static RegisterType *GetRegister() {
+ FstOnceInit(&register_init_,
+ &RegisterType::Init);
+
+ return register_;
+ }
+
+ void SetEntry(const KeyType &key,
+ const EntryType &entry) {
+ MutexLock l(register_lock_);
+
+ register_table_.insert(make_pair(key, entry));
+ }
+
+ EntryType GetEntry(const KeyType &key) const {
+ const EntryType *entry = LookupEntry(key);
+ if (entry) {
+ return *entry;
+ } else {
+ return LoadEntryFromSharedObject(key);
+ }
+ }
+
+ virtual ~GenericRegister() { }
+
+ protected:
+ // Override this if you want to be able to load missing definitions from
+ // shared object files.
+ virtual EntryType LoadEntryFromSharedObject(const KeyType &key) const {
+ string so_filename = ConvertKeyToSoFilename(key);
+
+ void *handle = dlopen(so_filename.c_str(), RTLD_LAZY);
+ if (handle == 0) {
+ LOG(ERROR) << "GenericRegister::GetEntry : " << dlerror();
+ return EntryType();
+ }
+
+ // We assume that the DSO constructs a static object in its global
+ // scope that does the registration. Thus we need only load it, not
+ // call any methods.
+ const EntryType *entry = this->LookupEntry(key);
+ if (entry == 0) {
+ LOG(ERROR) << "GenericRegister::GetEntry : "
+ << "lookup failed in shared object: " << so_filename;
+ return EntryType();
+ }
+ return *entry;
+ }
+
+ // Override this to define how to turn a key into an SO filename.
+ virtual string ConvertKeyToSoFilename(const KeyType& key) const = 0;
+
+ virtual const EntryType *LookupEntry(
+ const KeyType &key) const {
+ MutexLock l(register_lock_);
+
+ typename RegisterMapType::const_iterator it = register_table_.find(key);
+
+ if (it != register_table_.end()) {
+ return &it->second;
+ } else {
+ return 0;
+ }
+ }
+
+ private:
+ typedef map<KeyType, EntryType> RegisterMapType;
+
+ static void Init() {
+ register_lock_ = new Mutex;
+ register_ = new RegisterType;
+ }
+
+ static FstOnceType register_init_;
+ static Mutex *register_lock_;
+ static RegisterType *register_;
+
+ RegisterMapType register_table_;
+};
+
+template<class KeyType, class EntryType, class RegisterType>
+FstOnceType GenericRegister<KeyType, EntryType,
+ RegisterType>::register_init_ = FST_ONCE_INIT;
+
+template<class KeyType, class EntryType, class RegisterType>
+Mutex *GenericRegister<KeyType, EntryType, RegisterType>::register_lock_ = 0;
+
+template<class KeyType, class EntryType, class RegisterType>
+RegisterType *GenericRegister<KeyType, EntryType, RegisterType>::register_ = 0;
+
+//
+// GENERIC REGISTRATION
+//
+
+// Generic register-er class capable of creating new register entries in the
+// given RegisterType template parameter. This type must define types Key
+// and Entry, and have appropriate static GetRegister() and instance
+// SetEntry() functions. An easy way to accomplish this is to have RegisterType
+// be the type of a subclass of GenericRegister.
+template<class RegisterType>
+class GenericRegisterer {
+ public:
+ typedef typename RegisterType::Key Key;
+ typedef typename RegisterType::Entry Entry;
+
+ GenericRegisterer(Key key, Entry entry) {
+ RegisterType *reg = RegisterType::GetRegister();
+ reg->SetEntry(key, entry);
+ }
+};
+
+} // namespace fst
+
+#endif // FST_LIB_GENERIC_REGISTER_H_