user-gcc/src/env_base.cpp

126 lines
3.6 KiB
C++

/* Copyright 2020, Michele Santullo
* This file is part of user-gcc.
*
* User-gcc 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.
*
* User-gcc 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 user-gcc. If not, see <http://www.gnu.org/licenses/>.
*/
#include "env_base.hpp"
#include "string_view_cat.hpp"
#include "safe_print.hpp"
#include <stdexcept>
#include <type_traits>
namespace duck {
namespace {
template <typename F, typename R=decltype(std::declval<F>()())>
R call_noexcept (F func, std::string_view err_location) noexcept {
typedef R return_type;
try {
return func();
}
catch (const std::runtime_error& err) {
safe_print_error("Unexpected exception in ");
safe_print_error(err_location);
safe_print_error(": ");
safe_print_error_ln(err.what());
}
catch (...) {
safe_print_error("Unknown exception in ");
safe_print_error_ln(err_location);
}
if constexpr (not std::is_same<void, return_type>::value)
return return_type{};
}
} //unnamed namespace
class StdMutex : public EnvBase::Mutex {
public:
StdMutex (std::mutex& m) noexcept :
m_mutex(m)
{
}
virtual void lock() override { m_mutex.lock(); }
virtual void try_lock() override {m_mutex.try_lock(); }
virtual void unlock() noexcept override {m_mutex.unlock(); }
private:
std::mutex& m_mutex;
};
class EmptyMutex : public EnvBase::Mutex {
public:
EmptyMutex() noexcept = default;
virtual void lock() override { }
virtual void try_lock() override { }
virtual void unlock() noexcept override { }
};
bool EnvBase::empty() const noexcept {
return 0 == this->size();
}
std::string_view EnvBase::operator[] (std::string_view name) const noexcept {
return this->get(name, "");
}
detail::EnvVarProxy<std::string_view> EnvBase::operator[] (std::string_view name) noexcept {
return {name, this};
}
detail::EnvVarProxy<std::string> EnvBase::operator[] (std::string&& name) noexcept {
return {std::move(name), this};
}
detail::EnvVarProxy<std::string> EnvBase::operator[] (const std::string& name) noexcept {
return {to_string(name), this};
}
void EnvBase::set (std::string_view name, std::string_view value) {
StdMutex m(this->mutex());
this->set_implem(name, value, m);
}
void EnvBase::unset (std::string_view name) noexcept {
StdMutex m(this->mutex());
call_noexcept([&,this](){this->unset_implem(name, m);}, to_string_view(__func__));
}
bool EnvBase::is_set (std::string_view name) const noexcept {
StdMutex m(this->mutex());
return call_noexcept([&,this](){return this->is_set_implem(name, m);}, to_string_view(__func__));
}
auto EnvBase::size() const noexcept -> size_type {
StdMutex m(this->mutex());
return call_noexcept([this,&m](){return this->size_implem(m);}, to_string_view(__func__));
}
void EnvBase::set_nolock (EnvBase& obj, std::string_view name, std::string_view value) {
EmptyMutex m;
obj.set_implem(name, value, m);
}
void EnvBase::clear() noexcept {
StdMutex m(this->mutex());
call_noexcept([this,&m](){this->clear_implem(m);}, to_string_view(__func__));
return;
}
void EnvBase::clear_nolock (EnvBase& obj) noexcept {
EmptyMutex m;
call_noexcept([&](){obj.clear_implem(m);}, to_string_view(__func__));
return;
}
} //namespace duck