SetId Approximator::function_rhs_val(const Function& fun, SetId rhs, SetId val, Parity parity) const { POMAGMA_ASSERT1(rhs, "rhs is undefined"); POMAGMA_ASSERT1(val, "val is undefined"); POMAGMA_ASSERT1(parity == NABOVE or parity == NBELOW, "invalid parity"); const bool upward = (parity == NBELOW); const DenseSet& support = m_structure.carrier().support(); const DenseSet rhs_set = m_sets.load(rhs); // positive const DenseSet val_set = m_sets.load(val); // negative DenseSet lhs_set(m_item_dim); // negative for (auto iter = support.iter_diff(lhs_set); iter.ok(); iter.next()) { Ob lhs = *iter; if (unlikely(lhs_set.contains(lhs))) continue; // iterator latency for (auto iter = fun.get_Lx_set(lhs).iter_insn(rhs_set); iter.ok(); iter.next()) { Ob rhs = *iter; Ob val = fun.find(lhs, rhs); if (val_set.contains(val)) { convex_insert(lhs_set, lhs, upward); break; } } } return m_sets.store(std::move(lhs_set)); }
void FileBackedQueue::push(const void* message, uint8_t size) { POMAGMA_ASSERT1(size, "empty messages are not allowed"); std::unique_lock<std::mutex> lock(m_mutex); POMAGMA_ASSERT_C(pwrite(m_fid, &size, 1, m_write_offset)); m_write_offset += 1; POMAGMA_ASSERT_C(pwrite(m_fid, message, size, m_write_offset)); m_write_offset += size; }
void VectorQueue::push(const void* message, uint8_t size) { POMAGMA_ASSERT1(size, "empty messages are not allowed"); std::unique_lock<std::mutex> lock(m_mutex); size_t offset = m_data.size(); m_data.resize(offset + 1 + size); memcpy(m_data.data() + offset, &size, 1); memcpy(m_data.data() + offset + 1, message, size); }
SetId Approximator::function_lhs_rhs(const Function& fun, SetId lhs, SetId rhs, Parity parity) const { POMAGMA_ASSERT1(lhs, "lhs is undefined"); POMAGMA_ASSERT1(rhs, "rhs is undefined"); POMAGMA_ASSERT1(parity == ABOVE or parity == BELOW, "invalid parity"); const bool upward = (parity == ABOVE); const DenseSet lhs_set = m_sets.load(lhs); // positive const DenseSet rhs_set = m_sets.load(rhs); // positive DenseSet val_set(m_item_dim); // positive const Ob optimum = upward ? m_top : m_bot; POMAGMA_ASSERT1(lhs_set.contains(optimum), "invalid lhs set"); POMAGMA_ASSERT1(rhs_set.contains(optimum), "invalid rhs set"); val_set.insert(optimum); DenseSet temp_set(m_item_dim); for (auto iter = lhs_set.iter(); iter.ok(); iter.next()) { Ob lhs = *iter; // optimize for constant functions if (Ob lhs_top = fun.find(lhs, m_top)) { if (Ob lhs_bot = fun.find(lhs, m_bot)) { if (lhs_top == lhs_bot) { convex_insert(val_set, lhs_top, upward); continue; } } } temp_set.set_insn(rhs_set, fun.get_Lx_set(lhs)); for (auto iter = temp_set.iter(); iter.ok(); iter.next()) { Ob rhs = *iter; Ob val = fun.find(lhs, rhs); convex_insert(val_set, val, upward); } } return m_sets.store(std::move(val_set)); }
inline bool try_pop(CleanupTask &task) { const unsigned long type_count = g_type_count; POMAGMA_ASSERT1(type_count, "Cleanup::init has not been called"); unsigned long done = 0; while (not g_done_count.compare_exchange_weak(done, done + 1, std::memory_order_acq_rel)) { if (done == type_count) { return false; } } unsigned long type = 0; while (not g_type.compare_exchange_weak(type, (type + 1) % type_count, std::memory_order_acq_rel)) { } task.type = type; return true; }
void lock_shared () { int status = pthread_rwlock_rdlock(&m_rwlock); POMAGMA_ASSERT1(status == 0, "pthread_rwlock_rdlock failed"); }
// glibc seems to be buggy; don't unlock more often than it has been locked // see http://sourceware.org/bugzilla/show_bug.cgi?id=4825 void unlock () { int status = pthread_rwlock_unlock(&m_rwlock); POMAGMA_ASSERT1(status == 0, "pthread_rwlock_unlock failed"); }
~SharedMutex () { int status = pthread_rwlock_destroy(&m_rwlock); POMAGMA_ASSERT1(status == 0, "pthread_rwlock_destroy failed"); }
SharedMutex () { int status = pthread_rwlock_init(&m_rwlock, nullptr); POMAGMA_ASSERT1(status == 0, "pthread_rwlock_init failed"); }
Word *find(SetId id) const { SharedMutex::SharedLock lock(m_mutex); auto i = m_index.find(id); POMAGMA_ASSERT1(i != m_index.end(), "missing id " << id); return i->second; }
inline SetId Approximator::lazy_find(const std::string& name, Target target, Parity parity, SetId arg0, SetId arg1) { auto i = m_binary_cache.find(CacheKey{hash_name(name), target, parity}); POMAGMA_ASSERT1(i != m_binary_cache.end(), "programmer error"); return i->second->try_find({arg0, arg1}); }
Approximator::Approximator(Structure& structure, DenseSetStore& sets, WorkerPool& worker_pool) : // structure m_structure(structure), m_item_dim(structure.carrier().item_dim()), m_top(structure.nullary_function("TOP").find()), m_bot(structure.nullary_function("BOT").find()), m_less(structure.binary_relation("LESS")), m_nless(structure.binary_relation("NLESS")), // dense set stores m_sets(sets), m_empty_set(sets.store(std::move(DenseSet(m_item_dim)))), m_known(1 + m_item_dim), m_unknown(), // lazy map caches m_disjoint_cache(worker_pool, [this](const std::pair<SetId, SetId>& pair) { return m_sets.load(pair.first).disjoint(m_sets.load(pair.second)) ? Trool::TRUE : Trool::FALSE; }), m_union_cache(worker_pool, [this](const std::vector<SetId>& sets) { const size_t count = sets.size(); POMAGMA_ASSERT1(count >= 2, "too few sets: " << count); DenseSet val(m_item_dim); val.set_union(m_sets.load(sets[0]), m_sets.load(sets[1])); for (size_t i = 2; i < count; ++i) { val += m_sets.load(sets[i]); } return m_sets.store(std::move(val)); }), m_nullary_cache(), m_binary_cache() { POMAGMA_ASSERT(m_top, "TOP is not defined"); POMAGMA_ASSERT(m_bot, "BOT is not defined"); POMAGMA_INFO("Inserting LESS and NLESS in DenseSetStore"); for (auto iter = m_structure.carrier().iter(); iter.ok(); iter.next()) { const Ob ob = *iter; m_known[ob][ABOVE] = m_sets.store(m_less.get_Lx_set(ob)); m_known[ob][BELOW] = m_sets.store(m_less.get_Rx_set(ob)); m_known[ob][NABOVE] = m_sets.store(m_nless.get_Lx_set(ob)); m_known[ob][NBELOW] = m_sets.store(m_nless.get_Rx_set(ob)); } m_unknown[ABOVE] = m_known[m_top][ABOVE]; m_unknown[BELOW] = m_known[m_bot][BELOW]; m_unknown[NABOVE] = m_empty_set; m_unknown[NBELOW] = m_empty_set; POMAGMA_INFO("Initializing nullary_function cache"); for (const auto& i : signature().nullary_functions()) { const std::string& name = i.first; Ob ob = i.second->find(); Approximation approx = ob ? known(ob) : unknown(); POMAGMA_INSERT(m_nullary_cache, name, approx); } POMAGMA_INFO("Initializing binary_function cache"); for (const auto& i : signature().binary_functions()) { const auto& fun = *i.second; const uint64_t hash = hash_name(i.first); typedef SetPairToSetCache Cache; for (Parity p : {ABOVE, BELOW}) { POMAGMA_INSERT( m_binary_cache, CacheKey(hash, VAL, p), new Cache(worker_pool, [this, &fun, p](const std::pair<SetId, SetId>& x) { return function_lhs_rhs(fun, x.first, x.second, p); })); } for (Parity p : {NABOVE, NBELOW}) { POMAGMA_INSERT( m_binary_cache, CacheKey(hash, RHS, p), new Cache(worker_pool, [this, &fun, p](const std::pair<SetId, SetId>& x) { return function_lhs_val(fun, x.first, x.second, p); })); POMAGMA_INSERT( m_binary_cache, CacheKey(hash, LHS, p), new Cache(worker_pool, [this, &fun, p](const std::pair<SetId, SetId>& x) { return function_rhs_val(fun, x.first, x.second, p); })); } } POMAGMA_INFO("Initializing symmetric_function cache"); for (const auto& i : signature().symmetric_functions()) { const auto& fun = *i.second; const uint64_t hash = hash_name(i.first); typedef SetPairToSetCache Cache; for (Parity p : {ABOVE, BELOW}) { POMAGMA_INSERT( m_binary_cache, CacheKey(hash, VAL, p), new Cache(worker_pool, [this, &fun, p](const std::pair<SetId, SetId>& x) { return function_lhs_rhs(fun, x.first, x.second, p); })); } for (Parity p : {NABOVE, NBELOW}) { auto* cache = new Cache( worker_pool, [this, &fun, p](const std::pair<SetId, SetId>& x) { return function_lhs_val(fun, x.first, x.second, p); }); POMAGMA_INSERT(m_binary_cache, CacheKey(hash, RHS, p), cache); POMAGMA_INSERT(m_binary_cache, CacheKey(hash, LHS, p), cache); } } }