Replaced custom event code with Boost.Signals.

This commit is contained in:
Gunnar Beutner 2012-06-14 15:16:41 +02:00
parent b0a372c5f8
commit 1e1bb43dea
35 changed files with 245 additions and 236 deletions

View File

@ -4,7 +4,6 @@
include aminclude.am
SUBDIRS = \
compat \
third-party \
base \
dyn \

15
README
View File

@ -6,6 +6,7 @@ application using a dist tarball:
* C++ compiler
* OpenSSL library and header files
* Boost library and header files
* Doxygen (only if you plan on building the internal code documentation)
Packaging Requirements
@ -15,24 +16,10 @@ In order to build a dist tarball for the application the following external
software components need to be installed in addition to the build requirements
mentioned above:
* Boost library
* GNU Automake
* GNU Autoconf
* GNU Libtool
"make dist" extracts the following components from the Boost library (using
bcp):
* tr1
* smart_ptr
* bind
* function
* make_shared
These components are only used on the target system if your C++ compiler does
not at least support TR1 and there's no other system-wide installation of the
Boost library.
Debian Packages
---------------

View File

@ -65,4 +65,5 @@ libbase_la_LDFLAGS = \
libbase_la_LIBADD = \
$(LIBLTDL) \
$(OPENSSL_LIBS) \
$(BOOST_SIGNALS_LIB) \
${top_builddir}/third-party/mmatch/libmmatch.la

View File

@ -96,6 +96,8 @@ void Application::RunEventLoop(void)
fd_set readfds, writefds, exceptfds;
int nfds = -1;
Object::ClearHeldObjects();
Timer::CallExpiredTimers();
FD_ZERO(&readfds);

View File

@ -17,49 +17,22 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#ifndef DELEGATE_H
#define DELEGATE_H
#ifndef EVENTARGS_H
#define EVENTARGS_H
namespace icinga
{
template<class TObject, class TArgs>
int delegate_fwd(int (TObject::*function)(TArgs), weak_ptr<TObject> wref, TArgs args)
/**
* Base class for event arguments.
*
* @ingroup base
*/
struct I2_BASE_API EventArgs
{
shared_ptr<TObject> ref = wref.lock();
if (!ref)
return -1;
return (ref.get()->*function)(args);
}
template<class TObject, class TArgs>
function<int (TArgs)> bind_weak(int (TObject::*function)(TArgs), const weak_ptr<TObject>& wref)
{
return bind(&delegate_fwd<TObject, TArgs>, function, wref,
#ifdef HAVE_BOOST
_1
#else /* HAVE_BOOST */
placeholders::_1
#endif /* HAVE_BOOST */
);
}
template<class TObject, class TArgs>
function<int (TArgs)> bind_weak(int (TObject::*function)(TArgs), shared_ptr<TObject> ref)
{
weak_ptr<TObject> wref = weak_ptr<TObject>(ref);
return bind_weak(function, wref);
}
template<class TObject, class TArgs>
function<int (TArgs)> bind_weak(int (TObject::*function)(TArgs), shared_ptr<Object> ref)
{
weak_ptr<TObject> wref = weak_ptr<TObject>(static_pointer_cast<TObject>(ref));
return bind_weak(function, wref);
}
Object::Ptr Source; /**< The source of the event. */
};
}
#endif /* DELEGATE_H */
#endif /* EVENTARGS_H */

View File

@ -93,7 +93,6 @@
#include <algorithm>
using namespace std;
using std::exception;
#ifdef HAVE_STDCXX_0X
# include <memory>
@ -121,6 +120,8 @@ using namespace std::tr1::placeholders;
#endif /* HAVE_BOOST */
#endif /* HAVE_STDCXX_0X */
#include <boost/signal.hpp>
#if defined(__APPLE__) && defined(__MACH__)
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
@ -143,9 +144,8 @@ using namespace std::tr1::placeholders;
#include "object.h"
#include "exception.h"
#include "memory.h"
#include "delegate.h"
#include "observable.h"
#include "variant.h"
#include "eventargs.h"
#include "dictionary.h"
#include "timer.h"
#include "fifo.h"

View File

