Commit 9a29258b authored by Dominik Charousset's avatar Dominik Charousset

further modularized middleman, fixed names in logs

moved middleman_event_handler_base to its own header;
splitted middleman interface into two parts:
  - middleman: provides `start`, `stop`, and `run_later`
  - abstract_middleman: provides non thread-safe member function for protocols;
use typeid(decltype(*this)) rather than typeid(*this) as class name in logfiles
parent 561b43b0
......@@ -289,3 +289,5 @@ cppa/detail/logging.hpp
src/logging.cpp
cppa/network/continuable_writer.hpp
src/continuable_writer.cpp
cppa/network/middleman_event_handler_base.hpp
src/actor_addressing.cpp
......@@ -45,10 +45,12 @@ class deserializer;
* for actors. This class encapsulates a technology-specific
* actor addressing.
*/
class actor_addressing : public ref_counted {
class actor_addressing {
public:
virtual ~actor_addressing();
/**
* @brief Returns the technology identifier of the implementation.
* @note All-uppercase identifiers are reserved for libcppa's
......
......@@ -106,30 +106,32 @@ class logging {
} } // namespace cppa::detail
#define CPPA_VOID_STMT static_cast<void>(0)
#ifndef CPPA_DEBUG
#define CPPA_LOG_ERROR(unused) static_cast<void>(0)
#define CPPA_LOG_ERROR_IF(unused1,unused2) static_cast<void>(0)
#define CPPA_LOGF_ERROR(unused) static_cast<void>(0)
#define CPPA_LOGF_ERROR_IF(unused1,unused2) static_cast<void>(0)
#define CPPA_LOG_ERROR(unused) CPPA_VOID_STMT
#define CPPA_LOG_ERROR_IF(unused1,unused2) CPPA_VOID_STMT
#define CPPA_LOGF_ERROR(unused) CPPA_VOID_STMT
#define CPPA_LOGF_ERROR_IF(unused1,unused2) CPPA_VOID_STMT
#define CPPA_LOG_WARNING(unused) static_cast<void>(0)
#define CPPA_LOG_WARNING_IF(unused1,unused2) static_cast<void>(0)
#define CPPA_LOGF_WARNING(unused) static_cast<void>(0)
#define CPPA_LOGF_WARNING_IF(unused1,unused2) static_cast<void>(0)
#define CPPA_LOG_WARNING(unused) CPPA_VOID_STMT
#define CPPA_LOG_WARNING_IF(unused1,unused2) CPPA_VOID_STMT
#define CPPA_LOGF_WARNING(unused) CPPA_VOID_STMT
#define CPPA_LOGF_WARNING_IF(unused1,unused2) CPPA_VOID_STMT
#define CPPA_LOG_INFO(unused) static_cast<void>(0)
#define CPPA_LOG_INFO_IF(unused1,unused2) static_cast<void>(0)
#define CPPA_LOGF_INFO(unused) static_cast<void>(0)
#define CPPA_LOGF_INFO_IF(unused1,unused2) static_cast<void>(0)
#define CPPA_LOG_INFO(unused) CPPA_VOID_STMT
#define CPPA_LOG_INFO_IF(unused1,unused2) CPPA_VOID_STMT
#define CPPA_LOGF_INFO(unused) CPPA_VOID_STMT
#define CPPA_LOGF_INFO_IF(unused1,unused2) CPPA_VOID_STMT
#define CPPA_LOG_DEBUG(unused) static_cast<void>(0)
#define CPPA_LOG_DEBUG_IF(unused1,unused2) static_cast<void>(0)
#define CPPA_LOGF_DEBUG(unused) static_cast<void>(0)
#define CPPA_LOGF_DEBUG_IF(unused1,unused2) static_cast<void>(0)
#define CPPA_LOG_DEBUG(unused) CPPA_VOID_STMT
#define CPPA_LOG_DEBUG_IF(unused1,unused2) CPPA_VOID_STMT
#define CPPA_LOGF_DEBUG(unused) CPPA_VOID_STMT
#define CPPA_LOGF_DEBUG_IF(unused1,unused2) CPPA_VOID_STMT
#define CPPA_LOG_TRACE(unused) static_cast<void>(0)
#define CPPA_LOGF_TRACE(unused) static_cast<void>(0)
#define CPPA_LOG_TRACE(unused) CPPA_VOID_STMT
#define CPPA_LOGF_TRACE(unused) CPPA_VOID_STMT
#else
......@@ -138,40 +140,44 @@ class logging {
::cppa::detail::logging::instance()->log( \
level, "NONE", \
__FUNCTION__, __FILE__, __LINE__, scoped_oss.str()); \
} static_cast<void>(0)
} CPPA_VOID_STMT
#define CPPA_DO_LOG_MEMBER_FUN(level, message) { \
std::ostringstream scoped_oss; scoped_oss << message; \
::cppa::detail::logging::instance()->log( \
level, ::cppa::detail::demangle(typeid(*this)).c_str(), \
__FUNCTION__, __FILE__, __LINE__, scoped_oss.str()); \
} static_cast<void>(0)
} CPPA_VOID_STMT
#define CPPA_LOG_ERROR(message) CPPA_DO_LOG_MEMBER_FUN("ERROR ", message)
#define CPPA_LOGF_ERROR(message) CPPA_DO_LOG_FUN("ERROR ", message)
#ifndef CPPA_LOG_LEVEL
#define CPPA_LOG_LEVEL 0
#endif
#if CPPA_LOG_LEVEL > 0
# define CPPA_LOG_WARNING(message) CPPA_DO_LOG_MEMBER_FUN("WARNING", message)
# define CPPA_LOGF_WARNING(message) CPPA_DO_LOG_FUN("WARNING", message)
#else
# define CPPA_LOG_WARNING(unused) static_cast<void>(0)
# define CPPA_LOGF_WARNING(unused) static_cast<void>(0)
# define CPPA_LOG_WARNING(unused) CPPA_VOID_STMT
# define CPPA_LOGF_WARNING(unused) CPPA_VOID_STMT
#endif
#if CPPA_LOG_LEVEL > 1
# define CPPA_LOG_INFO(message) CPPA_DO_LOG_MEMBER_FUN("INFO ", message)
# define CPPA_LOGF_INFO(message) CPPA_DO_LOG_FUN("INFO ", message)
#else
# define CPPA_LOG_INFO(unused) static_cast<void>(0)
# define CPPA_LOGF_INFO(unused) static_cast<void>(0)
# define CPPA_LOG_INFO(unused) CPPA_VOID_STMT
# define CPPA_LOGF_INFO(unused) CPPA_VOID_STMT
#endif
#if CPPA_LOG_LEVEL > 2
# define CPPA_LOG_DEBUG(message) CPPA_DO_LOG_MEMBER_FUN("DEBUG ", message)
# define CPPA_LOGF_DEBUG(message) CPPA_DO_LOG_FUN("DEBUG ", message)
#else
# define CPPA_LOG_DEBUG(unused) static_cast<void>(0)
# define CPPA_LOGF_DEBUG(unused) static_cast<void>(0)
# define CPPA_LOG_DEBUG(unused) CPPA_VOID_STMT
# define CPPA_LOGF_DEBUG(unused) CPPA_VOID_STMT
#endif
#if CPPA_LOG_LEVEL > 3
......@@ -186,7 +192,8 @@ class logging {
CPPA_CONCATL(cppa_trace_helper_) << message ; \
::cppa::detail::logging::trace_helper CPPA_CONCATL(cppa_fun_trace_helper_) \
CPPA_LPAREN ::cppa::detail::demangle \
CPPA_LPAREN typeid CPPA_LPAREN *this CPPA_RPAREN CPPA_RPAREN , \
CPPA_LPAREN typeid CPPA_LPAREN decltype CPPA_LPAREN *this \
CPPA_RPAREN CPPA_RPAREN CPPA_RPAREN , \
__func__ , __FILE__ , __LINE__ , \
CPPA_CONCATL(cppa_trace_helper_) .str() CPPA_RPAREN
# define CPPA_LOGF_TRACE(message) \
......@@ -203,28 +210,28 @@ class logging {
#endif
#define CPPA_LOG_ERROR_IF(stmt,message) \
if (stmt) { CPPA_LOG_ERROR(message); }; static_cast<void>(0)
if (stmt) { CPPA_LOG_ERROR(message); }; CPPA_VOID_STMT
#define CPPA_LOG_WARNING_IF(stmt,message) \
if (stmt) { CPPA_LOG_WARNING(message); }; static_cast<void>(0)
if (stmt) { CPPA_LOG_WARNING(message); }; CPPA_VOID_STMT
#define CPPA_LOG_INFO_IF(stmt,message) \
if (stmt) { CPPA_LOG_INFO(message); }; static_cast<void>(0)
if (stmt) { CPPA_LOG_INFO(message); }; CPPA_VOID_STMT
#define CPPA_LOG_DEBUG_IF(stmt,message) \
if (stmt) { CPPA_LOG_DEBUG(message); }; static_cast<void>(0)
if (stmt) { CPPA_LOG_DEBUG(message); }; CPPA_VOID_STMT
#define CPPA_LOGF_ERROR_IF(stmt,message) \
if (stmt) { CPPA_LOGF_ERROR(message); }; static_cast<void>(0)
if (stmt) { CPPA_LOGF_ERROR(message); }; CPPA_VOID_STMT
#define CPPA_LOGF_WARNING_IF(stmt,message) \
if (stmt) { CPPA_LOGF_WARNING(message); }; static_cast<void>(0)
if (stmt) { CPPA_LOGF_WARNING(message); }; CPPA_VOID_STMT
#define CPPA_LOGF_INFO_IF(stmt,message) \
if (stmt) { CPPA_LOGF_INFO(message); }; static_cast<void>(0)
if (stmt) { CPPA_LOGF_INFO(message); }; CPPA_VOID_STMT
#define CPPA_LOGF_DEBUG_IF(stmt,message) \
if (stmt) { CPPA_LOGF_DEBUG(message); }; static_cast<void>(0)
if (stmt) { CPPA_LOGF_DEBUG(message); }; CPPA_VOID_STMT
#endif // CPPA_DEBUG
......
......@@ -50,7 +50,7 @@ class default_protocol : public protocol {
public:
default_protocol(middleman* parent);
default_protocol(abstract_middleman* parent);
atom_value identifier() const;
......
......@@ -45,26 +45,10 @@ namespace cppa { namespace detail { class singleton_manager; } }
namespace cppa { namespace network {
class middleman_impl;
class middleman_overseer;
class middleman_event_handler;
void middleman_loop(middleman_impl*);
class middleman {
// the most popular class in libcppa
friend class peer;
friend class protocol;
friend class peer_acceptor;
friend class singleton_manager;
friend class middleman_overseer;
friend class middleman_event_handler;
friend class detail::singleton_manager;
friend void middleman_loop(middleman_impl*);
public:
virtual ~middleman();
......@@ -73,54 +57,43 @@ class middleman {
virtual protocol_ptr protocol(atom_value id) = 0;
protected:
// runs @p fun in the middleman's event loop
virtual void run_later(std::function<void()> fun) = 0;
middleman();
protected:
virtual void stop() = 0;
virtual void start() = 0;
// to be called from protocol
// runs @p fun in the middleman's event loop
virtual void run_later(std::function<void()> fun) = 0;
// to be called from singleton_manager
private:
static middleman* create_singleton();
};
// to be called from peer
class middleman_event_handler;
/**
* @pre ptr->as_writer() != nullptr
*/
void continue_writer(const continuable_reader_ptr& ptr);
class abstract_middleman : public middleman {
/**
* @pre ptr->as_writer() != nullptr
*/
void stop_writer(const continuable_reader_ptr& ptr);
public:
// to be called form peer_acceptor or protocol
inline abstract_middleman() : m_done(false) { }
void continue_reader(const continuable_reader_ptr& what);
void stop_writer(const continuable_reader_ptr& ptr);
void continue_writer(const continuable_reader_ptr& ptr);
void stop_reader(const continuable_reader_ptr& what);
void continue_reader(const continuable_reader_ptr& what);
// to be called from m_handler or middleman_overseer
protected:
inline void quit() { m_done = true; }
inline bool done() const { return m_done; }
// member variables
bool m_done;
std::vector<continuable_reader_ptr> m_readers;
std::unique_ptr<middleman_event_handler> m_handler;
middleman_event_handler& handler();
};
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa 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 Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef MIDDLEMAN_EVENT_HANDLER_BASE_HPP
#define MIDDLEMAN_EVENT_HANDLER_BASE_HPP
#include <vector>
#include <utility>
#include "cppa/config.hpp"
#include "cppa/network/continuable_reader.hpp"
#include "cppa/network/continuable_writer.hpp"
#include "cppa/detail/logging.hpp"
namespace cppa { namespace network {
typedef int event_bitmask;
namespace event {
static constexpr event_bitmask none = 0x00;
static constexpr event_bitmask read = 0x01;
static constexpr event_bitmask write = 0x02;
static constexpr event_bitmask both = 0x03;
static constexpr event_bitmask error = 0x04;
} // namespace event
inline const char* eb2str(event_bitmask e) {
switch (e) {
default: return "INVALID";
case event::none: return "event::none";
case event::read: return "event::read";
case event::write: return "event::write";
case event::both: return "event::both";
case event::error: return "event::error";
}
}
struct fd_meta_info {
native_socket_type fd;
continuable_reader_ptr ptr;
event_bitmask mask;
fd_meta_info(native_socket_type a0,
const continuable_reader_ptr& a1,
event_bitmask a2)
: fd(a0), ptr(a1), mask(a2) { }
};
struct fd_meta_info_less {
inline bool operator()(const fd_meta_info& lhs, native_socket_type rhs) const {
return lhs.fd < rhs;
}
};
enum class fd_meta_event { add, erase, mod };
template<typename Derived>
class middleman_event_handler_base {
public:
typedef std::vector<fd_meta_info> vector_type;
virtual ~middleman_event_handler_base() { }
void alteration(const continuable_reader_ptr& ptr,
event_bitmask e,
fd_meta_event etype) {
native_socket_type fd;
switch (e) {
case event::read:
fd = ptr->read_handle();
break;
case event::write: {
auto wptr = ptr->as_writer();
if (wptr) fd = wptr->write_handle();
else {
CPPA_LOG_ERROR("ptr->as_writer() returned nullptr");
return;
}
break;
}
case event::both: {
fd = ptr->read_handle();
auto wptr = ptr->as_writer();
if (wptr) {
auto wrfd = wptr->write_handle();
if (fd != wrfd) {
CPPA_LOG_DEBUG("read_handle != write_handle, split "
"into two function calls");
// split into two function calls
e = event::read;
alteration(ptr, event::write, etype);
}
}
else {
CPPA_LOG_ERROR("ptr->as_writer() returned nullptr");
return;
}
break;
}
default:
CPPA_LOG_ERROR("invalid bitmask");
return;
}
m_alterations.emplace_back(fd_meta_info(fd, ptr, e), etype);
}
void add(const continuable_reader_ptr& ptr, event_bitmask e) {
CPPA_LOG_TRACE("ptr = " << ptr.get() << ", e = " << eb2str(e));
alteration(ptr, e, fd_meta_event::add);
}
void erase(const continuable_reader_ptr& ptr, event_bitmask e) {
CPPA_LOG_TRACE("ptr = " << ptr.get() << ", e = " << eb2str(e));
alteration(ptr, e, fd_meta_event::erase);
}
inline event_bitmask next_bitmask(event_bitmask old, event_bitmask arg, fd_meta_event op) {
CPPA_REQUIRE(op == fd_meta_event::add || op == fd_meta_event::erase);
return (op == fd_meta_event::add) ? old | arg : old & ~arg;
}
void update() {
CPPA_LOG_TRACE("");
for (auto& elem_pair : m_alterations) {
auto& elem = elem_pair.first;
auto old = event::none;
auto last = end(m_meta);
auto iter = lower_bound(begin(m_meta), last, elem.fd, m_less);
if (iter != last) old = iter->mask;
auto mask = next_bitmask(old, elem.mask, elem_pair.second);
auto ptr = elem.ptr.get();
CPPA_LOG_DEBUG("new bitmask for "
<< elem.ptr.get() << ": " << eb2str(mask));
if (iter == last || iter->fd != elem.fd) {
CPPA_LOG_INFO_IF(mask == event::none,
"cannot erase " << ptr
<< " (not found in m_meta)");
if (mask != event::none) {
m_meta.insert(iter, elem);
d()->handle_event(fd_meta_event::add, elem.fd,
event::none, mask, ptr);
}
}
else if (iter->fd == elem.fd) {
CPPA_REQUIRE(iter->ptr == elem.ptr);
if (mask == event::none) {
m_meta.erase(iter);
d()->handle_event(fd_meta_event::erase, elem.fd, old, mask, ptr);
}
else {
iter->mask = mask;
d()->handle_event(fd_meta_event::mod, elem.fd, old, mask, ptr);
}
}
}
m_alterations.clear();
}
protected:
fd_meta_info_less m_less;
vector_type m_meta; // this vector is *always* sorted
std::vector<std::pair<fd_meta_info,fd_meta_event> > m_alterations;
private:
vector_type::iterator find_meta(native_socket_type fd) {
auto last = end(m_meta);
auto iter = lower_bound(begin(m_meta), last, fd, m_less);
return (iter != last && iter->fd == fd) ? iter : last;
}
Derived* d() { return static_cast<Derived*>(this); }
};
template<class BaseIter, class BasIterAccess>
class event_iterator_impl {
public:
event_iterator_impl(const BaseIter& iter) : m_i(iter) { }
inline event_iterator_impl& operator++() {
m_access.advance(m_i);
return *this;
}
inline event_iterator_impl* operator->() { return this; }
inline const event_iterator_impl* operator->() const { return this; }
inline event_bitmask type() const {
return m_access.type(m_i);
}
inline continue_reading_result continue_reading() {
return ptr()->continue_reading();
}
inline continue_writing_result continue_writing() {
return ptr()->as_writer()->continue_writing();
}
inline bool equal_to(const event_iterator_impl& other) const {
return m_access.equal(m_i, other.m_i);
}
inline void handled() { m_access.handled(m_i); }
inline continuable_reader* ptr() { return m_access.ptr(m_i); }
private:
BaseIter m_i;
BasIterAccess m_access;
};
template<class Iter, class Access>
inline bool operator==(const event_iterator_impl<Iter,Access>& lhs,
const event_iterator_impl<Iter,Access>& rhs) {
return lhs.equal_to(rhs);
}
template<class Iter, class Access>
inline bool operator!=(const event_iterator_impl<Iter,Access>& lhs,
const event_iterator_impl<Iter,Access>& rhs) {
return !lhs.equal_to(rhs);
}
} } // namespace cppa::detail
#endif // MIDDLEMAN_EVENT_HANDLER_BASE_HPP
......@@ -44,7 +44,7 @@
namespace cppa { namespace network {
class middleman;
class abstract_middleman;
class continuable_reader;
class continuable_writer;
......@@ -56,7 +56,7 @@ class protocol : public ref_counted {
typedef std::initializer_list<primitive_variant> variant_args;
protocol(middleman* parent);
protocol(abstract_middleman* parent);
virtual atom_value identifier() const = 0;
......@@ -89,13 +89,13 @@ class protocol : public ref_counted {
// note: not thread-safe; call only in run_later functor!
void stop_writer(continuable_reader* what);
inline middleman* parent() { return m_parent; }
inline abstract_middleman* parent() { return m_parent; }
inline const middleman* parent() const { return m_parent; }
inline const abstract_middleman* parent() const { return m_parent; }
private:
middleman* m_parent;
abstract_middleman* m_parent;
};
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa 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 Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#include"cppa/actor_addressing.hpp"
namespace cppa {
actor_addressing::~actor_addressing() { }
} // namespace cppa
......@@ -55,16 +55,13 @@ default_actor_proxy::~default_actor_proxy() {
CPPA_LOGF_TRACE("lambda from ~default_actor_proxy"
<< "; node = " << to_string(*node) << ", aid " << aid
<< ", proto = " << to_string(proto->identifier()));
if (detail::singleton_manager::get_middleman()) {
proto->addressing()->erase(*node, aid);
auto p = proto->get_peer(*node);
if (p && p->erase_on_last_proxy_exited()) {
if (proto->addressing()->count_proxies(*node) == 0) {
proto->erase_peer(p);
}
proto->addressing()->erase(*node, aid);
auto p = proto->get_peer(*node);
if (p && p->erase_on_last_proxy_exited()) {
if (proto->addressing()->count_proxies(*node) == 0) {
proto->erase_peer(p);
}
}
// else: middleman already shut down!
});
}
......
......@@ -52,7 +52,7 @@ using namespace cppa::detail;
namespace cppa { namespace network {
default_protocol::default_protocol(middleman* parent)
default_protocol::default_protocol(abstract_middleman* parent)
: super(parent), m_addressing(this) { }
atom_value default_protocol::identifier() const {
......
This diff is collapsed.
......@@ -35,7 +35,7 @@
namespace cppa { namespace network {
protocol::protocol(middleman* parent) : m_parent(parent) { }
protocol::protocol(abstract_middleman* parent) : m_parent(parent) { }
void protocol::run_later(std::function<void()> fun) {
m_parent->run_later([=] { fun(); });
......
......@@ -371,7 +371,6 @@ class string_deserializer : public deserializer {
throw_malformed("atom string size > 10");
}
string substr(m_pos, substr_end);
std::cout << "atom string: " << substr << std::endl;
m_pos += substr.size() + 1;
return detail::atom_val(substr.c_str(), 0xF);
}
......
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