Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@
[submodule "third_party/wide-integer"]
path = third_party/wide-integer
url = ../../ckormanyos/wide-integer.git
[submodule "third_party/parallel-hashmap"]
path = third_party/parallel-hashmap
url = ../../greg7mdp/parallel-hashmap.git
2 changes: 1 addition & 1 deletion libgringo/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ set(source
# ]]]

add_library(libgringo STATIC ${header} ${source})
target_link_libraries(libgringo PUBLIC libpotassco libreify tsl::ordered_map tsl::hopscotch_map tsl::sparse_map tl::optional mpark::variant math::wide_integer)
target_link_libraries(libgringo PUBLIC libpotassco libreify tsl::ordered_map tsl::hopscotch_map tsl::sparse_map tl::optional mpark::variant math::wide_integer grep::phmap)
target_include_directories(libgringo
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
Expand Down
154 changes: 154 additions & 0 deletions libgringo/gringo/shared_mutex.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#pragma once

#if defined(_WIN32) || defined(_WIN64)
#define GRINGO_PLATFORM_WINDOWS 1
#else
#define GRINGO_PLATFORM_WINDOWS 0
#endif

#if !GRINGO_PLATFORM_WINDOWS && (defined(__unix__) || defined(__APPLE__))
#define GRINGO_PLATFORM_POSIX 1
#else
#define GRINGO_PLATFORM_POSIX 0
#endif

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <shared_mutex>

#if GRINGO_PLATFORM_WINDOWS
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#elif GRINGO_PLATFORM_POSIX
#include <pthread.h>
#endif

#ifndef PHMAP_DISABLE_MIX
#define PHMAP_DISABLE_MIX 1
#endif
#include <parallel_hashmap/phmap_base.h>

namespace Gringo {

#if GRINGO_PLATFORM_POSIX
namespace Detail {

inline void check_pthread_call(char const *fun, int code) noexcept {
if (code != 0) {
std::fprintf(stderr, "fatal: %s failed: %s\n", fun, std::strerror(code));
std::abort();
}
}

} // namespace Detail
#endif

class SharedMutex {
public:
SharedMutex() noexcept {
#if GRINGO_PLATFORM_WINDOWS
InitializeSRWLock(&srw_);
#elif GRINGO_PLATFORM_POSIX
Detail::check_pthread_call("pthread_rwlock_init", pthread_rwlock_init(&rw_, nullptr));
#endif
}

~SharedMutex() noexcept {
#if GRINGO_PLATFORM_POSIX
Detail::check_pthread_call("pthread_rwlock_destroy", pthread_rwlock_destroy(&rw_));
#endif
}

SharedMutex(const SharedMutex &) = delete;
SharedMutex &operator=(const SharedMutex &) = delete;
SharedMutex(SharedMutex &&) = delete;
SharedMutex &operator=(SharedMutex &&) = delete;

void lock_shared() noexcept {
#if GRINGO_PLATFORM_WINDOWS
AcquireSRWLockShared(&srw_);
#elif GRINGO_PLATFORM_POSIX
Detail::check_pthread_call("pthread_rwlock_rdlock", pthread_rwlock_rdlock(&rw_));
#else
mtx_.lock_shared();
#endif
}

bool try_lock_shared() noexcept {
#if GRINGO_PLATFORM_WINDOWS
return TryAcquireSRWLockShared(&srw_) != 0;
#elif GRINGO_PLATFORM_POSIX
return pthread_rwlock_tryrdlock(&rw_) == 0;
#else
return mtx_.try_lock_shared();
#endif
}

void unlock_shared() noexcept {
#if GRINGO_PLATFORM_WINDOWS
ReleaseSRWLockShared(&srw_);
#elif GRINGO_PLATFORM_POSIX
Detail::check_pthread_call("pthread_rwlock_unlock", pthread_rwlock_unlock(&rw_));
#else
mtx_.unlock_shared();
#endif
}

void lock() noexcept {
#if GRINGO_PLATFORM_WINDOWS
AcquireSRWLockExclusive(&srw_);
#elif GRINGO_PLATFORM_POSIX
Detail::check_pthread_call("pthread_rwlock_wrlock", pthread_rwlock_wrlock(&rw_));
#else
mtx_.lock();
#endif
}

bool try_lock() noexcept {
#if GRINGO_PLATFORM_WINDOWS
return TryAcquireSRWLockExclusive(&srw_) != 0;
#elif GRINGO_PLATFORM_POSIX
return pthread_rwlock_trywrlock(&rw_) == 0;
#else
return mtx_.try_lock();
#endif
}

void unlock() noexcept {
#if GRINGO_PLATFORM_WINDOWS
ReleaseSRWLockExclusive(&srw_);
#elif GRINGO_PLATFORM_POSIX
Detail::check_pthread_call("pthread_rwlock_unlock", pthread_rwlock_unlock(&rw_));
#else
mtx_.unlock();
#endif
}

private:
#if GRINGO_PLATFORM_WINDOWS
SRWLOCK srw_;
#elif GRINGO_PLATFORM_POSIX
pthread_rwlock_t rw_;
#else
std::shared_timed_mutex mtx_;
#endif
};

} // namespace Gringo

namespace phmap {

template <> class LockableImpl<Gringo::SharedMutex> : public Gringo::SharedMutex {
public:
using mutex_type = Gringo::SharedMutex;
using Base = LockableBaseImpl<Gringo::SharedMutex>;
using SharedLock = std::shared_lock<mutex_type>;
using ReadWriteLock = typename Base::ReadWriteLock;
using UniqueLock = std::unique_lock<mutex_type>;
using SharedLocks = typename Base::ReadLocks;
using UniqueLocks = typename Base::WriteLocks;
};

} // namespace phmap
28 changes: 16 additions & 12 deletions libgringo/src/symbol.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,15 @@

#include <algorithm>
#include <cstring>

#ifndef PHMAP_DISABLE_MIX
#define PHMAP_DISABLE_MIX 1
#endif
#include <parallel_hashmap/phmap.h>

#include <gringo/hash_set.hh>
#include <gringo/shared_mutex.hh>
#include <gringo/symbol.hh>
#include <iterator>
#include <mutex>

#ifdef _MSC_VER
#pragma warning(disable : 4200) // nonstandard extension used: zero-sized array in struct/union
Expand Down Expand Up @@ -79,28 +84,24 @@ String toString(uint64_t rep) { return String::fromRep(ptr(rep)); }

template <class T> struct UniqueConstruct {
public:
using Set = hash_set<T, typename T::Hash, typename T::EqualTo>;
using Set = phmap::parallel_flat_hash_set<T, typename T::Hash, typename T::EqualTo, std::allocator<T>, 4,
Gringo::SharedMutex>;

template <class U> static T const &construct(U &&x) {
// TODO: in C++17 this can use a read/write lock to not block reading threads
size_t hash = typename T::Hash{}(x);
std::lock_guard<std::mutex> g(mutex_);
auto hash = set_.hash(x);
auto it = set_.find(x, hash);
if (it != set_.end()) {
if (it != end(set_)) {
return *it;
}
return *set_.insert(T{std::forward<U>(x), hash}).first;
return *set_.emplace_with_hash(hash, std::forward<U>(x), hash).first;
}

private:
static Set set_; // NOLINT
static std::mutex mutex_; // NOLINT
static Set set_; // NOLINT
};

template <class T> typename UniqueConstruct<T>::Set UniqueConstruct<T>::set_; // NOLINT

template <class T> typename std::mutex UniqueConstruct<T>::mutex_; // NOLINT

template <class T, class U> T const &construct_unique(U &&x) {
return UniqueConstruct<T>::construct(std::forward<U>(x));
}
Expand All @@ -112,6 +113,7 @@ class MSig {
using Cons = std::pair<String, uint32_t>;

struct Hash {
using is_transparent = void;
size_t operator()(MSig const &sig) const { return sig.hash_; }
size_t operator()(Cons const &sig) const { return hash_mix(get_value_hash(sig)); }
};
Expand Down Expand Up @@ -190,6 +192,7 @@ class MFun {
using Cons = std::pair<Sig, SymSpan>;

struct Hash {
using is_transparent = void;
size_t operator()(MFun const &a) const { return a.fun_->hash(); }
size_t operator()(Cons const &a) const {
return hash_mix(get_value_hash(a.first, hash_range(begin(a.second), end(a.second))));
Expand Down Expand Up @@ -285,6 +288,7 @@ class String::Impl {
class String::Impl::MString {
public:
struct Hash {
using is_transparent = void;
size_t operator()(MString const &str) const { return str.str_->hash(); }
size_t operator()(char const *str) const { return hash_mix(strhash(str)); }
size_t operator()(StringSpan const &str) const { return hash_mix(strhash(str)); }
Expand Down
4 changes: 4 additions & 0 deletions third_party/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@ add_library(mpark::variant ALIAS variant)
add_library(wide_integer INTERFACE)
target_include_directories(wide_integer INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/wide-integer>)
add_library(math::wide_integer ALIAS wide_integer)

add_library(phmap INTERFACE)
target_include_directories(phmap INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/parallel-hashmap>)
add_library(grep::phmap ALIAS phmap)
1 change: 1 addition & 0 deletions third_party/parallel-hashmap
Submodule parallel-hashmap added at 8442f1
Loading