@ -21,6 +21,8 @@
using namespace icinga;
vector<Object::Ptr> Object::m_HeldObjects;
/**
* Default constructor for the Object class.
*/
@ -35,3 +37,22 @@ Object::~Object(void)
{
}
/**
* Temporarily holds onto a reference for an object. This can
* be used to safely clear the last reference to an object
* in an event handler.
*/
void Object::Hold(void)
{
m_HeldObjects.push_back(shared_from_this());
}
/**
* Clears all temporarily held objects.
*/
void Object::ClearHeldObjects(void)
{
cout << "Cleared " << m_HeldObjects.size() << " held objects." << endl;
m_HeldObjects.clear();
}

View File

@ -29,7 +29,7 @@ namespace icinga
*
* @ingroup base
*/
class I2_BASE_API Object : public enable_shared_from_this<Object>
class I2_BASE_API Object : public enable_shared_from_this<Object>, boost::signals::trackable
{
public:
typedef shared_ptr<Object> Ptr;
@ -39,9 +39,16 @@ protected:
Object(void);
virtual ~Object(void);
static void ClearHeldObjects(void);
protected:
void Hold(void);
private:
Object(const Object& other);
Object operator=(const Object& rhs);
static vector<Object::Ptr> m_HeldObjects;
};
/**

View File

@ -43,9 +43,9 @@ public:
void Start(void)
{
m_Parent->OnObjectAdded += bind_weak(&ObjectMap::ObjectAddedHandler, shared_from_this());
m_Parent->OnObjectCommitted += bind_weak(&ObjectMap::ObjectCommittedHandler, shared_from_this());
m_Parent->OnObjectRemoved += bind_weak(&ObjectMap::ObjectRemovedHandler, shared_from_this());
m_Parent->OnObjectAdded.connect(bind(&ObjectMap::ObjectAddedHandler, this, _1));
m_Parent->OnObjectCommitted.connect(bind(&ObjectMap::ObjectCommittedHandler, this, _1));
m_Parent->OnObjectRemoved.connect(bind(&ObjectMap::ObjectRemovedHandler, this, _1));
for (typename ObjectSet<TValue>::Iterator it = m_Parent->Begin(); it != m_Parent->End(); it++)
AddObject(*it);

View File

@ -49,9 +49,9 @@ public:
void Start(void)
{
if (m_Parent) {
m_Parent->OnObjectAdded += bind_weak(&ObjectSet::ObjectAddedOrCommittedHandler, shared_from_this());
m_Parent->OnObjectCommitted += bind_weak(&ObjectSet::ObjectAddedOrCommittedHandler, shared_from_this());
m_Parent->OnObjectRemoved += bind_weak(&ObjectSet::ObjectRemovedHandler, shared_from_this());
m_Parent->OnObjectAdded.connect(bind(&ObjectSet::ObjectAddedOrCommittedHandler, this, _1));
m_Parent->OnObjectCommitted.connect(bind(&ObjectSet::ObjectAddedOrCommittedHandler, this, _1));
m_Parent->OnObjectRemoved.connect(bind(&ObjectSet::ObjectRemovedHandler, this, _1));
for (ObjectSet::Iterator it = m_Parent->Begin(); it != m_Parent->End(); it++)
CheckObject(*it);
@ -107,9 +107,9 @@ public:
}
}
Observable<ObjectSetEventArgs<TValue> > OnObjectAdded;
Observable<ObjectSetEventArgs<TValue> > OnObjectCommitted;
Observable<ObjectSetEventArgs<TValue> > OnObjectRemoved;
boost::signal<void (const ObjectSetEventArgs<TValue>&)> OnObjectAdded;
boost::signal<void (const ObjectSetEventArgs<TValue>&)> OnObjectCommitted;
boost::signal<void (const ObjectSetEventArgs<TValue>&)> OnObjectRemoved;
Iterator Begin(void)
{

View File

@ -1,104 +0,0 @@
/******************************************************************************
* Icinga 2 *
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
* *
* This program 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 2 *
* of the License, or (at your option) any later version. *
* *
* This program 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 this program; if not, write to the Free Software Foundation *
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
******************************************************************************/
#ifndef OBSERVABLE_H
#define OBSERVABLE_H
namespace icinga
{
/**
* Base class for event arguments.
*
* @ingroup base
*/
struct I2_BASE_API EventArgs
{
Object::Ptr Source; /**< The source of the event. */
};
/**
* An observable event. Observers can be registered for it.
*
* @ingroup base
*/
template<class TArgs>
class Observable
{
public:
typedef function<int (const TArgs&)> ObserverType;
/**
* Adds an observer to this event.
*
* @param rhs The observer.
*/
Observable<TArgs>& operator +=(const ObserverType& rhs)
{
m_Observers.push_back(rhs);
return *this;
}
/**
* Removes an observer from this event.
*
* @param rhs The observer.
*/
Observable<TArgs>& operator -=(const ObserverType& rhs)
{
m_Observers.erase(rhs);
return *this;
}
/**
* Invokes each observer function that is registered for this event. Any
* observer function which returns -1 is removed.
*
* @param args Event arguments.
*/
void operator()(const TArgs& args)
{
typename vector<ObserverType>::size_type i = 0;
for (i = 0; i < m_Observers.size(); ) {
int result = m_Observers[i](args);
if (result == -1)
m_Observers.erase(m_Observers.begin() + i);
else
i++;
}
}
/**
* Checks whether there's at least one observer.
*
* @returns true if there are one or more observers, false otherwise.
*/
bool HasObservers(void) const
{
return !m_Observers.empty();
}
private:
vector<ObserverType> m_Observers;
};
}
#endif /* OBSERVABLE_H */

