Skip to content

Commit

Permalink
Use RW lock for AID instead of __thread variable
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Neverlord committed Apr 7, 2015
1 parent d6dae07 commit 079f637
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 23 deletions.
41 changes: 24 additions & 17 deletions libcaf_core/caf/detail/logging.hpp
Expand Up @@ -20,17 +20,20 @@
#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"
#include "caf/abstract_actor.hpp"

#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
Expand All @@ -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();
Expand All @@ -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) {
Expand Down
31 changes: 25 additions & 6 deletions libcaf_core/src/logging.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 079f637

Please sign in to comment.