Commit 21b95ba5 authored by Shu's avatar Shu 🍠
Browse files

Logger, libguarded

parent d53299eb
......@@ -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})
......
......@@ -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
......
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.
\ No newline at end of file
/***********************************************************************
*
* 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
/***********************************************************************
*
* 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
#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"
#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");
}
}
#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);
......
#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;
}