View File

@ -50,7 +50,7 @@ void Socket::Start(void)
{
assert(m_FD != INVALID_SOCKET);
OnException += bind_weak(&Socket::ExceptionEventHandler, shared_from_this());
OnException.connect(bind(&Socket::ExceptionEventHandler, this, _1));
Sockets.push_back(static_pointer_cast<Socket>(shared_from_this()));
}
@ -171,14 +171,15 @@ int Socket::GetLastSocketError(void)
*/
void Socket::HandleSocketError(const std::exception& ex)
{
if (OnError.HasObservers()) {
// XXX, TODO: add SetErrorHandling() function
/* if (OnError.HasObservers()) {*/
SocketErrorEventArgs sea(ex);
OnError(sea);
Close();
} else {
/* } else {
throw ex;
}
}*/
}
/**

View File

@ -55,12 +55,12 @@ public:
void SetFD(SOCKET fd);
SOCKET GetFD(void) const;
Observable<EventArgs> OnReadable;
Observable<EventArgs> OnWritable;
Observable<EventArgs> OnException;
boost::signal<void (const EventArgs&)> OnReadable;
boost::signal<void (const EventArgs&)> OnWritable;
boost::signal<void (const EventArgs&)> OnException;
Observable<SocketErrorEventArgs> OnError;
Observable<EventArgs> OnClosed;
boost::signal<void (const SocketErrorEventArgs&)> OnError;
boost::signal<void (const EventArgs&)> OnClosed;
virtual bool WantsToRead(void) const;
virtual bool WantsToWrite(void) const;

View File

@ -51,8 +51,8 @@ void TcpClient::Start(void)
{
TcpSocket::Start();
OnReadable += bind_weak(&TcpClient::ReadableEventHandler, shared_from_this());
OnWritable += bind_weak(&TcpClient::WritableEventHandler, shared_from_this());
OnReadable.connect(bind(&TcpClient::ReadableEventHandler, this, _1));
OnWritable.connect(bind(&TcpClient::WritableEventHandler, this, _1));
}
/**

View File

@ -61,7 +61,7 @@ public:
virtual bool WantsToRead(void) const;
virtual bool WantsToWrite(void) const;
Observable<EventArgs> OnDataAvailable;
boost::signal<void (const EventArgs&)> OnDataAvailable;
private:
TcpClientRole m_Role;

View File

@ -56,7 +56,7 @@ void TcpServer::Start(void)
{
TcpSocket::Start();
OnReadable += bind_weak(&TcpServer::ReadableEventHandler, shared_from_this());
OnReadable.connect(bind(&TcpServer::ReadableEventHandler, this, _1));
}
/**

View File

@ -54,7 +54,7 @@ public:
void Listen(void);
Observable<NewClientEventArgs> OnNewClient;
boost::signal<void (const NewClientEventArgs&)> OnNewClient;
virtual bool WantsToRead(void) const;

View File

@ -65,7 +65,7 @@ public:
void Reschedule(time_t next);
Observable<TimerEventArgs> OnTimerExpired;
boost::signal<void (const TimerEventArgs&)> OnTimerExpired;
private:
EventArgs m_UserArgs; /**< User-specified event arguments. */

View File

@ -55,7 +55,7 @@ public:
virtual bool WantsToRead(void) const;
virtual bool WantsToWrite(void) const;
Observable<VerifyCertificateEventArgs> OnVerifyCertificate;
boost::signal<void (const VerifyCertificateEventArgs&)> OnVerifyCertificate;
protected:
void HandleSSLError(void);

View File

@ -1,7 +0,0 @@
EXTRA_DIST=include
include:
rm -Rf boost && mkdir -p boost && \
bcp --boost=$(BOOST_PATH)/include tr1 smart_ptr bind function make_shared boost && \
rm -Rf include && mkdir include && \
mv boost/boost include/

View File

@ -30,9 +30,9 @@ void CheckerComponent::Start(void)
{
m_CheckerEndpoint = make_shared<VirtualEndpoint>();
m_CheckerEndpoint->RegisterTopicHandler("checker::AssignService",
bind_weak(&CheckerComponent::AssignServiceRequestHandler, shared_from_this()));
bind(&CheckerComponent::AssignServiceRequestHandler, this, _1));
m_CheckerEndpoint->RegisterTopicHandler("checker::RevokeService",
bind_weak(&CheckerComponent::AssignServiceRequestHandler, shared_from_this()));
bind(&CheckerComponent::AssignServiceRequestHandler, this, _1));
m_CheckerEndpoint->RegisterPublication("checker::CheckResult");
GetEndpointManager()->RegisterEndpoint(m_CheckerEndpoint);
@ -41,11 +41,11 @@ void CheckerComponent::Start(void)
GetEndpointManager()->SendAPIMessage(m_CheckerEndpoint, rm, bind(&CheckerComponent::TestResponseHandler, this, _1));
// TODO: get rid of this
ConfigObject::GetAllObjects()->OnObjectAdded += bind_weak(&CheckerComponent::NewServiceHandler, shared_from_this());
ConfigObject::GetAllObjects()->OnObjectAdded.connect(bind(&CheckerComponent::NewServiceHandler, this, _1));
m_CheckTimer = make_shared<Timer>();
m_CheckTimer->SetInterval(10);
m_CheckTimer->OnTimerExpired += bind_weak(&CheckerComponent::CheckTimerHandler, shared_from_this());
m_CheckTimer->OnTimerExpired.connect(bind(&CheckerComponent::CheckTimerHandler, this, _1));
m_CheckTimer->Start();
CheckTask::RegisterType("nagios", NagiosCheckTask::CreateTask);

View File

@ -35,23 +35,23 @@ void ConfigRpcComponent::Start(void)
long configSource;
if (GetConfig()->GetProperty("configSource", &configSource) && configSource != 0) {
m_ConfigRpcEndpoint->RegisterTopicHandler("config::FetchObjects",
bind_weak(&ConfigRpcComponent::FetchObjectsHandler, shared_from_this()));
bind(&ConfigRpcComponent::FetchObjectsHandler, this, _1));
ConfigObject::GetAllObjects()->OnObjectAdded += bind_weak(&ConfigRpcComponent::LocalObjectCommittedHandler, shared_from_this());
ConfigObject::GetAllObjects()->OnObjectCommitted += bind_weak(&ConfigRpcComponent::LocalObjectCommittedHandler, shared_from_this());
ConfigObject::GetAllObjects()->OnObjectRemoved += bind_weak(&ConfigRpcComponent::LocalObjectRemovedHandler, shared_from_this());
ConfigObject::GetAllObjects()->OnObjectAdded.connect(bind(&ConfigRpcComponent::LocalObjectCommittedHandler, this, _1));
ConfigObject::GetAllObjects()->OnObjectCommitted.connect(bind(&ConfigRpcComponent::LocalObjectCommittedHandler, this, _1));
ConfigObject::GetAllObjects()->OnObjectRemoved.connect(bind(&ConfigRpcComponent::LocalObjectRemovedHandler, this, _1));
m_ConfigRpcEndpoint->RegisterPublication("config::ObjectCommitted");
m_ConfigRpcEndpoint->RegisterPublication("config::ObjectRemoved");
}
endpointManager->OnNewEndpoint += bind_weak(&ConfigRpcComponent::NewEndpointHandler, shared_from_this());
endpointManager->OnNewEndpoint.connect(bind(&ConfigRpcComponent::NewEndpointHandler, this, _1));
m_ConfigRpcEndpoint->RegisterPublication("config::FetchObjects");
m_ConfigRpcEndpoint->RegisterTopicHandler("config::ObjectCommitted",
bind_weak(&ConfigRpcComponent::RemoteObjectCommittedHandler, shared_from_this()));
bind(&ConfigRpcComponent::RemoteObjectCommittedHandler, this, _1));
m_ConfigRpcEndpoint->RegisterTopicHandler("config::ObjectRemoved",
bind_weak(&ConfigRpcComponent::RemoteObjectRemovedHandler, shared_from_this()));
bind(&ConfigRpcComponent::RemoteObjectRemovedHandler, this, _1));
endpointManager->RegisterEndpoint(m_ConfigRpcEndpoint);
}
@ -66,7 +66,7 @@ void ConfigRpcComponent::Stop(void)
int ConfigRpcComponent::NewEndpointHandler(const NewEndpointEventArgs& ea)
{
ea.Endpoint->OnSessionEstablished += bind_weak(&ConfigRpcComponent::SessionEstablishedHandler, shared_from_this());
ea.Endpoint->OnSessionEstablished.connect(bind(&ConfigRpcComponent::SessionEstablishedHandler, this, _1));
return 0;
}

View File

@ -38,13 +38,13 @@ void DemoComponent::Start(void)
{
m_DemoEndpoint = make_shared<VirtualEndpoint>();
m_DemoEndpoint->RegisterTopicHandler("demo::HelloWorld",
bind_weak(&DemoComponent::HelloWorldRequestHandler, shared_from_this()));
bind(&DemoComponent::HelloWorldRequestHandler, this, _1));
m_DemoEndpoint->RegisterPublication("demo::HelloWorld");
GetEndpointManager()->RegisterEndpoint(m_DemoEndpoint);
m_DemoTimer = make_shared<Timer>();
m_DemoTimer->SetInterval(5);
m_DemoTimer->OnTimerExpired += bind_weak(&DemoComponent::DemoTimerHandler, shared_from_this());
m_DemoTimer->OnTimerExpired.connect(bind(&DemoComponent::DemoTimerHandler, this, _1));
m_DemoTimer->Start();
}

View File

@ -40,24 +40,24 @@ void DiscoveryComponent::Start(void)
m_DiscoveryEndpoint->RegisterPublication("discovery::RegisterComponent");
m_DiscoveryEndpoint->RegisterTopicHandler("discovery::RegisterComponent",
bind_weak(&DiscoveryComponent::RegisterComponentMessageHandler, shared_from_this()));
bind(&DiscoveryComponent::RegisterComponentMessageHandler, this, _1));
m_DiscoveryEndpoint->RegisterPublication("discovery::NewComponent");
m_DiscoveryEndpoint->RegisterTopicHandler("discovery::NewComponent",
bind_weak(&DiscoveryComponent::NewComponentMessageHandler, shared_from_this()));
bind(&DiscoveryComponent::NewComponentMessageHandler, this, _1));
m_DiscoveryEndpoint->RegisterTopicHandler("discovery::Welcome",
bind_weak(&DiscoveryComponent::WelcomeMessageHandler, shared_from_this()));
bind(&DiscoveryComponent::WelcomeMessageHandler, this, _1));
GetEndpointManager()->ForEachEndpoint(bind(&DiscoveryComponent::NewEndpointHandler, this, _1));
GetEndpointManager()->OnNewEndpoint += bind_weak(&DiscoveryComponent::NewEndpointHandler, shared_from_this());
GetEndpointManager()->OnNewEndpoint.connect(bind(&DiscoveryComponent::NewEndpointHandler, this, _1));
GetEndpointManager()->RegisterEndpoint(m_DiscoveryEndpoint);
/* create the reconnect timer */
m_DiscoveryTimer = make_shared<Timer>();
m_DiscoveryTimer->SetInterval(30);
m_DiscoveryTimer->OnTimerExpired += bind_weak(&DiscoveryComponent::DiscoveryTimerHandler, shared_from_this());
m_DiscoveryTimer->OnTimerExpired.connect(bind(&DiscoveryComponent::DiscoveryTimerHandler, this, _1));
m_DiscoveryTimer->Start();
/* call the timer as soon as possible */
@ -109,7 +109,7 @@ int DiscoveryComponent::CheckExistingEndpoint(Endpoint::Ptr endpoint, const NewE
*/
int DiscoveryComponent::NewEndpointHandler(const NewEndpointEventArgs& neea)
{
neea.Endpoint->OnIdentityChanged += bind_weak(&DiscoveryComponent::NewIdentityHandler, shared_from_this());
neea.Endpoint->OnIdentityChanged.connect(bind(&DiscoveryComponent::NewIdentityHandler, this, _1));
/* accept discovery::RegisterComponent messages from any endpoint */
neea.Endpoint->RegisterPublication("discovery::RegisterComponent");

114
config/ax_boost_signals.m4 Normal file
View File

@ -0,0 +1,114 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_boost_signals.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_BOOST_SIGNALS
#
# DESCRIPTION
#
# Test for Signals library from the Boost C++ libraries. The macro
# requires a preceding call to AX_BOOST_BASE. Further documentation is
# available at <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_SIGNALS_LIB)
#
# And sets:
#
# HAVE_BOOST_SIGNALS
#
# LICENSE
#
# Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
# Copyright (c) 2008 Michael Tindal
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 21
AC_DEFUN([AX_BOOST_SIGNALS],
[
AC_ARG_WITH([boost-signals],
AS_HELP_STRING([--with-boost-signals@<:@=special-lib@:>@],
[use the Signals library from boost - it is possible to specify a certain library for the linker
e.g. --with-boost-signals=boost_signals-gcc-mt-d ]),
[
if test "$withval" = "no"; then
want_boost="no"
elif test "$withval" = "yes"; then
want_boost="yes"
ax_boost_user_signals_lib=""
else
want_boost="yes"
ax_boost_user_signals_lib="$withval"
fi
],
[want_boost="yes"]
)
if test "x$want_boost" = "xyes"; then
AC_REQUIRE([AC_PROG_CC])
CPPFLAGS_SAVED="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
export LDFLAGS
AC_CACHE_CHECK(whether the Boost::Signals library is available,
ax_cv_boost_signals,
[AC_LANG_PUSH([C++])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/signal.hpp>
]],
[[boost::signal<void ()> sig;
return 0;
]])],
ax_cv_boost_signals=yes, ax_cv_boost_signals=no)
AC_LANG_POP([C++])
])
if test "x$ax_cv_boost_signals" = "xyes"; then
AC_DEFINE(HAVE_BOOST_SIGNALS,,[define if the Boost::Signals library is available])
BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
if test "x$ax_boost_user_signals_lib" = "x"; then
for libextension in `ls $BOOSTLIBDIR/libboost_signals*.so* $BOOSTLIBDIR/libboost_signals*.dylib* $BOOSTLIBDIR/libboost_signals*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_signals.*\)\.so.*$;\1;' -e 's;^lib\(boost_signals.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_signals.*\)\.a.*$;\1;'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_SIGNALS_LIB="-l$ax_lib"; AC_SUBST(BOOST_SIGNALS_LIB) link_signals="yes"; break],
[link_signals="no"])
done
if test "x$link_signals" != "xyes"; then
for libextension in `ls $BOOSTLIBDIR/boost_signals*.dll* $BOOSTLIBDIR/boost_signals*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_signals.*\)\.dll.*$;\1;' -e 's;^\(boost_signals.*\)\.a*$;\1;'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_SIGNALS_LIB="-l$ax_lib"; AC_SUBST(BOOST_SIGNALS_LIB) link_signals="yes"; break],
[link_signals="no"])
done
fi
else
for ax_lib in $ax_boost_user_signals_lib boost_signals-$ax_boost_user_signals_lib; do
AC_CHECK_LIB($ax_lib, main,
[BOOST_SIGNALS_LIB="-l$ax_lib"; AC_SUBST(BOOST_SIGNALS_LIB) link_signals="yes"; break],
[link_signals="no"])
done
fi
if test "x$ax_lib" = "x"; then
AC_MSG_ERROR(Could not find a version of the library!)
fi
if test "x$link_signals" != "xyes"; then
AC_MSG_ERROR(Could not link against $ax_lib !)
fi
fi
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
fi
])

