Logger, libguarded
This commit is contained in:
parent
d53299ebc8
commit
21b95ba5fe
|
@ -44,6 +44,7 @@ set(INCLUDE_LIBS
|
|||
"include/toml++"
|
||||
"include/Remotery/lib"
|
||||
"include/robin_hood"
|
||||
"include/libguarded"
|
||||
)
|
||||
|
||||
add_executable(univerxel "src/main.cpp" ${SOURCES} ${INCLUDE_SOURCES})
|
||||
|
|
5
TODO.md
5
TODO.md
|
@ -32,12 +32,9 @@
|
|||
- [ ] sanitizer
|
||||
- [ ] clang-tidy
|
||||
- [ ] cmake
|
||||
- https://github.com/microsoft/GSL/blob/master/include/gsl/pointers
|
||||
- [ ] Server
|
||||
- [ ] ZeroMQ
|
||||
- [ ] Mutex guard
|
||||
- [ ] Shared mutex
|
||||
- [ ] Logger
|
||||
- [x] Logger
|
||||
|
||||
## Rendering
|
||||
- [x] Render triangle
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2016, Ansel Sermersheim
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,198 @@
|
|||
/***********************************************************************
|
||||
*
|
||||
* Copyright (c) 2015-2020 Ansel Sermersheim
|
||||
*
|
||||
* This file is part of CsLibGuarded.
|
||||
*
|
||||
* CsLibGuarded is free software, released under the BSD 2-Clause license.
|
||||
* For license details refer to LICENSE provided with this project.
|
||||
*
|
||||
* CopperSpice 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.
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-2-Clause
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef CSLIBGUARDED_PLAIN_GUARDED_H
|
||||
#define CSLIBGUARDED_PLAIN_GUARDED_H
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
namespace libguarded
|
||||
{
|
||||
|
||||
/**
|
||||
\headerfile cs_plain_guarded.h <CsLibGuarded/cs_plain_guarded.h>
|
||||
|
||||
This templated class wraps an object and allows only one thread at a
|
||||
time to access the protected object.
|
||||
|
||||
This class will use std::mutex for the internal locking mechanism by
|
||||
default. Other classes which are useful for the mutex type are
|
||||
std::recursive_mutex, std::timed_mutex, and
|
||||
std::recursive_timed_mutex.
|
||||
|
||||
The handle returned by the various lock methods is moveable but not
|
||||
copyable.
|
||||
*/
|
||||
template <typename T, typename M = std::mutex>
|
||||
class plain_guarded
|
||||
{
|
||||
private:
|
||||
class deleter;
|
||||
|
||||
public:
|
||||
using handle = std::unique_ptr<T, deleter>;
|
||||
|
||||
/**
|
||||
Construct a guarded object. This constructor will accept any
|
||||
number of parameters, all of which are forwarded to the
|
||||
constructor of T.
|
||||
*/
|
||||
template <typename... Us>
|
||||
plain_guarded(Us &&... data);
|
||||
|
||||
/**
|
||||
Acquire a handle to the protected object. As a side effect, the
|
||||
protected object will be locked from access by any other
|
||||
thread. The lock will be automatically released when the handle
|
||||
is destroyed.
|
||||
*/
|
||||
[[nodiscard]] handle lock();
|
||||
|
||||
/**
|
||||
Attempt to acquire a handle to the protected object. Returns a
|
||||
null handle if the object is already locked. As a side effect,
|
||||
the protected object will be locked from access by any other
|
||||
thread. The lock will be automatically released when the handle
|
||||
is destroyed.
|
||||
*/
|
||||
[[nodiscard]] handle try_lock();
|
||||
|
||||
/**
|
||||
Attempt to acquire a handle to the protected object. As a side
|
||||
effect, the protected object will be locked from access by any
|
||||
other thread. The lock will be automatically released when the
|
||||
handle is destroyed.
|
||||
|
||||
Returns a null handle if the object is already locked, and does
|
||||
not become available for locking before the time duration has
|
||||
elapsed.
|
||||
|
||||
Calling this method requires that the underlying mutex type M
|
||||
supports the try_lock_for method. This is not true if M is the
|
||||
default std::mutex.
|
||||
*/
|
||||
template <class Duration>
|
||||
[[nodiscard]] handle try_lock_for(const Duration &duration);
|
||||
|
||||
/**
|
||||
Attempt to acquire a handle to the protected object. As a side
|
||||
effect, the protected object will be locked from access by any other
|
||||
thread. The lock will be automatically released when the handle is
|
||||
destroyed.
|
||||
|
||||
Returns a null handle if the object is already locked, and does not
|
||||
become available for locking before reaching the specified timepoint.
|
||||
|
||||
Calling this method requires that the underlying mutex type M
|
||||
supports the try_lock_until method. This is not true if M is the
|
||||
default std::mutex.
|
||||
*/
|
||||
template <class TimePoint>
|
||||
[[nodiscard]] handle try_lock_until(const TimePoint &timepoint);
|
||||
|
||||
private:
|
||||
T m_obj;
|
||||
M m_mutex;
|
||||
};
|
||||
|
||||
template <typename T, typename M>
|
||||
class plain_guarded<T, M>::deleter
|
||||
{
|
||||
public:
|
||||
using pointer = T *;
|
||||
|
||||
deleter(std::unique_lock<M> lock);
|
||||
|
||||
void operator()(T *ptr);
|
||||
|
||||
private:
|
||||
std::unique_lock<M> m_lock;
|
||||
};
|
||||
|
||||
template <typename T, typename M>
|
||||
plain_guarded<T, M>::deleter::deleter(std::unique_lock<M> lock)
|
||||
: m_lock(std::move(lock))
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T, typename M>
|
||||
void plain_guarded<T, M>::deleter::operator()(T *)
|
||||
{
|
||||
if (m_lock.owns_lock()) {
|
||||
m_lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename M>
|
||||
template <typename... Us>
|
||||
plain_guarded<T, M>::plain_guarded(Us &&... data)
|
||||
: m_obj(std::forward<Us>(data)...)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T, typename M>
|
||||
auto plain_guarded<T, M>::lock() -> handle
|
||||
{
|
||||
std::unique_lock<M> lock(m_mutex);
|
||||
return handle(&m_obj, deleter(std::move(lock)));
|
||||
}
|
||||
|
||||
template <typename T, typename M>
|
||||
auto plain_guarded<T, M>::try_lock() -> handle
|
||||
{
|
||||
std::unique_lock<M> lock(m_mutex, std::try_to_lock);
|
||||
|
||||
if (lock.owns_lock()) {
|
||||
return handle(&m_obj, deleter(std::move(lock)));
|
||||
} else {
|
||||
return handle(nullptr, deleter(std::move(lock)));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename M>
|
||||
template <typename Duration>
|
||||
auto plain_guarded<T, M>::try_lock_for(const Duration &d) -> handle
|
||||
{
|
||||
std::unique_lock<M> lock(m_mutex, d);
|
||||
|
||||
if (lock.owns_lock()) {
|
||||
return handle(&m_obj, deleter(std::move(lock)));
|
||||
} else {
|
||||
return handle(nullptr, deleter(std::move(lock)));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename M>
|
||||
template <typename TimePoint>
|
||||
auto plain_guarded<T, M>::try_lock_until(const TimePoint &tp) -> handle
|
||||
{
|
||||
std::unique_lock<M> lock(m_mutex, tp);
|
||||
|
||||
if (lock.owns_lock()) {
|
||||
return handle(&m_obj, deleter(std::move(lock)));
|
||||
} else {
|
||||
return handle(nullptr, deleter(std::move(lock)));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename M = std::mutex>
|
||||
using guarded [[deprecated("renamed to plain_guarded")]] = plain_guarded<T, M>;
|
||||
|
||||
} // namespace libguarded
|
||||
|
||||
#endif
|
|
@ -0,0 +1,234 @@
|
|||
/***********************************************************************
|
||||
*
|
||||
* Copyright (c) 2015-2020 Ansel Sermersheim
|
||||
*
|
||||
* This file is part of CsLibGuarded.
|
||||
*
|
||||
* CsLibGuarded is free software, released under the BSD 2-Clause license.
|
||||
* For license details refer to LICENSE provided with this project.
|
||||
*
|
||||
* CopperSpice 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.
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-2-Clause
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef CSLIBGUARDED_SHARED_GUARDED_H
|
||||
#define CSLIBGUARDED_SHARED_GUARDED_H
|
||||
|
||||
#include <memory>
|
||||
#include <shared_mutex>
|
||||
|
||||
namespace libguarded
|
||||
{
|
||||
|
||||
/**
|
||||
\headerfile cs_shared_guarded.h <CsLibGuarded/cs_shared_guarded.h>
|
||||
|
||||
This templated class wraps an object and allows only one thread at
|
||||
a time to modify the protected object.
|
||||
|
||||
This class will use std::shared_timed_mutex for the internal
|
||||
locking mechanism by default. In C++17 the std::shared_mutex class
|
||||
is also available.
|
||||
|
||||
The handle returned by the various lock methods is moveable but not
|
||||
copyable.
|
||||
*/
|
||||
template <typename T, typename M = std::shared_timed_mutex, typename L = std::shared_lock<M>>
|
||||
class shared_guarded
|
||||
{
|
||||
private:
|
||||
class deleter;
|
||||
class shared_deleter;
|
||||
|
||||
public:
|
||||
using handle = std::unique_ptr<T, deleter>;
|
||||
using shared_handle = std::unique_ptr<const T, shared_deleter>;
|
||||
|
||||
template <typename... Us>
|
||||
shared_guarded(Us &&... data);
|
||||
|
||||
// exclusive access
|
||||
[[nodiscard]] handle lock();
|
||||
[[nodiscard]] handle try_lock();
|
||||
|
||||
template <class Duration>
|
||||
[[nodiscard]] handle try_lock_for(const Duration &duration);
|
||||
|
||||
template <class TimePoint>
|
||||
[[nodiscard]] handle try_lock_until(const TimePoint &timepoint);
|
||||
|
||||
// shared access, note "shared" in method names
|
||||
[[nodiscard]] shared_handle lock_shared() const;
|
||||
[[nodiscard]] shared_handle try_lock_shared() const;
|
||||
|
||||
template <class Duration>
|
||||
[[nodiscard]] shared_handle try_lock_shared_for(const Duration &duration) const;
|
||||
|
||||
template <class TimePoint>
|
||||
[[nodiscard]] shared_handle try_lock_shared_until(const TimePoint &timepoint) const;
|
||||
|
||||
private:
|
||||
T m_obj;
|
||||
mutable M m_mutex;
|
||||
};
|
||||
|
||||
template <typename T, typename M, typename L>
|
||||
class shared_guarded<T, M, L>::deleter
|
||||
{
|
||||
public:
|
||||
using pointer = T *;
|
||||
|
||||
deleter(std::unique_lock<M> lock);
|
||||
|
||||
void operator()(T *ptr);
|
||||
|
||||
private:
|
||||
std::unique_lock<M> m_lock;
|
||||
};
|
||||
|
||||
template <typename T, typename M, typename L>
|
||||
shared_guarded<T, M, L>::deleter::deleter(std::unique_lock<M> lock)
|
||||
: m_lock(std::move(lock))
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T, typename M, typename L>
|
||||
void shared_guarded<T, M, L>::deleter::operator()(T *)
|
||||
{
|
||||
if (m_lock.owns_lock()) {
|
||||
m_lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename M, typename L>
|
||||
class shared_guarded<T, M, L>::shared_deleter
|
||||
{
|
||||
public:
|
||||
using pointer = const T *;
|
||||
|
||||
shared_deleter(L lock);
|
||||
|
||||
void operator()(const T *ptr);
|
||||
|
||||
private:
|
||||
L m_lock;
|
||||
};
|
||||
|
||||
template <typename T, typename M, typename L>
|
||||
shared_guarded<T, M, L>::shared_deleter::shared_deleter(L lock)
|
||||
: m_lock(std::move(lock))
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T, typename M, typename L>
|
||||
void shared_guarded<T, M, L>::shared_deleter::operator()(const T *)
|
||||
{
|
||||
if (m_lock.owns_lock()) {
|
||||
m_lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename M, typename L>
|
||||
template <typename... Us>
|
||||
shared_guarded<T, M, L>::shared_guarded(Us &&... data)
|
||||
: m_obj(std::forward<Us>(data)...)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T, typename M, typename L>
|
||||
auto shared_guarded<T, M, L>::lock() -> handle
|
||||
{
|
||||
std::unique_lock<M> lock(m_mutex);
|
||||
return handle(&m_obj, deleter(std::move(lock)));
|
||||
}
|
||||
|
||||
template <typename T, typename M, typename L>
|
||||
auto shared_guarded<T, M, L>::try_lock() -> handle
|
||||
{
|
||||
std::unique_lock<M> lock(m_mutex, std::try_to_lock);
|
||||
|
||||
if (lock.owns_lock()) {
|
||||
return handle(&m_obj, deleter(std::move(lock)));
|
||||
} else {
|
||||
return handle(nullptr, deleter(std::move(lock)));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename M, typename L>
|
||||
template <typename Duration>
|
||||
auto shared_guarded<T, M, L>::try_lock_for(const Duration &duration) -> handle
|
||||
{
|
||||
std::unique_lock<M> lock(m_mutex, duration);
|
||||
|
||||
if (lock.owns_lock()) {
|
||||
return handle(&m_obj, deleter(std::move(lock)));
|
||||
} else {
|
||||
return handle(nullptr, deleter(std::move(lock)));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename M, typename L>
|
||||
template <typename TimePoint>
|
||||
auto shared_guarded<T, M, L>::try_lock_until(const TimePoint &timepoint) -> handle
|
||||
{
|
||||
std::unique_lock<M> lock(m_mutex, timepoint);
|
||||
|
||||
if (lock.owns_lock()) {
|
||||
return handle(&m_obj, deleter(std::move(lock)));
|
||||
} else {
|
||||
return handle(nullptr, deleter(std::move(lock)));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename M, typename L>
|
||||
auto shared_guarded<T, M, L>::lock_shared() const -> shared_handle
|
||||
{
|
||||
L lock(m_mutex);
|
||||
return shared_handle(&m_obj, shared_deleter(std::move(lock)));
|
||||
}
|
||||
|
||||
template <typename T, typename M, typename L>
|
||||
auto shared_guarded<T, M, L>::try_lock_shared() const -> shared_handle
|
||||
{
|
||||
L lock(m_mutex, std::try_to_lock);
|
||||
|
||||
if (lock.owns_lock()) {
|
||||
return shared_handle(&m_obj, shared_deleter(std::move(lock)));
|
||||
} else {
|
||||
return shared_handle(nullptr, shared_deleter(std::move(lock)));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename M, typename L>
|
||||
template <typename Duration>
|
||||
auto shared_guarded<T, M, L>::try_lock_shared_for(const Duration &d) const -> shared_handle
|
||||
{
|
||||
L lock(m_mutex, d);
|
||||
|
||||
if (lock.owns_lock()) {
|
||||
return shared_handle(&m_obj, shared_deleter(std::move(lock)));
|
||||
} else {
|
||||
return shared_handle(nullptr, shared_deleter(std::move(lock)));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename M, typename L>
|
||||
template <typename TimePoint>
|
||||
auto shared_guarded<T, M, L>::try_lock_shared_until(const TimePoint &tp) const -> shared_handle
|
||||
{
|
||||
L lock(m_mutex, tp);
|
||||
|
||||
if (lock.owns_lock()) {
|
||||
return shared_handle(&m_obj, shared_deleter(std::move(lock)));
|
||||
} else {
|
||||
return shared_handle(nullptr, shared_deleter(std::move(lock)));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace libguarded
|
||||
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
#define GREY "\033[0;90m"
|
||||
#define GREEN "\033[0;32m"
|
||||
#define BROWN "\033[0;33m"
|
||||
#define BLUE "\033[0;34m"
|
||||
#define RED "\033[1;31m"
|
||||
#define YELLOW "\033[1;33m"
|
||||
#define BOLD "\033[1;1m"
|
||||
#define BLUE_BOLD "\033[1;34m"
|
||||
#define END_COLOR "\033[0m"
|
||||
#define UNDERLINE "\e[4m"
|
||||
#define END_STYLE "\e[0m"
|
|
@ -0,0 +1,11 @@
|
|||
#include "logger.hpp"
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
|
||||
namespace logger {
|
||||
std::_Put_time<char> now() {
|
||||
const auto tp = std::chrono::system_clock::now();
|
||||
const auto timet = std::chrono::system_clock::to_time_t(tp);
|
||||
return std::put_time(std::localtime(&timet), "%Y-%m-%d %X");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "colors.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
#define _OUT(expr) {std::ostringstream oss; oss << expr << std::endl; std::cout << oss.str();}
|
||||
#define LOG(expr) _OUT("[" << logger::now() << "] " << expr)
|
||||
#define LOG_E(expr) _OUT("[" << RED << logger::now() << END_COLOR << "] " << expr)
|
||||
#define LOG_W(expr) _OUT("[" << YELLOW << logger::now() << END_COLOR << "] " << expr)
|
||||
#define LOG_I(expr) _OUT("[" << GREEN << logger::now() << END_COLOR << "] " << expr)
|
||||
#define LOG_D(expr) _OUT("[" << GREY << logger::now() << END_COLOR << "] " << expr)
|
||||
|
||||
namespace logger {
|
||||
std::_Put_time<char> now();
|
||||
}
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
/// Entry point
|
||||
int main(int, char *[]){
|
||||
LOG("Univerxel");
|
||||
options options;
|
||||
state state;
|
||||
reports reports;
|
||||
|
@ -77,7 +78,7 @@ int main(int, char *[]){
|
|||
rmt_CreateGlobalInstance(&rmt);
|
||||
rmt_BindOpenGL();
|
||||
#if RMT_ENABLED
|
||||
std::cout << "Profiling !" << std::endl;
|
||||
LOG("Profiling !");
|
||||
#endif
|
||||
|
||||
world::Universe world = world::Universe(options.world);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "ShortIndexed.hpp"
|
||||
|
||||
#include "vboindexer.hpp"
|
||||
#include "../../data/logger.hpp"
|
||||
|
||||
using namespace buffer;
|
||||
|
||||
|
@ -95,7 +96,7 @@ void ShortIndexed::setData(const ShortIndexed::Data& data) {
|
|||
|
||||
IndexSize = data.indices.size();
|
||||
if(IndexSize != data.indices.size()) {
|
||||
std::cout << "ShortBuffer overflow: " << data.indices.size() << std::endl;
|
||||
LOG_E("ShortBuffer overflow: " << data.indices.size());
|
||||
}
|
||||
setIndicies(IndexSize * sizeof(GLushort), &data.indices[0]);
|
||||
setVertices(data.vertices.size() * sizeof(glm::vec3), &data.vertices[0]);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
using namespace world;
|
||||
|
||||
Universe::Universe(const Universe::options &options): generator(42), regionDict("content/zstd.dict"), contouring(std::make_shared<contouring::Dummy>()) {
|
||||
Universe::Universe(const Universe::options &options): generator(42), dicts("content/zstd.dict"), contouring(std::make_shared<contouring::Dummy>()) {
|
||||
setOptions(options);
|
||||
folderPath = options.folderPath;
|
||||
struct vec_istream: std::streambuf {
|
||||
|
@ -22,7 +22,7 @@ Universe::Universe(const Universe::options &options): generator(42), regionDict(
|
|||
// Load workers
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
loadWorkers.emplace_back([&] {
|
||||
const auto ctx = regionDict.make_reader();
|
||||
const auto ctx = dicts.make_reader();
|
||||
while (running) {
|
||||
chunk_pos pos;
|
||||
loadQueue.wait();
|
||||
|
@ -50,7 +50,7 @@ Universe::Universe(const Universe::options &options): generator(42), regionDict(
|
|||
// Save workers
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
saveWorkers.emplace_back([&] {
|
||||
const auto ctx = regionDict.make_writer();
|
||||
const auto ctx = dicts.make_writer();
|
||||
while (running) {
|
||||
robin_hood::pair<chunk_pos, std::shared_ptr<Chunk>> task;
|
||||
saveQueue.wait();
|
||||
|
@ -100,16 +100,16 @@ Universe::~Universe() {
|
|||
}
|
||||
|
||||
std::shared_ptr<Region> Universe::getRegion(const region_pos& pos) {
|
||||
std::shared_lock lock(regionMutex);
|
||||
const auto it = regionCache.find(pos);
|
||||
if(it == regionCache.end()) {
|
||||
lock.unlock();
|
||||
const auto reg = std::make_shared<Region>(folderPath, pos);
|
||||
std::unique_lock u_lock(regionMutex);
|
||||
return regionCache.insert({pos, reg}).first->second;
|
||||
} else {
|
||||
return it->second;
|
||||
{ // Found
|
||||
const auto shared = regions.lock_shared();
|
||||
const auto it = shared->find(pos);
|
||||
if(it != shared->end())
|
||||
return it->second;
|
||||
}
|
||||
// Reading
|
||||
const auto reg = std::make_shared<Region>(folderPath, pos);
|
||||
const auto unique = regions.lock();
|
||||
return unique->insert({pos, reg}).first->second;
|
||||
}
|
||||
|
||||
void Universe::update(const camera_pos& pos, Universe::report& rep) {
|
||||
|
@ -174,18 +174,17 @@ void Universe::update(const camera_pos& pos, Universe::report& rep) {
|
|||
|
||||
{
|
||||
rmt_ScopedCPUSample(Region, 0);
|
||||
std::unique_lock lock(regionMutex);
|
||||
const auto unique = regions.lock(); // MAYBE: shared then unique
|
||||
rep.region_count.push(unique->size());
|
||||
const auto me = glm::divide(last_pos, glm::ivec3(REGION_LENGTH));
|
||||
for (auto it = regionCache.begin(); it != regionCache.end();) {
|
||||
for (auto it = unique->begin(); it != unique->end(); it++) {
|
||||
if (glm::length2(it->first - me) > keepDistance) {
|
||||
std::cout << "rem" << std::endl;
|
||||
it = regionCache.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
LOG_D("Remove region");
|
||||
unique->erase(it);
|
||||
break; //NOTE: save one max per frame
|
||||
}
|
||||
}
|
||||
}
|
||||
rep.region_count.push(regionCache.size());
|
||||
}
|
||||
void Universe::setOptions(const Universe::options& options) {
|
||||
loadDistance = options.loadDistance;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <shared_mutex>
|
||||
#include <shared_mutex_guarded.h>
|
||||
using namespace libguarded;
|
||||
#include "../data/math.hpp"
|
||||
#include "../data/safe_queue.hpp"
|
||||
#include "../data/safe_priority_queue.hpp"
|
||||
|
@ -98,9 +98,8 @@ namespace world {
|
|||
int keepDistance;
|
||||
std::string folderPath;
|
||||
|
||||
std::shared_mutex regionMutex; //MAYBE: shared_guard
|
||||
robin_hood::unordered_map<region_pos, std::shared_ptr<Region>> regionCache;
|
||||
dict_set regionDict;
|
||||
shared_guarded<robin_hood::unordered_map<region_pos, std::shared_ptr<Region>>> regions;
|
||||
dict_set dicts;
|
||||
std::shared_ptr<Region> getRegion(const region_pos &);
|
||||
|
||||
/// Contouring worker
|
||||
|
|
|
@ -45,14 +45,14 @@ void FileRegion::load() {
|
|||
|
||||
// Ignore content
|
||||
if(!index.insert({pos, std::make_pair(size, file.tellg())}).second) {
|
||||
std::cout << "Duplicated chunk: " << path << ":" << (int)pos.x << "." << (int)pos.y << "." << (int)pos.z << std::endl;
|
||||
LOG_E("Duplicated chunk: " << path << ":" << (int)pos.x << "." << (int)pos.y << "." << (int)pos.z);
|
||||
}
|
||||
file.ignore(size);
|
||||
file.peek();
|
||||
}
|
||||
|
||||
if(file.bad()) {
|
||||
std::cout << "region corrupted read " << path << std::endl;
|
||||
LOG_E("region corrupted read " << path);
|
||||
}
|
||||
|
||||
assert(index.size() == chunkCount);
|
||||
|
@ -73,10 +73,10 @@ bool FileRegion::read(const region_chunk_pos& pos, const read_ctx& ctx, data& ou
|
|||
out.resize(maxSize);
|
||||
const auto actualSize = ZSTD_decompress_usingDDict(ctx.ctx, out.data(), out.size(), in->data(), in->size(), ctx.dict);
|
||||
if(ZSTD_isError(actualSize)) {
|
||||
std::cout << "Corrupted region chunk: " << path << ":" << (int)pos.x << "." << (int)pos.y << "." << (int)pos.z << " "
|
||||
<< ZSTD_getErrorName(actualSize) << std::endl;
|
||||
LOG_E("Corrupted region chunk: " << path << ":" << (int)pos.x << "." << (int)pos.y << "." << (int)pos.z << " "
|
||||
<< ZSTD_getErrorName(actualSize));
|
||||
#ifdef REMOVE_CORRUPTED
|
||||
std::cout << "Removing" << std::endl;
|
||||
LOG_W("Removing");
|
||||
index.erase(it);
|
||||
lock.unlock();
|
||||
save(std::nullopt);
|
||||
|
@ -93,8 +93,8 @@ void FileRegion::write(const region_chunk_pos& pos, const write_ctx& ctx, const
|
|||
|
||||
const auto actualSize = ZSTD_compress_usingCDict(ctx.ctx, buffer->data(), buffer->capacity(), in.data(), in.size(), ctx.dict);
|
||||
if (ZSTD_isError(actualSize)) {
|
||||
std::cout << "Corrupted chunk save: " << path << ":" << (int)pos.x << "." << (int)pos.y << "." << (int)pos.z << " "
|
||||
<< ZSTD_getErrorName(actualSize) << std::endl;
|
||||
LOG_E("Corrupted chunk save: " << path << ":" << (int)pos.x << "." << (int)pos.y << "." << (int)pos.z << " "
|
||||
<< ZSTD_getErrorName(actualSize));
|
||||
return;
|
||||
}
|
||||
buffer->resize(actualSize);
|
||||
|
@ -108,7 +108,7 @@ void FileRegion::save(std::optional<std::pair<region_chunk_pos, std::unique_ptr<
|
|||
|
||||
std::ofstream tmpFile(tmpPath, std::ios::out | std::ios::binary);
|
||||
if (!tmpFile.good()) {
|
||||
std::cout << "Corrupted region path: " << tmpPath << std::endl;
|
||||
LOG_E("Corrupted region path: " << tmpPath);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ void FileRegion::save(std::optional<std::pair<region_chunk_pos, std::unique_ptr<
|
|||
}
|
||||
|
||||
if (!tmpFile.good()) {
|
||||
std::cout << "region corrupted write " << tmpPath << std::endl;
|
||||
LOG_E("Region corrupted write " << tmpPath);
|
||||
tmpFile.close();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -57,13 +57,13 @@ void MemoryRegion::load() {
|
|||
data->resize(size);
|
||||
file.read(data->data(), data->size());
|
||||
if(!content.insert({pos, data}).second) {
|
||||
std::cout << "Duplicated chunk: " << path << ":" << (int)pos.x << "." << (int)pos.y << "." << (int)pos.z << std::endl;
|
||||
LOG_E("Duplicated chunk: " << path << ":" << (int)pos.x << "." << (int)pos.y << "." << (int)pos.z);
|
||||
}
|
||||
file.peek();
|
||||
}
|
||||
|
||||
if(file.bad()) {
|
||||
std::cout << "region corrupted read " << path << std::endl;
|
||||
LOG_E("Region corrupted read " << path);
|
||||
}
|
||||
assert(content.size() == chunkCount);
|
||||
file.close();
|
||||
|
@ -81,10 +81,10 @@ bool MemoryRegion::read(const region_chunk_pos& pos, const read_ctx& ctx, data&
|
|||
out.resize(maxSize);
|
||||
const auto actualSize = ZSTD_decompress_usingDDict(ctx.ctx, out.data(), out.size(), in->data(), in->size(), ctx.dict);
|
||||
if(ZSTD_isError(actualSize)) {
|
||||
std::cout << "Corrupted region chunk: " << path << ":" << (int)pos.x << "." << (int)pos.y << "." << (int)pos.z << " "
|
||||
<< ZSTD_getErrorName(actualSize) << std::endl;
|
||||
LOG_E("Corrupted region chunk: " << path << ":" << (int)pos.x << "." << (int)pos.y << "." << (int)pos.z << " "
|
||||
<< ZSTD_getErrorName(actualSize));
|
||||
#ifdef REMOVE_CORRUPTED
|
||||
std::cout << "Removing" << std::endl;
|
||||
LOG_W("Removing");
|
||||
lock.unlock();
|
||||
{
|
||||
std::unique_lock ulock(mutex);
|
||||
|
@ -104,8 +104,8 @@ void MemoryRegion::write(const region_chunk_pos& pos, const write_ctx& ctx, cons
|
|||
|
||||
const auto actualSize = ZSTD_compress_usingCDict(ctx.ctx, buffer->data(), buffer->capacity(), in.data(), in.size(), ctx.dict);
|
||||
if (ZSTD_isError(actualSize)) {
|
||||
std::cout << "Corrupted chunk save: " << path << ":" << (int)pos.x << "." << (int)pos.y << "." << (int)pos.z << " "
|
||||
<< ZSTD_getErrorName(actualSize) << std::endl;
|
||||
LOG_E("Corrupted chunk save: " << path << ":" << (int)pos.x << "." << (int)pos.y << "." << (int)pos.z << " "
|
||||
<< ZSTD_getErrorName(actualSize));
|
||||
return;
|
||||
}
|
||||
buffer->resize(actualSize);
|
||||
|
@ -134,7 +134,7 @@ void MemoryRegion::save(bool force) {
|
|||
|
||||
std::ofstream file(path, std::ios::out | std::ios::binary);
|
||||
if (!file.good()) {
|
||||
std::cout << "Corrupted region path: " << path << std::endl;
|
||||
LOG_E("Corrupted region path: " << path);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -169,7 +169,7 @@ void MemoryRegion::save(bool force) {
|
|||
}
|
||||
|
||||
if (!file.good()) {
|
||||
std::cout << "region corrupted write " << path << std::endl;
|
||||
LOG_E("Region corrupted write " << path);
|
||||
file.close();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <zstd.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include "../../data/logger.hpp"
|
||||
|
||||
namespace world {
|
||||
struct read_ctx {
|
||||
|
@ -27,7 +27,7 @@ namespace world {
|
|||
dict_set(const std::string& path) {
|
||||
std::ifstream is(path, std::ios::in | std::ios::binary | std::ios::ate);
|
||||
if(!is.good()) {
|
||||
std::cout << "missing dict " << path << std::endl;
|
||||
LOG_E("Missing dict " << path);
|
||||
exit(1);
|
||||
}
|
||||
const auto end = is.tellg();
|
||||
|
|
Loading…
Reference in New Issue