void SemiTable::Remove(int index) { const SemiConnection& s = m_entries[index]; if (s.m_group_id != -1) { m_groups->GetGroupById(s.m_group_id) ->BreakConnection(index, s.m_con_type); } m_end_table[SlotIndex(HashEndpoints(s))].Exclude(index); m_hash_table[SlotIndex(s.m_hash)].Exclude(index); m_freelist.PushBack(index); m_usedlist.Exclude(index); }
void SemiTable::TransferEndpoints(cell_t from, cell_t to) { for (int i = 0; i < m_usedlist.Length(); ++i) { const int index = m_usedlist[i]; SemiConnection& s = m_entries[index]; if (s.m_p1 == from || s.m_p2 == from) { m_end_table[SlotIndex(HashEndpoints(s))].Exclude(index); m_hash_table[SlotIndex(s.m_hash)].Exclude(index); s.ReplaceEndpoint(from, to); m_end_table[SlotIndex(HashEndpoints(s))].Include(index); m_hash_table[SlotIndex(s.m_hash)].Include(index); } } }
int32_t SemiTable::HashToIndex(uint32_t hash) const { int hslot = SlotIndex(hash); for (int i = 0; i < m_hash_table[hslot].Length(); ++i) if (m_entries[ m_hash_table[hslot][i] ].m_hash == hash) return m_hash_table[hslot][i]; assert(false); return -1; }
const SemiConnection& SemiTable::LookupHash(uint32_t hash) const { int hslot = SlotIndex(hash); for (int i = 0; i < m_hash_table[hslot].Length(); ++i) { const SemiConnection& s = m_entries[ m_hash_table[hslot][i] ]; if (s.m_hash == hash) return s; } throw YException() << "Lookup failed on hash!! (" << hash << ")\n"; return m_entries[0]; // to avoid compilation error }
void SemiTable::RemoveAllBetween(cell_t a, cell_t b) { int eslot = SlotIndex(Hash(a) ^ Hash(b)); SlotSizeList m_worklist(m_end_table[eslot]); for (int i = 0; i < m_worklist.Length(); ++i) { const int index = m_worklist[i]; const SemiConnection& s = m_entries[ index ]; if (s.SameEndpoints(a, b)) { Remove(index); } } }
/************************************************************** NAME : BsaveTemplateSlots DESCRIPTION : Writes class instance template binary data INPUTS : 1) The defclass 2) The binary file pointer RETURNS : Nothing useful SIDE EFFECTS : Defclass instance template binary data written NOTES : None **************************************************************/ static void BsaveTemplateSlots( struct constructHeader *theDefclass, void *buf) { DEFCLASS *cls = (DEFCLASS *) theDefclass; register unsigned i; long tsp; for (i = 0 ; i < cls->instanceSlotCount ; i++) { tsp = SlotIndex(cls->instanceTemplate[i]); GenWrite((void *) &tsp,(UNLN) sizeof(long),(FILE *) buf); } }
void SemiTable::Include(const SemiConnection& s) { // Abort include if s is a superset of an existing connection. // Make a list of all existing connections that are supsersets of s. BEGIN_USING_WORKLIST; m_worklist.Clear(); int eslot = SlotIndex(HashEndpoints(s)); for (int i = 0; i < m_end_table[eslot].Length(); ++i) { const int index = m_end_table[eslot][i]; const SemiConnection& other = m_entries[ index ]; if (other.SameEndpoints(s)) { if (other.IsCarrierSubsetOf(s)) { // YTrace() << "############### SKIPPING SUPERSET ####\n"; // YTrace() << "s: " << s.ToString() << '\n'; // YTrace() << "o: " << other.ToString() << '\n'; FINISH_USING_WORKLIST; return; } else if (s.IsCarrierSubsetOf(other)) { m_worklist.PushBack(index); } } } // If an existing superset of s is used in a group we can replace // it with s; otherwise, just free all supersets. int replace_index = -1; for (int i = 0; i < m_worklist.Length(); ++i) { const int index = m_worklist[i]; SemiConnection& other = m_entries[ index ]; if (other.m_group_id != -1) { // Only be possible to do this once: If a semi from // this list is used in a group connection, then the // endpoints of this list are in the same group, hence, // there are exactly two disjoint semis from this list // used in the group connection. Hence if s is a subset of // semi1 it cannot be a subset of semi2 (and vice versa). assert(replace_index == -1); replace_index = index; } else { Remove(index); m_newlist.Exclude(&other); } } FINISH_USING_WORKLIST; // Replace an existing semi if (replace_index != -1) { SemiConnection& other = m_entries[ replace_index ]; // Move it into its new hash slot m_hash_table[SlotIndex(other.m_hash)].Exclude(replace_index); int hslot = SlotIndex(s.m_hash); if (m_hash_table[hslot].Length() >= MAX_ENTRIES_PER_SLOT) throw YException("Hash list is full!"); m_hash_table[hslot].PushBack(replace_index); int group_id = other.m_group_id; cell_t type = other.m_con_type; // YTrace() << "Replacing SemiConnection!\n" // << "gid: " << group_id << " type: " << type << '\n' // << "old: " << other.ToString() << '\n' // << "new: " << s.ToString() << '\n'; m_entries[replace_index] = s; m_entries[replace_index].m_group_id = group_id; m_entries[replace_index].m_con_type = type; // FIXME: add it to the new list of semis??! // Shrink all groups above g // FIXME: Is this okay? Should I really allow SemiTable // access to private stuff in Groups? Group* g = m_groups->GetGroupById(group_id); m_groups->ComputeConnectionCarrier(g, type); m_groups->RecomputeFromChildrenToTop(g); // YTrace() << "index=" << replace_index << '\n'; // YTrace() << "REPLACED: " << s.ToString() << ' ' // << YUtil::HashString(s.m_hash) << '\n'; } // Find room for s else { if (m_freelist.IsEmpty()) throw YException("SemiTable is full!!!"); if (m_end_table[eslot].Length() >= MAX_ENTRIES_PER_SLOT) throw YException("Endpoint list is full!"); int hslot = SlotIndex(s.m_hash); if (m_hash_table[hslot].Length() >= MAX_ENTRIES_PER_SLOT) throw YException("Hash list is full!"); int index = m_freelist.Last(); m_freelist.PopBack(); m_usedlist.PushBack(index); m_end_table[eslot].PushBack(index); m_hash_table[hslot].PushBack(index); m_entries[index] = s; if (m_newlist.Length() >= 128) throw YException("New list is full (>=128)!!"); m_newlist.PushBack(&m_entries[index]); } }
oSlotEntry PendingChainState::slot_lookup_by_timestamp( const time_point_sec timestamp )const { const auto iter = _slot_timestamp_to_delegate.find( timestamp ); if( iter != _slot_timestamp_to_delegate.end() ) return _slot_index_to_entry.at( SlotIndex( iter->second, timestamp ) ); const ChainInterfacePtr prev_state = _prev_state.lock(); if( !prev_state ) return oSlotEntry(); const oSlotEntry entry = prev_state->lookup<SlotEntry>( timestamp ); if( entry.valid() && _slot_index_remove.count( entry->index ) == 0 ) return *entry; return oSlotEntry(); }