Commit 079f6372 authored by Dominik Charousset's avatar Dominik Charousset

Use RW lock for AID instead of __thread variable

Store actor IDs in an unordered map protected via RW lock instead of using a
non-portable `__thread` variable. Though this is less efficient, the
performance overhead is still negligible compared to the overall cost of
enabling logging in the first place. Close #258; a more generic
`thread_specific_ptr` implementation turned out have too much implementation
overhead to be worth the effort.
parent d6dae07b
......@@ -20,10 +20,12 @@
#ifndef CAF_LOGGING_HPP
#define CAF_LOGGING_HPP
#include <thread>
#include <cstring>
#include <sstream>
#include <iostream>
#include <type_traits>
#include <unordered_map>
#include "caf/config.hpp"
#include "caf/to_string.hpp"
......@@ -31,6 +33,7 @@
#include "caf/detail/singletons.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/detail/shared_spinlock.hpp"
/*
* To enable logging, you have to define CAF_DEBUG. This enables
......@@ -51,40 +54,35 @@ namespace detail {
class singletons;
class logging {
public:
friend class detail::singletons;
public:
// returns the actor ID for the current thread or 0 if none is assigned
actor_id get_aid();
// associates given actor id with this thread,
// returns the previously set actor id
actor_id set_aid(actor_id aid);
virtual void log(const char* level, const char* class_name,
const char* function_name, const char* file_name,
int line_num, const std::string& msg) = 0;
const char* function_name, const char* file_name,
int line_num, const std::string& msg) = 0;
class trace_helper {
public:
trace_helper(std::string class_name, const char* fun_name,
const char* file_name, int line_num,
const std::string& msg);
const char* file_name, int line_num, const std::string& msg);
~trace_helper();
private:
std::string m_class;
const char* m_fun_name;
const char* m_file_name;
int m_line_num;
};
protected:
virtual ~logging();
static logging* create_singleton();
......@@ -93,20 +91,29 @@ class logging {
virtual void stop() = 0;
inline void dispose() { delete this; }
inline void dispose() {
delete this;
}
private:
detail::shared_spinlock m_aids_lock;
std::unordered_map<std::thread::id, actor_id> m_aids;
};
struct oss_wr {
inline oss_wr() {
// nop
}
inline oss_wr() { }
inline oss_wr(oss_wr&& other) : m_str(std::move(other.m_str)) {}
inline oss_wr(oss_wr&& other) : m_str(std::move(other.m_str)) {
// nop
}
std::string m_str;
inline std::string str() { return std::move(m_str); }
inline std::string str() {
return std::move(m_str);
}
};
inline oss_wr operator<<(oss_wr&& lhs, std::string str) {
......
......@@ -50,8 +50,6 @@ namespace detail {
namespace {
__thread actor_id t_self_id;
constexpr struct pop_aid_log_event_t {
constexpr pop_aid_log_event_t() {
// nop
......@@ -156,7 +154,7 @@ class logging_impl : public logging {
}
std::ostringstream line;
line << time(0) << " " << level << " "
<< "actor" << t_self_id << " " << std::this_thread::get_id() << " "
<< "actor" << get_aid() << " " << std::this_thread::get_id() << " "
<< class_name << " " << function_name << " " << file_name << ":"
<< line_num << " " << msg << std::endl;
m_queue.synchronized_enqueue(m_queue_mtx, m_queue_cv,
......@@ -196,10 +194,31 @@ logging* logging::create_singleton() {
return new logging_impl;
}
// returns the actor ID for the current thread
actor_id logging::get_aid() {
shared_lock<detail::shared_spinlock> guard{m_aids_lock};
auto i = m_aids.find(std::this_thread::get_id());
if (i != m_aids.end()) {
return i->second;
}
return 0;
}
actor_id logging::set_aid(actor_id aid) {
actor_id prev = t_self_id;
t_self_id = aid;
return prev;
auto tid = std::this_thread::get_id();
upgrade_lock<detail::shared_spinlock> guard{m_aids_lock};
auto i = m_aids.find(tid);
if (i != m_aids.end()) {
// we modify it despite the shared lock because the elements themselves
// are considered thread-local
auto res = i->second;
i->second = aid;
return res;
}
// upgrade to unique lock and insert new element
upgrade_to_unique_lock<detail::shared_spinlock> uguard{guard};
m_aids.insert(std::make_pair(tid, aid));
return 0; // was empty before
}
} // namespace detail
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment