61 lines
1.6 KiB
C++
61 lines
1.6 KiB
C++
#pragma once
|
|
#include <atomic>
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <type_traits>
|
|
#include <unordered_map>
|
|
#include <variant>
|
|
#include <vector>
|
|
|
|
namespace vptyp {
|
|
|
|
static constexpr std::string_view configErrorMsg =
|
|
"Bruh, incorrect configuration";
|
|
|
|
class Logger {
|
|
// helper class for handling worker thread
|
|
class Worker;
|
|
|
|
using map_type =
|
|
std::unordered_map<std::string, std::variant<int64_t, double>>;
|
|
|
|
public:
|
|
virtual ~Logger();
|
|
|
|
Logger();
|
|
explicit Logger(std::ostream& out);
|
|
Logger(Logger&) = delete;
|
|
Logger(Logger&&) = delete;
|
|
Logger& operator=(Logger&) = delete;
|
|
Logger& operator=(Logger&&) = delete;
|
|
|
|
/// @return success or not (already configured)
|
|
bool configure(const std::vector<std::string>& d);
|
|
|
|
template <typename Metric,
|
|
typename = std::enable_if_t<std::is_arithmetic_v<Metric>>>
|
|
void add(const std::string& field, Metric metric) {
|
|
refs.fetch_add(1, std::memory_order_release);
|
|
map_type* locked = active.load(std::memory_order_acquire);
|
|
auto it = locked->find(field);
|
|
if (it == locked->end()) {
|
|
throw configErrorMsg; // additional 30ns on bench ?
|
|
}
|
|
it->second = metric;
|
|
refs.fetch_sub(1, std::memory_order_release);
|
|
}
|
|
|
|
bool isConfigured() { return configured == CONFIGURED; }
|
|
|
|
private:
|
|
friend Worker;
|
|
enum Configuration { NOT_CONFIGURED, CONFIG_IN_PROGRESS, CONFIGURED };
|
|
std::atomic<int> configured{NOT_CONFIGURED};
|
|
std::unique_ptr<Worker> worker;
|
|
std::unique_ptr<map_type> m1, m2;
|
|
std::atomic<map_type*> active; // impl may use mutex!
|
|
std::atomic<size_t> refs{0};
|
|
};
|
|
|
|
} // namespace vptyp
|