1f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// cache.h 2f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 3f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Licensed under the Apache License, Version 2.0 (the "License"); 4f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// you may not use this file except in compliance with the License. 5f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// You may obtain a copy of the License at 6f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 7f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// http://www.apache.org/licenses/LICENSE-2.0 8f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 9f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Unless required by applicable law or agreed to in writing, software 10f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// distributed under the License is distributed on an "AS IS" BASIS, 11f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// See the License for the specific language governing permissions and 13f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// limitations under the License. 14f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 15f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Copyright 2005-2010 Google, Inc. 16f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Author: riley@google.com (Michael Riley) 17f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 18f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// \file 19f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// An Fst implementation that caches FST elements of a delayed 20f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// computation. 21f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 22f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#ifndef FST_LIB_CACHE_H__ 23f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#define FST_LIB_CACHE_H__ 24f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 25f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <vector> 26f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonusing std::vector; 27f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <list> 28f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 29f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/vector-fst.h> 30f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 31f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 32f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian HodsonDECLARE_bool(fst_default_cache_gc); 33f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian HodsonDECLARE_int64(fst_default_cache_gc_limit); 34f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 35f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonnamespace fst { 36f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 37f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct CacheOptions { 38f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson bool gc; // enable GC 39f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson size_t gc_limit; // # of bytes allowed before GC 40f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 41f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson CacheOptions(bool g, size_t l) : gc(g), gc_limit(l) {} 42f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson CacheOptions() 43f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson : gc(FLAGS_fst_default_cache_gc), 44f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson gc_limit(FLAGS_fst_default_cache_gc_limit) {} 45f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}; 46f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 47f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// A CacheStateAllocator allocates and frees CacheStates 48f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// template <class S> 49f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// struct CacheStateAllocator { 50f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// S *Allocate(StateId s); 51f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// void Free(S *state, StateId s); 52f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// }; 53f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// 54f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 55f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// A simple allocator class, can be overridden as needed, 56f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// maintains a single entry cache. 57f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class S> 58f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct DefaultCacheStateAllocator { 59f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename S::Arc::StateId StateId; 60f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 61f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson DefaultCacheStateAllocator() : mru_(NULL) { } 62f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 63f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ~DefaultCacheStateAllocator() { 64f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson delete mru_; 65f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 66f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 67f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson S *Allocate(StateId s) { 68f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (mru_) { 69f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson S *state = mru_; 70f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson mru_ = NULL; 71f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->Reset(); 72f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return state; 73f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 74f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return new S(); 75f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 76f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 77f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void Free(S *state, StateId s) { 78f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (mru_) { 79f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson delete mru_; 80f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 81f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson mru_ = state; 82f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 83f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 84f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private: 85f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson S *mru_; 86f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}; 87f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 88f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// VectorState but additionally has a flags data member (see 89f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// CacheState below). This class is used to cache FST elements with 90f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// the flags used to indicate what has been cached. Use HasStart() 91f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// HasFinal(), and HasArcs() to determine if cached and SetStart(), 925b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// SetFinal(), AddArc(), (or PushArc() and SetArcs()) to cache. Note 935b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// you must set the final weight even if the state is non-final to 945b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// mark it as cached. If the 'gc' option is 'false', cached items have 955b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// the extent of the FST - minimizing computation. If the 'gc' option 965b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// is 'true', garbage collection of states (not in use in an arc 975b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// iterator and not 'protected') is performed, in a rough 985b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// approximation of LRU order, when 'gc_limit' bytes is reached - 995b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// controlling memory use. When 'gc_limit' is 0, special optimizations 1005b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// apply - minimizing memory use. 101f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 102f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class S, class C = DefaultCacheStateAllocator<S> > 103f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass CacheBaseImpl : public VectorFstBaseImpl<S> { 104f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public: 105f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef S State; 106f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef C Allocator; 107f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename State::Arc Arc; 108f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename Arc::Weight Weight; 109f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename Arc::StateId StateId; 110f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 111f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson using FstImpl<Arc>::Type; 112f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson using FstImpl<Arc>::Properties; 113f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson using FstImpl<Arc>::SetProperties; 114f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson using VectorFstBaseImpl<State>::NumStates; 1155b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin using VectorFstBaseImpl<State>::Start; 116f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson using VectorFstBaseImpl<State>::AddState; 117f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson using VectorFstBaseImpl<State>::SetState; 1185b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin using VectorFstBaseImpl<State>::ReserveStates; 119f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 120f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson explicit CacheBaseImpl(C *allocator = 0) 121f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson : cache_start_(false), nknown_states_(0), min_unexpanded_state_id_(0), 122f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson cache_first_state_id_(kNoStateId), cache_first_state_(0), 123f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson cache_gc_(FLAGS_fst_default_cache_gc), cache_size_(0), 124f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson cache_limit_(FLAGS_fst_default_cache_gc_limit > kMinCacheLimit || 125f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson FLAGS_fst_default_cache_gc_limit == 0 ? 1265b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin FLAGS_fst_default_cache_gc_limit : kMinCacheLimit), 1275b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin protect_(false) { 1285b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin allocator_ = allocator ? allocator : new C(); 1295b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 130f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 131f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson explicit CacheBaseImpl(const CacheOptions &opts, C *allocator = 0) 132f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson : cache_start_(false), nknown_states_(0), 133f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson min_unexpanded_state_id_(0), cache_first_state_id_(kNoStateId), 134f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson cache_first_state_(0), cache_gc_(opts.gc), cache_size_(0), 135f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson cache_limit_(opts.gc_limit > kMinCacheLimit || opts.gc_limit == 0 ? 1365b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin opts.gc_limit : kMinCacheLimit), 1375b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin protect_(false) { 1385b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin allocator_ = allocator ? allocator : new C(); 1395b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 140f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 1415b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin // Preserve gc parameters. If preserve_cache true, also preserves 1425b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin // cache data. 1435b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin CacheBaseImpl(const CacheBaseImpl<S, C> &impl, bool preserve_cache = false) 1445b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin : VectorFstBaseImpl<S>(), cache_start_(false), nknown_states_(0), 1455b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin min_unexpanded_state_id_(0), cache_first_state_id_(kNoStateId), 1465b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_first_state_(0), cache_gc_(impl.cache_gc_), cache_size_(0), 1475b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_limit_(impl.cache_limit_), 1485b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin protect_(impl.protect_) { 1495b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin allocator_ = new C(); 1505b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (preserve_cache) { 1515b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_start_ = impl.cache_start_; 1525b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin nknown_states_ = impl.nknown_states_; 1535b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin expanded_states_ = impl.expanded_states_; 1545b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin min_unexpanded_state_id_ = impl.min_unexpanded_state_id_; 1555b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (impl.cache_first_state_id_ != kNoStateId) { 1565b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_first_state_id_ = impl.cache_first_state_id_; 1575b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_first_state_ = allocator_->Allocate(cache_first_state_id_); 1585b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin *cache_first_state_ = *impl.cache_first_state_; 159f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 1605b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_states_ = impl.cache_states_; 1615b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_size_ = impl.cache_size_; 1625b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin ReserveStates(impl.NumStates()); 1635b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin for (StateId s = 0; s < impl.NumStates(); ++s) { 1645b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin const S *state = 1655b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin static_cast<const VectorFstBaseImpl<S> &>(impl).GetState(s); 1665b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (state) { 1675b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin S *copied_state = allocator_->Allocate(s); 1685b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin *copied_state = *state; 1695b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin AddState(copied_state); 1705b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } else { 1715b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin AddState(0); 1725b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 1735b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 1745b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin VectorFstBaseImpl<S>::SetStart(impl.Start()); 1755b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 1765b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 177f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 178f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ~CacheBaseImpl() { 179f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson allocator_->Free(cache_first_state_, cache_first_state_id_); 180f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson delete allocator_; 181f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 182f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 183f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Gets a state from its ID; state must exist. 184f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const S *GetState(StateId s) const { 185f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (s == cache_first_state_id_) 186f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return cache_first_state_; 187f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson else 188f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return VectorFstBaseImpl<S>::GetState(s); 189f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 190f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 191f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Gets a state from its ID; state must exist. 192f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson S *GetState(StateId s) { 193f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (s == cache_first_state_id_) 194f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return cache_first_state_; 195f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson else 196f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return VectorFstBaseImpl<S>::GetState(s); 197f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 198f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 199f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Gets a state from its ID; return 0 if it doesn't exist. 200f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const S *CheckState(StateId s) const { 201f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (s == cache_first_state_id_) 202f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return cache_first_state_; 203f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson else if (s < NumStates()) 204f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return VectorFstBaseImpl<S>::GetState(s); 205f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson else 206f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return 0; 207f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 208f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 209f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Gets a state from its ID; add it if necessary. 2105b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin S *ExtendState(StateId s); 211f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 212f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void SetStart(StateId s) { 213f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson VectorFstBaseImpl<S>::SetStart(s); 214f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson cache_start_ = true; 215f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (s >= nknown_states_) 216f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson nknown_states_ = s + 1; 217f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 218f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 219f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void SetFinal(StateId s, Weight w) { 220f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson S *state = ExtendState(s); 221f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->final = w; 222f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->flags |= kCacheFinal | kCacheRecent | kCacheModified; 223f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 224f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 225f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // AddArc adds a single arc to state s and does incremental cache 226f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // book-keeping. For efficiency, prefer PushArc and SetArcs below 227f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // when possible. 228f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void AddArc(StateId s, const Arc &arc) { 229f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson S *state = ExtendState(s); 230f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->arcs.push_back(arc); 231f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (arc.ilabel == 0) { 232f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ++state->niepsilons; 233f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 234f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (arc.olabel == 0) { 235f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ++state->noepsilons; 236f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 237f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const Arc *parc = state->arcs.empty() ? 0 : &(state->arcs.back()); 238f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson SetProperties(AddArcProperties(Properties(), s, arc, parc)); 239f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->flags |= kCacheModified; 2405b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (cache_gc_ && s != cache_first_state_id_ && 2415b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin !(state->flags & kCacheProtect)) { 242f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson cache_size_ += sizeof(Arc); 243f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (cache_size_ > cache_limit_) 244f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson GC(s, false); 245f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 246f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 247f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 248f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Adds a single arc to state s but delays cache book-keeping. 249f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // SetArcs must be called when all PushArc calls at a state are 250f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // complete. Do not mix with calls to AddArc. 251f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void PushArc(StateId s, const Arc &arc) { 252f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson S *state = ExtendState(s); 253f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->arcs.push_back(arc); 254f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 255f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 256f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Marks arcs of state s as cached and does cache book-keeping after all 257f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // calls to PushArc have been completed. Do not mix with calls to AddArc. 258f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void SetArcs(StateId s) { 259f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson S *state = ExtendState(s); 260f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson vector<Arc> &arcs = state->arcs; 261f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->niepsilons = state->noepsilons = 0; 262f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson for (size_t a = 0; a < arcs.size(); ++a) { 263f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const Arc &arc = arcs[a]; 264f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (arc.nextstate >= nknown_states_) 265f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson nknown_states_ = arc.nextstate + 1; 266f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (arc.ilabel == 0) 267f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ++state->niepsilons; 268f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (arc.olabel == 0) 269f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ++state->noepsilons; 270f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 271f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ExpandedState(s); 272f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->flags |= kCacheArcs | kCacheRecent | kCacheModified; 2735b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (cache_gc_ && s != cache_first_state_id_ && 2745b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin !(state->flags & kCacheProtect)) { 275f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson cache_size_ += arcs.capacity() * sizeof(Arc); 276f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (cache_size_ > cache_limit_) 277f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson GC(s, false); 278f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 279f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson }; 280f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 281f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void ReserveArcs(StateId s, size_t n) { 282f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson S *state = ExtendState(s); 283f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->arcs.reserve(n); 284f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 285f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 286f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void DeleteArcs(StateId s, size_t n) { 287f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson S *state = ExtendState(s); 288dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin const vector<Arc> &arcs = state->arcs; 289f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson for (size_t i = 0; i < n; ++i) { 290f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson size_t j = arcs.size() - i - 1; 291f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (arcs[j].ilabel == 0) 292dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin --state->niepsilons; 293f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (arcs[j].olabel == 0) 294dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin --state->noepsilons; 295f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 2965b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin 297f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->arcs.resize(arcs.size() - n); 298f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson SetProperties(DeleteArcsProperties(Properties())); 299f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->flags |= kCacheModified; 3005b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (cache_gc_ && s != cache_first_state_id_ && 3015b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin !(state->flags & kCacheProtect)) { 3025b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_size_ -= n * sizeof(Arc); 3035b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 304f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 305f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 306f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void DeleteArcs(StateId s) { 307f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson S *state = ExtendState(s); 3085b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin size_t n = state->arcs.size(); 309f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->niepsilons = 0; 310f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->noepsilons = 0; 311f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->arcs.clear(); 312f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson SetProperties(DeleteArcsProperties(Properties())); 313f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->flags |= kCacheModified; 3145b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (cache_gc_ && s != cache_first_state_id_ && 3155b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin !(state->flags & kCacheProtect)) { 3165b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_size_ -= n * sizeof(Arc); 3175b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 3185b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 3195b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin 3205b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin void DeleteStates(const vector<StateId> &dstates) { 3215b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin size_t old_num_states = NumStates(); 3225b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin vector<StateId> newid(old_num_states, 0); 3235b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin for (size_t i = 0; i < dstates.size(); ++i) 3245b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin newid[dstates[i]] = kNoStateId; 3255b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin StateId nstates = 0; 3265b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin for (StateId s = 0; s < old_num_states; ++s) { 3275b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (newid[s] != kNoStateId) { 3285b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin newid[s] = nstates; 3295b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin ++nstates; 3305b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 3315b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 3325b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin // just for states_.resize(), does unnecessary walk. 3335b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin VectorFstBaseImpl<S>::DeleteStates(dstates); 3345b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin SetProperties(DeleteStatesProperties(Properties())); 3355b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin // Update list of cached states. 3365b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin typename list<StateId>::iterator siter = cache_states_.begin(); 3375b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin while (siter != cache_states_.end()) { 3385b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (newid[*siter] != kNoStateId) { 3395b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin *siter = newid[*siter]; 3405b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin ++siter; 3415b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } else { 3425b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_states_.erase(siter++); 3435b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 3445b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 3455b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 3465b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin 3475b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin void DeleteStates() { 3485b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_states_.clear(); 3495b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin allocator_->Free(cache_first_state_, cache_first_state_id_); 3505b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin for (int s = 0; s < NumStates(); ++s) { 3515b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin allocator_->Free(VectorFstBaseImpl<S>::GetState(s), s); 3525b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin SetState(s, 0); 3535b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 3545b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin nknown_states_ = 0; 3555b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin min_unexpanded_state_id_ = 0; 3565b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_first_state_id_ = kNoStateId; 3575b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_first_state_ = 0; 3585b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_size_ = 0; 3595b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_start_ = false; 3605b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin VectorFstBaseImpl<State>::DeleteStates(); 3615b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin SetProperties(DeleteAllStatesProperties(Properties(), 3625b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin kExpanded | kMutable)); 363f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 364f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 365f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Is the start state cached? 366f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson bool HasStart() const { 367f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (!cache_start_ && Properties(kError)) 368f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson cache_start_ = true; 369f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return cache_start_; 370f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 371f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 372f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Is the final weight of state s cached? 373f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson bool HasFinal(StateId s) const { 374f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const S *state = CheckState(s); 375f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (state && state->flags & kCacheFinal) { 376f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->flags |= kCacheRecent; 377f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return true; 378f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } else { 379f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return false; 380f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 381f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 382f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 383f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Are arcs of state s cached? 384f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson bool HasArcs(StateId s) const { 385f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const S *state = CheckState(s); 386f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (state && state->flags & kCacheArcs) { 387f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state->flags |= kCacheRecent; 388f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return true; 389f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } else { 390f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return false; 391f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 392f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 393f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 394f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson Weight Final(StateId s) const { 395f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const S *state = GetState(s); 396f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return state->final; 397f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 398f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 399f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson size_t NumArcs(StateId s) const { 400f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const S *state = GetState(s); 401f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return state->arcs.size(); 402f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 403f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 404f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson size_t NumInputEpsilons(StateId s) const { 405f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const S *state = GetState(s); 406f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return state->niepsilons; 407f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 408f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 409f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson size_t NumOutputEpsilons(StateId s) const { 410f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const S *state = GetState(s); 411f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return state->noepsilons; 412f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 413f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 414f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Provides information needed for generic arc iterator. 415f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void InitArcIterator(StateId s, ArcIteratorData<Arc> *data) const { 416f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const S *state = GetState(s); 417f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson data->base = 0; 418f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson data->narcs = state->arcs.size(); 419f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson data->arcs = data->narcs > 0 ? &(state->arcs[0]) : 0; 420f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson data->ref_count = &(state->ref_count); 421f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ++(*data->ref_count); 422f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 423f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 424f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Number of known states. 425f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson StateId NumKnownStates() const { return nknown_states_; } 426f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 427f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Update number of known states taking in account the existence of state s. 428f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void UpdateNumKnownStates(StateId s) { 429f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (s >= nknown_states_) 430f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson nknown_states_ = s + 1; 431f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 432f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 433f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Find the mininum never-expanded state Id 434f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson StateId MinUnexpandedState() const { 435f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson while (min_unexpanded_state_id_ < expanded_states_.size() && 436f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson expanded_states_[min_unexpanded_state_id_]) 437f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ++min_unexpanded_state_id_; 438f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return min_unexpanded_state_id_; 439f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 440f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 4415b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin // Removes from cache_states_ and uncaches (not referenced-counted 4425b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin // or protected) states that have not been accessed since the last 4435b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin // GC until at most cache_fraction * cache_limit_ bytes are cached. 4445b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin // If that fails to free enough, recurs uncaching recently visited 4455b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin // states as well. If still unable to free enough memory, then 4465b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin // widens cache_limit_ to fulfill condition. 4475b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin void GC(StateId current, bool free_recent, float cache_fraction = 0.666); 448f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 4495b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin // Setc/clears GC protection: if true, new states are protected 4505b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin // from garbage collection. 4515b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin void GCProtect(bool on) { protect_ = on; } 452f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 453f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void ExpandedState(StateId s) { 454f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (s < min_unexpanded_state_id_) 455f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return; 456f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson while (expanded_states_.size() <= s) 457f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson expanded_states_.push_back(false); 458f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson expanded_states_[s] = true; 459f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 460f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 4615b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin C *GetAllocator() const { 4625b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin return allocator_; 4635b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 4645b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin 465f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // Caching on/off switch, limit and size accessors. 466f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson bool GetCacheGc() const { return cache_gc_; } 467f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson size_t GetCacheLimit() const { return cache_limit_; } 468f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson size_t GetCacheSize() const { return cache_size_; } 469f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 470f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private: 4715b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin static const size_t kMinCacheLimit = 8096; // Minimum (non-zero) cache limit 4725b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin 4735b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin static const uint32 kCacheFinal = 0x0001; // Final weight has been cached 4745b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin static const uint32 kCacheArcs = 0x0002; // Arcs have been cached 4755b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin static const uint32 kCacheRecent = 0x0004; // Mark as visited since GC 4765b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin static const uint32 kCacheProtect = 0x0008; // Mark state as GC protected 477f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 478f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public: 4795b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin static const uint32 kCacheModified = 0x0010; // Mark state as modified 480f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson static const uint32 kCacheFlags = kCacheFinal | kCacheArcs | kCacheRecent 4815b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin | kCacheProtect | kCacheModified; 482f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 483f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private: 4845b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin C *allocator_; // used to allocate new states 485f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson mutable bool cache_start_; // Is the start state cached? 486f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson StateId nknown_states_; // # of known states 487f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson vector<bool> expanded_states_; // states that have been expanded 488f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson mutable StateId min_unexpanded_state_id_; // minimum never-expanded state Id 489f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson StateId cache_first_state_id_; // First cached state id 490f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson S *cache_first_state_; // First cached state 491f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson list<StateId> cache_states_; // list of currently cached states 492f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson bool cache_gc_; // enable GC 493f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson size_t cache_size_; // # of bytes cached 494f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson size_t cache_limit_; // # of bytes allowed before GC 4955b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin bool protect_; // Protect new states from GC 496f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 4975b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin void operator=(const CacheBaseImpl<S, C> &impl); // disallow 498f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}; 499f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 5005b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// Gets a state from its ID; add it if necessary. 5015b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkintemplate <class S, class C> 5025b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander GutkinS *CacheBaseImpl<S, C>::ExtendState(typename S::Arc::StateId s) { 5035b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin // If 'protect_' true and a new state, protects from garbage collection. 5045b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (s == cache_first_state_id_) { 5055b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin return cache_first_state_; // Return 1st cached state 5065b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } else if (cache_limit_ == 0 && cache_first_state_id_ == kNoStateId) { 5075b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_first_state_id_ = s; // Remember 1st cached state 5085b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_first_state_ = allocator_->Allocate(s); 5095b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (protect_) cache_first_state_->flags |= kCacheProtect; 5105b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin return cache_first_state_; 5115b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } else if (cache_first_state_id_ != kNoStateId && 5125b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_first_state_->ref_count == 0 && 5135b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin !(cache_first_state_->flags & kCacheProtect)) { 5145b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin // With Default allocator, the Free and Allocate will reuse the same S*. 5155b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin allocator_->Free(cache_first_state_, cache_first_state_id_); 5165b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_first_state_id_ = s; 5175b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_first_state_ = allocator_->Allocate(s); 5185b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (protect_) cache_first_state_->flags |= kCacheProtect; 5195b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin return cache_first_state_; // Return 1st cached state 5205b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } else { 5215b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin while (NumStates() <= s) // Add state to main cache 5225b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin AddState(0); 5235b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin S *state = VectorFstBaseImpl<S>::GetState(s); 5245b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (!state) { 5255b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin state = allocator_->Allocate(s); 5265b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (protect_) state->flags |= kCacheProtect; 5275b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin SetState(s, state); 5285b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (cache_first_state_id_ != kNoStateId) { // Forget 1st cached state 5295b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin while (NumStates() <= cache_first_state_id_) 5305b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin AddState(0); 5315b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin SetState(cache_first_state_id_, cache_first_state_); 5325b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (cache_gc_ && !(cache_first_state_->flags & kCacheProtect)) { 5335b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_states_.push_back(cache_first_state_id_); 5345b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_size_ += sizeof(S) + 5355b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_first_state_->arcs.capacity() * sizeof(Arc); 5365b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 5375b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_limit_ = kMinCacheLimit; 5385b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_first_state_id_ = kNoStateId; 5395b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_first_state_ = 0; 5405b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 5415b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (cache_gc_ && !protect_) { 5425b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_states_.push_back(s); 5435b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_size_ += sizeof(S); 5445b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (cache_size_ > cache_limit_) 5455b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin GC(s, false); 5465b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 5475b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 5485b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin return state; 5495b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 5505b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin} 5515b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin 5525b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// Removes from cache_states_ and uncaches (not referenced-counted or 5535b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// protected) states that have not been accessed since the last GC 5545b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// until at most cache_fraction * cache_limit_ bytes are cached. If 5555b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// that fails to free enough, recurs uncaching recently visited states 5565b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// as well. If still unable to free enough memory, then widens cache_limit_ 5575b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin// to fulfill condition. 5585b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkintemplate <class S, class C> 5595b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkinvoid CacheBaseImpl<S, C>::GC(typename S::Arc::StateId current, 5605b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin bool free_recent, float cache_fraction) { 5615b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (!cache_gc_) 5625b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin return; 5635b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin VLOG(2) << "CacheImpl: Enter GC: object = " << Type() << "(" << this 5645b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin << "), free recently cached = " << free_recent 5655b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin << ", cache size = " << cache_size_ 5665b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin << ", cache frac = " << cache_fraction 5675b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin << ", cache limit = " << cache_limit_ << "\n"; 5685b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin typename list<StateId>::iterator siter = cache_states_.begin(); 5695b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin 5705b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin size_t cache_target = cache_fraction * cache_limit_; 5715b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin while (siter != cache_states_.end()) { 5725b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin StateId s = *siter; 5735b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin S* state = VectorFstBaseImpl<S>::GetState(s); 5745b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (cache_size_ > cache_target && state->ref_count == 0 && 5755b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin (free_recent || !(state->flags & kCacheRecent)) && s != current) { 5765b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_size_ -= sizeof(S) + state->arcs.capacity() * sizeof(Arc); 5775b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin allocator_->Free(state, s); 5785b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin SetState(s, 0); 5795b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_states_.erase(siter++); 5805b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } else { 5815b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin state->flags &= ~kCacheRecent; 5825b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin ++siter; 5835b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 5845b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 5855b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin if (!free_recent && cache_size_ > cache_target) { // recurses on recent 5865b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin GC(current, true); 5875b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } else if (cache_target > 0) { // widens cache limit 5885b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin while (cache_size_ > cache_target) { 5895b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_limit_ *= 2; 5905b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin cache_target *= 2; 5915b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 5925b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } else if (cache_size_ > 0) { 5935b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin FSTERROR() << "CacheImpl:GC: Unable to free all cached states"; 5945b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 5955b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin VLOG(2) << "CacheImpl: Exit GC: object = " << Type() << "(" << this 5965b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin << "), free recently cached = " << free_recent 5975b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin << ", cache size = " << cache_size_ 5985b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin << ", cache frac = " << cache_fraction 5995b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin << ", cache limit = " << cache_limit_ << "\n"; 6005b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin} 6015b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin 602f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class S, class C> const uint32 CacheBaseImpl<S, C>::kCacheFinal; 603f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class S, class C> const uint32 CacheBaseImpl<S, C>::kCacheArcs; 604f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class S, class C> const uint32 CacheBaseImpl<S, C>::kCacheRecent; 605f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class S, class C> const uint32 CacheBaseImpl<S, C>::kCacheModified; 606f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class S, class C> const size_t CacheBaseImpl<S, C>::kMinCacheLimit; 607f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 608f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Arcs implemented by an STL vector per state. Similar to VectorState 609f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// but adds flags and ref count to keep track of what has been cached. 610f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A> 611f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct CacheState { 612f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef A Arc; 613f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename A::Weight Weight; 614f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename A::StateId StateId; 615f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 616f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson CacheState() : final(Weight::Zero()), flags(0), ref_count(0) {} 617f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 618f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void Reset() { 619f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson flags = 0; 620f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ref_count = 0; 621f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson arcs.resize(0); 622f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 623f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 624f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson Weight final; // Final weight 625f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson vector<A> arcs; // Arcs represenation 626f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson size_t niepsilons; // # of input epsilons 627f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson size_t noepsilons; // # of output epsilons 628f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson mutable uint32 flags; 629f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson mutable int ref_count; 630f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}; 631f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 632f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// A CacheBaseImpl with a commonly used CacheState. 633f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class A> 634f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass CacheImpl : public CacheBaseImpl< CacheState<A> > { 635f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public: 636f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef CacheState<A> State; 637f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 638f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson CacheImpl() {} 639f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 640f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson explicit CacheImpl(const CacheOptions &opts) 641f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson : CacheBaseImpl< CacheState<A> >(opts) {} 642f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 6435b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin CacheImpl(const CacheImpl<A> &impl, bool preserve_cache = false) 6445b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin : CacheBaseImpl<State>(impl, preserve_cache) {} 645f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 646f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private: 647f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void operator=(const CacheImpl<State> &impl); // disallow 648f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}; 649f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 650f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 651f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Use this to make a state iterator for a CacheBaseImpl-derived Fst, 652f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// which must have type 'State' defined. Note this iterator only 653f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// returns those states reachable from the initial state, so consider 654f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// implementing a class-specific one. 655f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class F> 656f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass CacheStateIterator : public StateIteratorBase<typename F::Arc> { 657f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public: 658f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename F::Arc Arc; 659f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename Arc::StateId StateId; 660f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename F::State State; 661f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef CacheBaseImpl<State> Impl; 662f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 663f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson CacheStateIterator(const F &fst, Impl *impl) 6645b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin : fst_(fst), impl_(impl), s_(0) { 6655b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin fst_.Start(); // force start state 6665b6dc79427b8f7eeb6a7ff68034ab8548ce670eaAlexander Gutkin } 667f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 668f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson bool Done() const { 669f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (s_ < impl_->NumKnownStates()) 670f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return false; 671f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (s_ < impl_->NumKnownStates()) 672f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return false; 673f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson for (StateId u = impl_->MinUnexpandedState(); 674f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson u < impl_->NumKnownStates(); 675f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson u = impl_->MinUnexpandedState()) { 676f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // force state expansion 677f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ArcIterator<F> aiter(fst_, u); 678f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson aiter.SetFlags(kArcValueFlags, kArcValueFlags | kArcNoCache); 679f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson for (; !aiter.Done(); aiter.Next()) 680f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson impl_->UpdateNumKnownStates(aiter.Value().nextstate); 681f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson impl_->ExpandedState(u); 682f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (s_ < impl_->NumKnownStates()) 683f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return false; 684f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 685f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return true; 686f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 687f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 688f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson StateId Value() const { return s_; } 689f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 690f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void Next() { ++s_; } 691f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 692f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void Reset() { s_ = 0; } 693f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 694f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private: 695f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // This allows base class virtual access to non-virtual derived- 696f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // class members of the same name. It makes the derived class more 697f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // efficient to use but unsafe to further derive. 698f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson virtual bool Done_() const { return Done(); } 699f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson virtual StateId Value_() const { return Value(); } 700f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson virtual void Next_() { Next(); } 701f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson virtual void Reset_() { Reset(); } 702f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 703f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const F &fst_; 704f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson Impl *impl_; 705f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson StateId s_; 706f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}; 707f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 708f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 709f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Use this to make an arc iterator for a CacheBaseImpl-derived Fst, 710f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// which must have types 'Arc' and 'State' defined. 711f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class F, 712f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson class C = DefaultCacheStateAllocator<CacheState<typename F::Arc> > > 713f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass CacheArcIterator { 714f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public: 715f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename F::Arc Arc; 716f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename F::State State; 717f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename Arc::StateId StateId; 718f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef CacheBaseImpl<State, C> Impl; 719f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 720f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson CacheArcIterator(Impl *impl, StateId s) : i_(0) { 721f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state_ = impl->ExtendState(s); 722f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ++state_->ref_count; 723f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 724f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 725f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ~CacheArcIterator() { --state_->ref_count; } 726f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 727f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson bool Done() const { return i_ >= state_->arcs.size(); } 728f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 729f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const Arc& Value() const { return state_->arcs[i_]; } 730f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 731f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void Next() { ++i_; } 732f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 733f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson size_t Position() const { return i_; } 734f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 735f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void Reset() { i_ = 0; } 736f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 737f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void Seek(size_t a) { i_ = a; } 738f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 739f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson uint32 Flags() const { 740f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return kArcValueFlags; 741f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 742f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 743f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void SetFlags(uint32 flags, uint32 mask) {} 744f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 745f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private: 746f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const State *state_; 747f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson size_t i_; 748f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 749f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson DISALLOW_COPY_AND_ASSIGN(CacheArcIterator); 750f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}; 751f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 752f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Use this to make a mutable arc iterator for a CacheBaseImpl-derived Fst, 753f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// which must have types 'Arc' and 'State' defined. 754f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class F, 755f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson class C = DefaultCacheStateAllocator<CacheState<typename F::Arc> > > 756f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonclass CacheMutableArcIterator 757f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson : public MutableArcIteratorBase<typename F::Arc> { 758f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson public: 759f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename F::State State; 760f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename F::Arc Arc; 761f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename Arc::StateId StateId; 762f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef typename Arc::Weight Weight; 763f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson typedef CacheBaseImpl<State, C> Impl; 764f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 765f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson // You will need to call MutateCheck() in the constructor. 766f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson CacheMutableArcIterator(Impl *impl, StateId s) : i_(0), s_(s), impl_(impl) { 767f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state_ = impl_->ExtendState(s_); 768f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ++state_->ref_count; 769f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson }; 770f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 771f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ~CacheMutableArcIterator() { 772f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson --state_->ref_count; 773f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 774f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 775f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson bool Done() const { return i_ >= state_->arcs.size(); } 776f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 777f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson const Arc& Value() const { return state_->arcs[i_]; } 778f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 779f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void Next() { ++i_; } 780f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 781f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson size_t Position() const { return i_; } 782f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 783f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void Reset() { i_ = 0; } 784f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 785f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void Seek(size_t a) { i_ = a; } 786f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 787f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void SetValue(const Arc& arc) { 788f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson state_->flags |= CacheBaseImpl<State, C>::kCacheModified; 789f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson uint64 properties = impl_->Properties(); 790f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson Arc& oarc = state_->arcs[i_]; 791f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (oarc.ilabel != oarc.olabel) 792f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson properties &= ~kNotAcceptor; 793f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (oarc.ilabel == 0) { 794f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson --state_->niepsilons; 795f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson properties &= ~kIEpsilons; 796f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (oarc.olabel == 0) 797f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson properties &= ~kEpsilons; 798f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 799f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (oarc.olabel == 0) { 800f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson --state_->noepsilons; 801f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson properties &= ~kOEpsilons; 802f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 803f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (oarc.weight != Weight::Zero() && oarc.weight != Weight::One()) 804f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson properties &= ~kWeighted; 805f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson oarc = arc; 806f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (arc.ilabel != arc.olabel) { 807f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson properties |= kNotAcceptor; 808f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson properties &= ~kAcceptor; 809f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 810f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (arc.ilabel == 0) { 811f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ++state_->niepsilons; 812f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson properties |= kIEpsilons; 813f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson properties &= ~kNoIEpsilons; 814f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (arc.olabel == 0) { 815f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson properties |= kEpsilons; 816f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson properties &= ~kNoEpsilons; 817f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 818f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 819f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (arc.olabel == 0) { 820f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson ++state_->noepsilons; 821f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson properties |= kOEpsilons; 822f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson properties &= ~kNoOEpsilons; 823f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 824f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson if (arc.weight != Weight::Zero() && arc.weight != Weight::One()) { 825f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson properties |= kWeighted; 826f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson properties &= ~kUnweighted; 827f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 828f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson properties &= kSetArcProperties | kAcceptor | kNotAcceptor | 829f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson kEpsilons | kNoEpsilons | kIEpsilons | kNoIEpsilons | 830f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson kOEpsilons | kNoOEpsilons | kWeighted | kUnweighted; 831f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson impl_->SetProperties(properties); 832f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 833f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 834f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson uint32 Flags() const { 835f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson return kArcValueFlags; 836f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson } 837f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 838f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void SetFlags(uint32 f, uint32 m) {} 839f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 840f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson private: 841f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson virtual bool Done_() const { return Done(); } 842f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson virtual const Arc& Value_() const { return Value(); } 843f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson virtual void Next_() { Next(); } 844f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson virtual size_t Position_() const { return Position(); } 845f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson virtual void Reset_() { Reset(); } 846f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson virtual void Seek_(size_t a) { Seek(a); } 847f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson virtual void SetValue_(const Arc &a) { SetValue(a); } 848f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson uint32 Flags_() const { return Flags(); } 849f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson void SetFlags_(uint32 f, uint32 m) { SetFlags(f, m); } 850f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 851f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson size_t i_; 852f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson StateId s_; 853f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson Impl *impl_; 854f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson State *state_; 855f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 856f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson DISALLOW_COPY_AND_ASSIGN(CacheMutableArcIterator); 857f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}; 858f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 859f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson} // namespace fst 860f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson 861f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#endif // FST_LIB_CACHE_H__ 862