diff --git a/src/parser.tmpl.h b/src/parser.tmpl.h index 97fa925..a13fc3d 100644 --- a/src/parser.tmpl.h +++ b/src/parser.tmpl.h @@ -430,7 +430,8 @@ void parser::complete(const item& i, container_t& t, container_t& c, // Predictor may have been evicted from S; it can still drive // completion only if conjunction-cascade machinery kept it in U. bool in_S = S[it->set].find(*it) != S[it->set].end(); - bool in_U = any_conj && it->set < U.size() + const size_t predictor_set = it->set; + bool in_U = any_conj && predictor_set < U.size() && U[it->set].find(*it) != U[it->set].end(); if (!in_S && !in_U) continue; DBGP(print(std::cout << " ? checking \t\t\t\t", *it) << "\n";) diff --git a/src/utility/tree.h b/src/utility/tree.h index 1f93013..0a602c3 100644 --- a/src/utility/tree.h +++ b/src/utility/tree.h @@ -275,7 +275,10 @@ struct bintree { */ inline static std::atomic gc_enabled{true}; // Protects M() and gc_callbacks; shared for reads, exclusive for writes/gc. - inline static std::shared_mutex mtx_{}; + static std::shared_mutex& mutex() { + static std::shared_mutex value; + return value; + } /** * @brief Garbage collect tree nodes @@ -891,7 +894,10 @@ struct lcrs_tree : public bintree { = std::function; inline static hook_function hook = nullptr; // Protects hook and use_hooks (shared for reads, exclusive for set/reset). - inline static std::shared_mutex hook_mtx_{}; + static std::shared_mutex& hook_mutex() { + static std::shared_mutex value; + return value; + } inline static void set_hook(hook_function h); inline static void reset_hook(); inline static bool is_hooked(); diff --git a/src/utility/tree.tmpl.h b/src/utility/tree.tmpl.h index 38e6f9c..3e32d50 100644 --- a/src/utility/tree.tmpl.h +++ b/src/utility/tree.tmpl.h @@ -104,7 +104,7 @@ tref bintree::get() const { return reinterpret_cast(this); } template const htref bintree::geth(tref h) { if (h == NULL) return htree::null(); - std::unique_lock lock(mtx_); + std::unique_lock lock(mutex()); auto res = M().find(*reinterpret_cast(h)); if (auto sp = res->second.lock()) return sp; htref ret(new htree(h)); @@ -129,13 +129,13 @@ tref bintree::get(const T& v, tref l, tref r) { bintree bn(v, l, r); // Fast path: shared lock for the common case where the node already exists. { - std::shared_lock lock(mtx_); + std::shared_lock lock(mutex()); auto it = M().find(bn); if (it != M().end()) return reinterpret_cast(std::addressof(it->first)); } // Slow path: exclusive lock to insert (double-check after acquiring). - std::unique_lock lock(mtx_); + std::unique_lock lock(mutex()); auto res = M().emplace(bn, htree::wp()); return reinterpret_cast(std::addressof(res.first->first)); } @@ -164,7 +164,7 @@ void bintree::gc() { template void bintree::gc(std::unordered_set& keep) { if (!gc_enabled.load(std::memory_order_relaxed)) return; - std::unique_lock lock(mtx_); + std::unique_lock lock(mutex()); // DBG(dump();) //DBG(htree::dump();) @@ -260,7 +260,7 @@ template cache_t& bintree::create_cache(const cache_t& init) { static std::deque caches; // Protect both caches and the gc callback lists under the exclusive lock. - std::unique_lock lock(mtx_); + std::unique_lock lock(mutex()); cache_t& cache = caches.emplace_back(init); // Pre-sweep: once this entry's key is fully reachable, its value's @@ -525,10 +525,10 @@ tref lcrs_tree::get_raw(const T& v, const tref* ch, size_t len, tref r) { template tref lcrs_tree::get(const T& v, const tref* ch, size_t len, tref r) { // Snapshot hook under shared lock; call it after releasing the lock - // to avoid holding hook_mtx_ while bintree::get() acquires mtx_. + // to avoid holding hook_mutex() while bintree::get() acquires mutex(). hook_function h; { - std::shared_lock lock(hook_mtx_); + std::shared_lock lock(hook_mutex()); if (!use_hooks || !hook) return get_raw(v, ch, len, r); h = hook; } @@ -993,19 +993,19 @@ std::string dump_to_str(const subtree_map& m, bool subtree) { template void lcrs_tree::set_hook(hook_function h) { - std::unique_lock lock(hook_mtx_); + std::unique_lock lock(hook_mutex()); hook = h; } template void lcrs_tree::reset_hook() { - std::unique_lock lock(hook_mtx_); + std::unique_lock lock(hook_mutex()); hook = nullptr; } template bool lcrs_tree::is_hooked() { - std::shared_lock lock(hook_mtx_); + std::shared_lock lock(hook_mutex()); return hook != nullptr; }