/* unlink a state object from the hash table, but don't free it */ void unhash_state(struct state *st) { /* unlink from forward chain */ struct state **p; if(st->st_hashchain_prev == NULL) { p = state_hash(st->st_icookie, st->st_rcookie, NULL); if(*p != st) { p = state_hash(st->st_icookie, zero_cookie, NULL); } } else { p = &st->st_hashchain_prev->st_hashchain_next; } /* unlink from forward chain */ passert(*p == st); *p = st->st_hashchain_next; /* unlink from backward chain */ if (st->st_hashchain_next != NULL) { passert(st->st_hashchain_next->st_hashchain_prev == st); st->st_hashchain_next->st_hashchain_prev = st->st_hashchain_prev; } st->st_hashchain_next = st->st_hashchain_prev = NULL; }
/** * 引数としてあたえられたStateが等しいかどうかを判定する */ static int state_equals_with_compress(State *check, State *stored) { LmnBinStr bs1, bs2; int t; #ifdef PROFILE if (lmn_env.prof_no_memeq) { /* 本フラグが真の場合はグラフ同形成判定を行わず, ハッシュ値の一致不一致で状態の等価性を判定する. * ハッシュコンフリクトで完全性が損なわれるが, . * ハッシュ値が完全に散らばることが既知の問題に対し, メモリ使用量等のプロファイルを取る際など, * プロファイル収集を円滑に行うべく使用する. グラフ同型成判定の時間分だけ高速化できる */ return (state_hash(check) == state_hash(stored)); } #endif if (s_is_d(check)) { bs1 = state_D_fetch(check); } else { bs1 = state_binstr(check); } if (s_is_d(stored)) { bs2 = state_binstr_reconstructor(stored); } else { bs2 = state_binstr(stored); } if (is_encoded(check) && is_encoded(stored)) { /* 膜のIDで比較 */ t = check->state_name == stored->state_name && binstr_compare(bs1, bs2) == 0; } else if (state_mem(check) && bs2) { /* 同型性判定 */ t = check->state_name == stored->state_name && lmn_mem_equals_enc(bs2, state_mem(check)); } else if (bs1 && bs2) { /* このブロックは基本的には例外処理なので注意. * PORなどでコピー状態を挿入する際に呼ばれることがある. */ LmnMembrane *mem = lmn_binstr_decode(bs1); t = check->state_name == stored->state_name && lmn_mem_equals_enc(bs2, mem); lmn_mem_free_rec(mem); } else { lmn_fatal("implementation error"); } if (s_is_d(stored)) { lmn_binstr_free(bs2); } return t; }
/* * unlink a state object from the hash table that had a zero * rcookie before, and rehash it into the right place */ void rehash_state(struct state *st) { unsigned bucket = 0; /* unlink from forward chain */ struct state **p = st->st_hashchain_prev == NULL ? state_hash(st->st_icookie, zero_cookie, &bucket) : &st->st_hashchain_prev->st_hashchain_next; DBG(DBG_CONTROL , DBG_log("rehashing state object #%lu from bucket %u" , st->st_serialno, bucket)); /* unlink from forward chain */ passert(*p == st); *p = st->st_hashchain_next; /* unlink from backward chain */ if (st->st_hashchain_next != NULL) { passert(st->st_hashchain_next->st_hashchain_prev == st); st->st_hashchain_next->st_hashchain_prev = st->st_hashchain_prev; } st->st_hashchain_next = st->st_hashchain_prev = NULL; /* now, re-insert */ insert_state(st); }
/* Insert a state object in the hash table. The object is inserted * at the begining of list. * Needs cookies, connection, and msgid. */ void insert_state(struct state *st) { unsigned int bucket; struct state **p = state_hash(st->st_icookie, st->st_rcookie, &bucket); passert(st->st_hashchain_prev == NULL && st->st_hashchain_next == NULL); DBG(DBG_CONTROL , DBG_log("inserting state object #%lu bucket: %u" , st->st_serialno, bucket)); if (*p != NULL) { passert((*p)->st_hashchain_prev == NULL); (*p)->st_hashchain_prev = st; } st->st_hashchain_next = *p; *p = st; /* Ensure that somebody is in charge of killing this state: * if no event is scheduled for it, schedule one to discard the state. * If nothing goes wrong, this event will be replaced by * a more appropriate one. */ if (st->st_event == NULL) event_schedule(EVENT_SO_DISCARD, 0, st); refresh_state(st); }
static State * state_table_force (StateTable *table, const unsigned *positions) { unsigned hash = state_hash (table->n_entries, positions); unsigned idx = hash % table->n_entries; State *at = table->hash_table[idx]; while (at != NULL) { if (memcmp (at->positions, positions, sizeof (unsigned) * table->n_entries) == 0) return at; at = at->hash_next; } /* Allocate a state */ if (table->n_states_free_in_slab == 0) { StateSlab *slab = dsk_malloc (table->sizeof_slab); table->next_free_in_cur_slab = (State *)(slab + 1); table->n_states_free_in_slab = table->n_states_in_slab; slab->next_slab = table->cur_slab; table->cur_slab = slab; } at = table->next_free_in_cur_slab; table->next_free_in_cur_slab = (State *) ((char*)table->next_free_in_cur_slab + table->sizeof_state); table->n_states_free_in_slab -= 1; table->occupancy++; if (table->occupancy * 2 > table->table_size) { unsigned new_table_size = ...; ... idx = hash % table->table_size; }