View File

@ -53,6 +53,7 @@ AX_CXX_COMPILE_STDCXX_0X
AX_CXX_GCC_ABI_DEMANGLE
AX_PTHREAD
AX_BOOST_BASE
AX_BOOST_SIGNALS
AX_BOOST_UNIT_TEST_FRAMEWORK
AX_CHECK_OPENSSL([], [AC_MSG_ERROR([You need the OpenSSL headers and libraries in order to build this application])])
AC_CHECK_LIB(ssl, SSL_new)
@ -66,7 +67,6 @@ AC_CHECK_LIB(shlwapi, PathRemoveFileSpecA)
AC_CONFIG_FILES([
Makefile
compat/Makefile
base/Makefile
components/Makefile
components/checker/Makefile

View File

@ -79,8 +79,8 @@ public:
ConstTopicIterator BeginPublications(void) const;
ConstTopicIterator EndPublications(void) const;
Observable<EventArgs> OnIdentityChanged;
Observable<EventArgs> OnSessionEstablished;
boost::signal<void (const EventArgs&)> OnIdentityChanged;
boost::signal<void (const EventArgs&)> OnSessionEstablished;
private:
string m_Identity; /**< The identity of this endpoint. */

View File

@ -109,8 +109,8 @@ void EndpointManager::AddConnection(string node, string service)
void EndpointManager::RegisterServer(JsonRpcServer::Ptr server)
{
m_Servers.push_back(server);
server->OnNewClient += bind_weak(&EndpointManager::NewClientHandler,
shared_from_this());
server->OnNewClient.connect(bind(&EndpointManager::NewClientHandler,
this, _1));
}
/**
@ -327,7 +327,7 @@ void EndpointManager::RescheduleRequestTimer(void)
if (!m_RequestTimer) {
m_RequestTimer = make_shared<Timer>();
m_RequestTimer->OnTimerExpired += bind_weak(&EndpointManager::RequestTimerHandler, shared_from_this());
m_RequestTimer->OnTimerExpired.connect(bind(&EndpointManager::RequestTimerHandler, this, _1));
}
if (it != m_Requests.end()) {

View File

@ -105,7 +105,7 @@ public:
Endpoint::Ptr GetEndpointByIdentity(string identity) const;
Observable<NewEndpointEventArgs> OnNewEndpoint;
boost::signal<void (const NewEndpointEventArgs&)> OnNewEndpoint;
private:
string m_Identity;

View File

@ -54,10 +54,10 @@ int IcingaApplication::Main(const vector<string>& args)
/* register handler for 'component' config objects */
static ConfigObject::Set::Ptr componentObjects = make_shared<ConfigObject::Set>(ConfigObject::GetAllObjects(), ConfigObject::MakeTypePredicate("component"));
function<int (const ObjectSetEventArgs<ConfigObject::Ptr>&)> NewComponentHandler = bind_weak(&IcingaApplication::NewComponentHandler, shared_from_this());
componentObjects->OnObjectAdded += NewComponentHandler;
componentObjects->OnObjectCommitted += NewComponentHandler;
componentObjects->OnObjectRemoved += bind_weak(&IcingaApplication::DeletedComponentHandler, shared_from_this());
function<int (const ObjectSetEventArgs<ConfigObject::Ptr>&)> NewComponentHandler = bind(&IcingaApplication::NewComponentHandler, this, _1);
componentObjects->OnObjectAdded.connect(NewComponentHandler);
componentObjects->OnObjectCommitted.connect(NewComponentHandler);
componentObjects->OnObjectRemoved.connect(bind(&IcingaApplication::DeletedComponentHandler, this, _1));
componentObjects->Start();
/* load config file */

View File

@ -45,10 +45,10 @@ void JsonRpcEndpoint::Connect(string node, string service, shared_ptr<SSL_CTX> s
void JsonRpcEndpoint::SetClient(JsonRpcClient::Ptr client)
{
m_Client = client;
client->OnNewMessage += bind_weak(&JsonRpcEndpoint::NewMessageHandler, shared_from_this());
client->OnClosed += bind_weak(&JsonRpcEndpoint::ClientClosedHandler, shared_from_this());
client->OnError += bind_weak(&JsonRpcEndpoint::ClientErrorHandler, shared_from_this());
client->OnVerifyCertificate += bind_weak(&JsonRpcEndpoint::VerifyCertificateHandler, shared_from_this());
client->OnNewMessage.connect(bind(&JsonRpcEndpoint::NewMessageHandler, this, _1));
client->OnClosed.connect(bind(&JsonRpcEndpoint::ClientClosedHandler, this, _1));
client->OnError.connect(bind(&JsonRpcEndpoint::ClientErrorHandler, this, _1));
client->OnVerifyCertificate.connect(bind(&JsonRpcEndpoint::VerifyCertificateHandler, this, _1));
}
bool JsonRpcEndpoint::IsLocal(void) const
@ -122,8 +122,10 @@ int JsonRpcEndpoint::ClientClosedHandler(const EventArgs&)
ClearPublications();
// remove the endpoint if there are no more subscriptions */
if (BeginSubscriptions() == EndSubscriptions())
if (BeginSubscriptions() == EndSubscriptions()) {
Hold();
GetEndpointManager()->UnregisterEndpoint(static_pointer_cast<Endpoint>(shared_from_this()));
}
m_Client.reset();

View File

@ -40,7 +40,19 @@ bool VirtualEndpoint::IsConnected(void) const
void VirtualEndpoint::RegisterTopicHandler(string topic, function<int (const NewRequestEventArgs&)> callback)
{
m_TopicHandlers[topic] += callback;
map<string, shared_ptr<boost::signal<void (const NewRequestEventArgs&)> > >::iterator it;
it = m_TopicHandlers.find(topic);
shared_ptr<boost::signal<void (const NewRequestEventArgs&)> > sig;
if (it == m_TopicHandlers.end()) {
sig = make_shared<boost::signal<void (const NewRequestEventArgs&)> >();
m_TopicHandlers.insert(make_pair(topic, sig));
} else {
sig = it->second;
}
sig->connect(callback);
RegisterSubscription(topic);
}
@ -60,16 +72,17 @@ void VirtualEndpoint::ProcessRequest(Endpoint::Ptr sender, const RequestMessage&
if (!request.GetMethod(&method))
return;
map<string, Observable<NewRequestEventArgs> >::iterator i = m_TopicHandlers.find(method);
map<string, shared_ptr<boost::signal<void (const NewRequestEventArgs&)> > >::iterator it;
it = m_TopicHandlers.find(method);
if (i == m_TopicHandlers.end())
if (it == m_TopicHandlers.end())
return;
NewRequestEventArgs nrea;
nrea.Source = shared_from_this();
nrea.Sender = sender;
nrea.Request = request;
i->second(nrea);
(*it->second)(nrea);
}
void VirtualEndpoint::ProcessResponse(Endpoint::Ptr sender, const ResponseMessage& response)

View File

@ -59,7 +59,7 @@ public:
virtual void Stop(void);
private:
map< string, Observable<NewRequestEventArgs> > m_TopicHandlers;
map< string, shared_ptr<boost::signal<void (const NewRequestEventArgs&)> > > m_TopicHandlers;
};
}

View File

@ -34,7 +34,7 @@ void JsonRpcClient::Start(void)
{
TlsClient::Start();
OnDataAvailable += bind_weak(&JsonRpcClient::DataAvailableHandler, shared_from_this());
OnDataAvailable.connect(bind(&JsonRpcClient::DataAvailableHandler, this, _1));
}
/**

View File

@ -50,7 +50,7 @@ public:
virtual void Start(void);
Observable<NewMessageEventArgs> OnNewMessage;
boost::signal<void (const NewMessageEventArgs&)> OnNewMessage;
private:
int DataAvailableHandler(const EventArgs&);