mirror of
https://github.com/luanti-org/luanti.git
synced 2025-07-22 17:18:39 +00:00
commit
3e386eee61
7 changed files with 9 additions and 508 deletions
|
@ -30,9 +30,10 @@ along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "server/serverlist.h"
|
#include "server/serverlist.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
#include <mutex>
|
||||||
|
#include <shared_mutex>
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "threading/thread.h"
|
#include "threading/thread.h"
|
||||||
#include "threading/concurrent_map.h"
|
|
||||||
#include "network/address.h"
|
#include "network/address.h"
|
||||||
|
|
||||||
//copypaste from ../socket.cpp
|
//copypaste from ../socket.cpp
|
||||||
|
@ -303,6 +304,7 @@ void *lan_adv::run()
|
||||||
if (p["port"].isInt()) {
|
if (p["port"].isInt()) {
|
||||||
p["address"] = addr_str;
|
p["address"] = addr_str;
|
||||||
auto key = addr_str + ":" + p["port"].asString();
|
auto key = addr_str + ":" + p["port"].asString();
|
||||||
|
std::unique_lock lock(mutex);
|
||||||
if (p["cmd"].asString() == "shutdown") {
|
if (p["cmd"].asString() == "shutdown") {
|
||||||
//infostream << "server shutdown " << key << "\n";
|
//infostream << "server shutdown " << key << "\n";
|
||||||
collected.erase(key);
|
collected.erase(key);
|
||||||
|
|
|
@ -20,10 +20,11 @@ along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
#include <map>
|
||||||
|
#include <shared_mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include "threading/thread.h"
|
#include "threading/thread.h"
|
||||||
#include "threading/concurrent_map.h"
|
|
||||||
|
|
||||||
|
|
||||||
class lan_adv : public Thread
|
class lan_adv : public Thread
|
||||||
|
@ -37,7 +38,9 @@ public:
|
||||||
|
|
||||||
void serve(unsigned short port);
|
void serve(unsigned short port);
|
||||||
|
|
||||||
concurrent_map<std::string, Json::Value> collected;
|
std::map<std::string, Json::Value> collected;
|
||||||
|
std::shared_mutex mutex;
|
||||||
|
|
||||||
std::atomic_bool fresh;
|
std::atomic_bool fresh;
|
||||||
std::atomic_int clients_num;
|
std::atomic_int clients_num;
|
||||||
|
|
||||||
|
|
|
@ -1101,6 +1101,7 @@ int ModApiMainMenu::l_get_lan_servers(lua_State *L)
|
||||||
int top = lua_gettop(L);
|
int top = lua_gettop(L);
|
||||||
unsigned int index = 1;
|
unsigned int index = 1;
|
||||||
|
|
||||||
|
std::shared_lock lock(ServerList::lan_adv_client.mutex);
|
||||||
for (const auto &server : ServerList::lan_adv_client.collected) {
|
for (const auto &server : ServerList::lan_adv_client.collected) {
|
||||||
lua_pushnumber(L, index);
|
lua_pushnumber(L, index);
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,5 @@ set(JTHREAD_SRCS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/event.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/event.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/thread.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/thread.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/semaphore.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/semaphore.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/lock.cpp
|
|
||||||
PARENT_SCOPE)
|
PARENT_SCOPE)
|
||||||
|
|
||||||
|
|
|
@ -1,209 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (C) 2024 proller <proler@gmail.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
This file is part of Freeminer.
|
|
||||||
|
|
||||||
Freeminer is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Freeminer is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "lock.h"
|
|
||||||
|
|
||||||
template <class LOCKER, class Key, class T, class Compare = std::less<Key>,
|
|
||||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
|
||||||
class concurrent_map_ : public std::map<Key, T, Compare, Allocator>, public LOCKER
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef typename std::map<Key, T, Compare, Allocator> full_type;
|
|
||||||
typedef Key key_type;
|
|
||||||
typedef T mapped_type;
|
|
||||||
|
|
||||||
mapped_type &operator[](const key_type &k) = delete;
|
|
||||||
mapped_type &operator[](key_type &&k) = delete;
|
|
||||||
|
|
||||||
mapped_type nothing = {};
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
mapped_type& get(Args &&...args)
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_shared_rec();
|
|
||||||
|
|
||||||
//if (!full_type::contains(std::forward<Args>(args)...))
|
|
||||||
if (full_type::find(std::forward<Args>(args)...) == full_type::end())
|
|
||||||
return nothing;
|
|
||||||
|
|
||||||
return full_type::operator[](std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) at(Args &&...args)
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_shared_rec();
|
|
||||||
return full_type::at(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) assign(Args &&...args)
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_unique_rec();
|
|
||||||
return full_type::assign(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) insert(Args &&...args)
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_unique_rec();
|
|
||||||
return full_type::insert(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) emplace(Args &&...args)
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_unique_rec();
|
|
||||||
return full_type::emplace(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) emplace_try(Args &&...args)
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::try_lock_unique_rec();
|
|
||||||
if (!lock->owns_lock())
|
|
||||||
return false;
|
|
||||||
return full_type::emplace(std::forward<Args>(args)...).second;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) insert_or_assign(Args &&...args)
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_unique_rec();
|
|
||||||
return full_type::insert_or_assign(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) empty(Args &&...args) const noexcept
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_shared_rec();
|
|
||||||
return full_type::empty(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) size(Args &&...args) const
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_shared_rec();
|
|
||||||
return full_type::size(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) count(Args &&...args) const
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_shared_rec();
|
|
||||||
return full_type::count(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) contains(Args &&...args) const
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_shared_rec();
|
|
||||||
return full_type::contains(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) find(Args &&...args)
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_shared_rec();
|
|
||||||
return full_type::find(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) begin(Args &&...args)
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_shared_rec();
|
|
||||||
return full_type::begin(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) rbegin(Args &&...args)
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_shared_rec();
|
|
||||||
return full_type::rbegin(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) end(Args &&...args)
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_shared_rec();
|
|
||||||
return full_type::end(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) rend(Args &&...args)
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_shared_rec();
|
|
||||||
return full_type::rend(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) erase(Args &&...args)
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_unique_rec();
|
|
||||||
return full_type::erase(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
decltype(auto) clear(Args &&...args)
|
|
||||||
{
|
|
||||||
auto lock = LOCKER::lock_unique_rec();
|
|
||||||
return full_type::clear(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Key, class T, class Compare = std::less<Key>,
|
|
||||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
|
||||||
using concurrent_map = concurrent_map_<locker<>, Key, T, Compare, Allocator>;
|
|
||||||
|
|
||||||
template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator<std::pair<const Key, T>>>
|
|
||||||
using concurrent_shared_map = concurrent_map_<shared_locker, Key, T, Compare, Allocator>;
|
|
||||||
|
|
||||||
#if ENABLE_THREADS
|
|
||||||
|
|
||||||
template <class Key, class T, class Compare = std::less<Key>,
|
|
||||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
|
||||||
using maybe_concurrent_map = concurrent_map<Key, T, Compare, Allocator>;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
template <class Key, class T, class Compare = std::less<Key>,
|
|
||||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
|
||||||
class not_concurrent_map : public std::map<Key, T, Compare, Allocator>,
|
|
||||||
public dummy_locker
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef typename std::map<Key, T, Compare, Allocator> full_type;
|
|
||||||
typedef Key key_type;
|
|
||||||
typedef T mapped_type;
|
|
||||||
|
|
||||||
mapped_type &get(const key_type &k) { return full_type::operator[](k); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Key, class T, class Compare = std::less<Key>,
|
|
||||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
|
||||||
using maybe_concurrent_map = not_concurrent_map<Key, T, Compare, Allocator>;
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,131 +0,0 @@
|
||||||
#include "lock.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "profiler.h"
|
|
||||||
|
|
||||||
#if !defined(NDEBUG) && !defined(LOCK_PROFILE)
|
|
||||||
//#define LOCK_PROFILE 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LOCK_PROFILE
|
|
||||||
#define SCOPE_PROFILE(a) ScopeProfiler scp___(g_profiler, "Lock: " a);
|
|
||||||
#else
|
|
||||||
#define SCOPE_PROFILE(a)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<class GUARD, class MUTEX>
|
|
||||||
recursive_lock<GUARD, MUTEX>::recursive_lock(MUTEX & mtx, std::atomic<std::size_t> & thread_id_, bool try_lock):
|
|
||||||
thread_id(thread_id_) {
|
|
||||||
auto thread_me = std::hash<std::thread::id>()(std::this_thread::get_id());
|
|
||||||
if(thread_me != thread_id) {
|
|
||||||
if (try_lock) {
|
|
||||||
SCOPE_PROFILE("try_lock");
|
|
||||||
lock = new GUARD(mtx, try_to_lock);
|
|
||||||
if (lock->owns_lock()) {
|
|
||||||
thread_id = thread_me;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
#if LOCK_PROFILE
|
|
||||||
g_profiler->add("Lock: try_lock fail", 1);
|
|
||||||
#endif
|
|
||||||
//infostream<<"not locked "<<" thread="<<thread_id<<" lock="<<lock<<std::endl;
|
|
||||||
}
|
|
||||||
delete lock;
|
|
||||||
} else {
|
|
||||||
SCOPE_PROFILE("lock");
|
|
||||||
lock = new GUARD(mtx);
|
|
||||||
thread_id = thread_me;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
#if LOCK_PROFILE
|
|
||||||
g_profiler->add("Lock: recursive", 1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
lock = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class GUARD, class MUTEX>
|
|
||||||
recursive_lock<GUARD, MUTEX>::~recursive_lock() {
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class GUARD, class MUTEX>
|
|
||||||
bool recursive_lock<GUARD, MUTEX>::owns_lock() {
|
|
||||||
if (lock)
|
|
||||||
return lock;
|
|
||||||
auto thread_me = std::hash<std::thread::id>()(std::this_thread::get_id());
|
|
||||||
return thread_id == thread_me;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class GUARD, class MUTEX>
|
|
||||||
void recursive_lock<GUARD, MUTEX>::unlock() {
|
|
||||||
if(lock) {
|
|
||||||
thread_id = 0;
|
|
||||||
lock->unlock();
|
|
||||||
delete lock;
|
|
||||||
lock = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class mutex, class unique_lock, class shared_lock>
|
|
||||||
locker<mutex, unique_lock, shared_lock>::locker() {
|
|
||||||
thread_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class mutex, class unique_lock, class shared_lock>
|
|
||||||
std::unique_ptr<unique_lock> locker<mutex, unique_lock, shared_lock>::lock_unique() {
|
|
||||||
return std::make_unique<unique_lock>(mtx);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class mutex, class unique_lock, class shared_lock>
|
|
||||||
std::unique_ptr<unique_lock> locker<mutex, unique_lock, shared_lock>::try_lock_unique() {
|
|
||||||
SCOPE_PROFILE("locker::try_lock_unique");
|
|
||||||
return std::make_unique<unique_lock>(mtx, std::try_to_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class mutex, class unique_lock, class shared_lock>
|
|
||||||
std::unique_ptr<shared_lock> locker<mutex, unique_lock, shared_lock>::lock_shared() const {
|
|
||||||
SCOPE_PROFILE("locker::lock_shared");
|
|
||||||
return std::make_unique<shared_lock>(mtx);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class mutex, class unique_lock, class shared_lock>
|
|
||||||
std::unique_ptr<shared_lock> locker<mutex, unique_lock, shared_lock>::try_lock_shared() {
|
|
||||||
SCOPE_PROFILE("locker::try_lock_shared");
|
|
||||||
return std::make_unique<shared_lock>(mtx, std::try_to_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class mutex, class unique_lock, class shared_lock>
|
|
||||||
std::unique_ptr<recursive_lock<unique_lock, mutex>> locker<mutex, unique_lock, shared_lock>::lock_unique_rec() const {
|
|
||||||
SCOPE_PROFILE("locker::lock_unique_rec");
|
|
||||||
return std::make_unique<lock_rec_unique>(mtx, thread_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class mutex, class unique_lock, class shared_lock>
|
|
||||||
std::unique_ptr<recursive_lock<unique_lock, mutex>> locker<mutex, unique_lock, shared_lock>::try_lock_unique_rec() {
|
|
||||||
SCOPE_PROFILE("locker::try_lock_unique_rec");
|
|
||||||
return std::make_unique<lock_rec_unique>(mtx, thread_id, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class mutex, class unique_lock, class shared_lock>
|
|
||||||
std::unique_ptr<recursive_lock<shared_lock, mutex>> locker<mutex, unique_lock, shared_lock>::lock_shared_rec() const {
|
|
||||||
SCOPE_PROFILE("locker::lock_shared_rec");
|
|
||||||
return std::make_unique<lock_rec_shared>(mtx, thread_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class mutex, class unique_lock, class shared_lock>
|
|
||||||
std::unique_ptr<recursive_lock<shared_lock, mutex>> locker<mutex, unique_lock, shared_lock>::try_lock_shared_rec() {
|
|
||||||
SCOPE_PROFILE("locker::try_lock_shared_rec");
|
|
||||||
return std::make_unique<lock_rec_shared>(mtx, thread_id, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template class recursive_lock<std::unique_lock<use_mutex>>;
|
|
||||||
template class locker<>;
|
|
||||||
#if LOCK_TWO
|
|
||||||
template class recursive_lock<try_shared_lock, try_shared_mutex>;
|
|
||||||
template class recursive_lock<std::unique_lock<try_shared_mutex>, try_shared_mutex>;
|
|
||||||
|
|
||||||
template class locker<try_shared_mutex, std::unique_lock<try_shared_mutex>, std::shared_lock<try_shared_mutex>>;
|
|
||||||
#endif
|
|
|
@ -1,164 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of Freeminer.
|
|
||||||
|
|
||||||
Freeminer is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Freeminer is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <atomic>
|
|
||||||
#include <thread>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "../config.h"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
|
|
||||||
//#include "../threading/mutex.h"
|
|
||||||
using use_mutex = std::mutex;
|
|
||||||
using try_shared_mutex = use_mutex;
|
|
||||||
using try_shared_lock = std::unique_lock<try_shared_mutex>;
|
|
||||||
using unique_lock = std::unique_lock<try_shared_mutex>;
|
|
||||||
const auto try_to_lock = std::try_to_lock;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
typedef std::mutex use_mutex;
|
|
||||||
|
|
||||||
|
|
||||||
#if USE_BOOST // not finished
|
|
||||||
|
|
||||||
//#include <ctime>
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
//#include <boost/thread/locks.hpp>
|
|
||||||
typedef boost::shared_mutex try_shared_mutex;
|
|
||||||
typedef boost::shared_lock<try_shared_mutex> try_shared_lock;
|
|
||||||
typedef boost::unique_lock<try_shared_mutex> unique_lock;
|
|
||||||
const auto try_to_lock = boost::try_to_lock;
|
|
||||||
#define LOCK_TWO 1
|
|
||||||
|
|
||||||
#elif HAVE_SHARED_MUTEX
|
|
||||||
//#elif __cplusplus >= 201305L
|
|
||||||
|
|
||||||
#include <shared_mutex>
|
|
||||||
using try_shared_mutex = std::shared_mutex;
|
|
||||||
using try_shared_lock = std::shared_lock<try_shared_mutex>;
|
|
||||||
using unique_lock = std::unique_lock<try_shared_mutex>;
|
|
||||||
const auto try_to_lock = std::try_to_lock;
|
|
||||||
#define LOCK_TWO 1
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
using try_shared_mutex = use_mutex;
|
|
||||||
using try_shared_lock = std::unique_lock<try_shared_mutex> ;
|
|
||||||
using unique_lock = std::unique_lock<try_shared_mutex> ;
|
|
||||||
const auto try_to_lock = std::try_to_lock;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// http://stackoverflow.com/questions/4792449/c0x-has-no-semaphores-how-to-synchronize-threads
|
|
||||||
/* uncomment when need
|
|
||||||
#include <condition_variable>
|
|
||||||
class semaphore {
|
|
||||||
private:
|
|
||||||
std::mutex mtx;
|
|
||||||
std::condition_variable cv;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
public:
|
|
||||||
semaphore(int count_ = 0):count(count_){;}
|
|
||||||
void notify() {
|
|
||||||
std::unique_lock<std::mutex> lck(mtx);
|
|
||||||
++count;
|
|
||||||
cv.notify_one();
|
|
||||||
}
|
|
||||||
void wait() {
|
|
||||||
std::unique_lock<std::mutex> lck(mtx);
|
|
||||||
while(count == 0){
|
|
||||||
cv.wait(lck);
|
|
||||||
}
|
|
||||||
count--;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
template<class GUARD, class MUTEX = use_mutex>
|
|
||||||
class recursive_lock {
|
|
||||||
public:
|
|
||||||
GUARD * lock;
|
|
||||||
std::atomic<std::size_t> & thread_id;
|
|
||||||
recursive_lock(MUTEX & mtx, std::atomic<std::size_t> & thread_id_, bool try_lock = false);
|
|
||||||
~recursive_lock();
|
|
||||||
bool owns_lock();
|
|
||||||
void unlock();
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class mutex = use_mutex, class unique_lock = std::unique_lock<mutex> , class shared_lock = std::unique_lock<mutex> >
|
|
||||||
class locker {
|
|
||||||
public:
|
|
||||||
using lock_rec_shared = recursive_lock<shared_lock, mutex>;
|
|
||||||
using lock_rec_unique = recursive_lock<unique_lock, mutex>;
|
|
||||||
|
|
||||||
mutable mutex mtx;
|
|
||||||
mutable std::atomic<std::size_t> thread_id;
|
|
||||||
|
|
||||||
locker();
|
|
||||||
std::unique_ptr<unique_lock> lock_unique();
|
|
||||||
std::unique_ptr<unique_lock> try_lock_unique();
|
|
||||||
std::unique_ptr<shared_lock> lock_shared() const;
|
|
||||||
std::unique_ptr<shared_lock> try_lock_shared();
|
|
||||||
std::unique_ptr<lock_rec_unique> lock_unique_rec() const;
|
|
||||||
std::unique_ptr<lock_rec_unique> try_lock_unique_rec();
|
|
||||||
std::unique_ptr<lock_rec_shared> lock_shared_rec() const;
|
|
||||||
std::unique_ptr<lock_rec_shared> try_lock_shared_rec();
|
|
||||||
};
|
|
||||||
|
|
||||||
using shared_locker = locker<try_shared_mutex, unique_lock, try_shared_lock>;
|
|
||||||
|
|
||||||
class dummy_lock {
|
|
||||||
public:
|
|
||||||
~dummy_lock() {}; //no unused variable warning
|
|
||||||
bool owns_lock() {return true;}
|
|
||||||
bool operator!() {return true;}
|
|
||||||
dummy_lock * operator->() {return this; }
|
|
||||||
void unlock() {};
|
|
||||||
};
|
|
||||||
|
|
||||||
class dummy_locker {
|
|
||||||
public:
|
|
||||||
dummy_lock lock_unique() { return {}; };
|
|
||||||
dummy_lock try_lock_unique() { return {}; };
|
|
||||||
dummy_lock lock_shared() { return {}; };
|
|
||||||
dummy_lock try_lock_shared() { return {}; };
|
|
||||||
dummy_lock lock_unique_rec() { return {}; };
|
|
||||||
dummy_lock try_lock_unique_rec() { return {}; };
|
|
||||||
dummy_lock lock_shared_rec() { return {}; };
|
|
||||||
dummy_lock try_lock_shared_rec() { return {}; };
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#if ENABLE_THREADS
|
|
||||||
|
|
||||||
using maybe_locker = locker<>;
|
|
||||||
using maybe_shared_locker = shared_locker;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
using maybe_locker = dummy_locker;
|
|
||||||
using maybe_shared_locker = dummy_locker;
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Add table
Add a link
Reference in a new issue