Use specific types (rather than Object::Ptr) for event handlers.

This commit is contained in:
Gunnar Beutner 2012-06-16 13:06:06 +02:00
parent 7abf1bad51
commit dbe48e501c
31 changed files with 122 additions and 84 deletions

View File

@ -465,7 +465,7 @@ int Application::Run(int argc, char **argv)
int result;
assert(!Application::m_Instance);
Application::m_Instance = static_pointer_cast<Application>(shared_from_this());
Application::m_Instance = GetSelf();
#ifndef _WIN32
struct sigaction sa;

View File

@ -90,14 +90,14 @@ bool ConfigObject::IsAbstract(void) const
void ConfigObject::Commit(void)
{
ConfigObject::Ptr dobj = GetObject(GetType(), GetName());
ConfigObject::Ptr self = static_pointer_cast<ConfigObject>(shared_from_this());
ConfigObject::Ptr self = GetSelf();
assert(!dobj || dobj == self);
m_Container->CheckObject(self);
}
void ConfigObject::Unregister(void)
{
ConfigObject::Ptr self = static_pointer_cast<ConfigObject>(shared_from_this());
ConfigObject::Ptr self = GetSelf();
m_Container->RemoveObject(self);
}

View File

@ -44,7 +44,7 @@ Object::~Object(void)
*/
void Object::Hold(void)
{
m_HeldObjects.push_back(shared_from_this());
m_HeldObjects.push_back(GetSelf());
}
/**
@ -55,3 +55,7 @@ void Object::ClearHeldObjects(void)
m_HeldObjects.clear();
}
SharedPtrHolder Object::GetSelf(void)
{
return SharedPtrHolder(shared_from_this());
}

View File

@ -23,6 +23,8 @@
namespace icinga
{
class SharedPtrHolder;
/**
* Base class for all heap-allocated objects. At least one of its methods
* has to be virtual for RTTI to work.
@ -43,6 +45,8 @@ protected:
void Hold(void);
SharedPtrHolder GetSelf(void);
private:
Object(const Object& other);
Object operator=(const Object& rhs);
@ -50,6 +54,39 @@ private:
static vector<Object::Ptr> m_HeldObjects;
};
/**
* Holds a shared pointer and provides support for implicit upcasts.
*/
class SharedPtrHolder
{
public:
explicit SharedPtrHolder(const shared_ptr<Object>& object)
: m_Object(object)
{ }
template<typename T>
operator shared_ptr<T>(void) const
{
#ifdef _DEBUG
shared_ptr<T> other = dynamic_pointer_cast<T>(m_Object);
assert(other);
#else /* _DEBUG */
shared_ptr<T> other = static_pointer_cast<T>(m_Object);
#endif /* _DEBUG */
return other;
}
template<typename T>
operator weak_ptr<T>(void) const
{
return static_cast<shared_ptr<T> >(*this);
}
private:
shared_ptr<Object> m_Object;
};
/**
* Compares a weak pointer with a raw pointer.
*/

View File

@ -61,7 +61,7 @@ public:
Range range = GetRange(key);
for (Iterator it = range.first; it != range.second; it++) {
callback(shared_from_this(), *it);
callback(GetSelf(), *it);
}
}

View File

@ -55,7 +55,7 @@ public:
void AddObject(const TValue& object)
{
m_Objects.insert(object);
OnObjectAdded(shared_from_this(), object);
OnObjectAdded(GetSelf(), object);
}
void RemoveObject(const TValue& object)
@ -64,7 +64,7 @@ public:
if (it != m_Objects.end()) {
m_Objects.erase(it);
OnObjectRemoved(shared_from_this(), object);
OnObjectRemoved(GetSelf(), object);
}
}
@ -81,14 +81,14 @@ public:
if (!Contains(object)) {
AddObject(object);
} else {
OnObjectCommitted(shared_from_this(), object);
OnObjectCommitted(GetSelf(), object);
}
}
}
boost::signal<void (const Object::Ptr&, const TValue&)> OnObjectAdded;
boost::signal<void (const Object::Ptr&, const TValue&)> OnObjectCommitted;
boost::signal<void (const Object::Ptr&, const TValue&)> OnObjectRemoved;
boost::signal<void (const typename ObjectSet<TValue>::Ptr&, const TValue&)> OnObjectAdded;
boost::signal<void (const typename ObjectSet<TValue>::Ptr&, const TValue&)> OnObjectCommitted;
boost::signal<void (const typename ObjectSet<TValue>::Ptr&, const TValue&)> OnObjectRemoved;
Iterator Begin(void)
{
@ -103,7 +103,7 @@ public:
void ForeachObject(function<void (const typename Object::Ptr&, const TValue&)> callback)
{
for (Iterator it = Begin(); it != End(); it++) {
callback(shared_from_this(), *it);
callback(GetSelf(), *it);
}
}

View File

@ -52,7 +52,7 @@ void Socket::Start(void)
OnException.connect(boost::bind(&Socket::ExceptionEventHandler, this));
Sockets.push_back(static_pointer_cast<Socket>(shared_from_this()));
Sockets.push_back(GetSelf());
}
/**
@ -125,7 +125,7 @@ void Socket::CloseInternal(bool from_dtor)
if (!from_dtor) {
Stop();
OnClosed(shared_from_this());
OnClosed(GetSelf());
}
}
@ -170,7 +170,7 @@ int Socket::GetLastSocketError(void)
void Socket::HandleSocketError(const std::exception& ex)
{
if (!OnError.empty()) {
OnError(shared_from_this(), ex);
OnError(GetSelf(), ex);
Close();
} else {

View File

@ -42,12 +42,12 @@ public:
void SetFD(SOCKET fd);
SOCKET GetFD(void) const;
boost::signal<void (const Object::Ptr&)> OnReadable;
boost::signal<void (const Object::Ptr&)> OnWritable;
boost::signal<void (const Object::Ptr&)> OnException;
boost::signal<void (const Socket::Ptr&)> OnReadable;
boost::signal<void (const Socket::Ptr&)> OnWritable;
boost::signal<void (const Socket::Ptr&)> OnException;
boost::signal<void (const Object::Ptr&, const std::exception&)> OnError;
boost::signal<void (const Object::Ptr&)> OnClosed;
boost::signal<void (const Socket::Ptr&, const std::exception&)> OnError;
boost::signal<void (const Socket::Ptr&)> OnClosed;
virtual bool WantsToRead(void) const;
virtual bool WantsToWrite(void) const;

View File

@ -159,7 +159,7 @@ void TcpClient::ReadableEventHandler(void)
m_RecvQueue->Write(NULL, rc);
OnDataAvailable(shared_from_this());
OnDataAvailable(GetSelf());
}
/**

View File

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

View File

@ -93,7 +93,7 @@ void TcpServer::ReadableEventHandler(void)
client->SetFD(fd);
client->Start();
OnNewClient(shared_from_this(), client);
OnNewClient(GetSelf(), client);
}
/**

View File

@ -44,7 +44,7 @@ public:
void Listen(void);
boost::signal<void (const Object::Ptr&, const TcpClient::Ptr&)> OnNewClient;
boost::signal<void (const TcpServer::Ptr&, const TcpClient::Ptr&)> OnNewClient;
virtual bool WantsToRead(void) const;

View File

@ -100,7 +100,7 @@ void Timer::CallExpiredTimers(void)
*/
void Timer::Call(void)
{
OnTimerExpired(shared_from_this());
OnTimerExpired(GetSelf());
}
/**
@ -130,7 +130,7 @@ void Timer::Start(void)
{
Stop();
Timers.push_back(static_pointer_cast<Timer>(shared_from_this()));
Timers.push_back(GetSelf());
Reschedule(time(NULL) + m_Interval);
}

View File

@ -52,7 +52,7 @@ public:
void Reschedule(time_t next);
boost::signal<void(const Object::Ptr&)> OnTimerExpired;
boost::signal<void(const Timer::Ptr&)> OnTimerExpired;
private:
time_t m_Interval; /**< The interval of the timer. */

View File

@ -136,7 +136,7 @@ void TlsClient::ReadableEventHandler(void)
GetRecvQueue()->Write(NULL, rc);
OnDataAvailable(shared_from_this());
OnDataAvailable(GetSelf());
}
/**
@ -244,7 +244,7 @@ int TlsClient::SSLVerifyCertificate(int ok, X509_STORE_CTX *x509Context)
bool valid = false;
shared_ptr<X509> x509Certificate = shared_ptr<X509>(x509Context->cert, &TlsClient::NullCertificateDeleter);
client->OnVerifyCertificate(client->shared_from_this(), valid, x509Context, x509Certificate);
client->OnVerifyCertificate(client->GetSelf(), valid, x509Context, x509Certificate);
return valid ? 1 : 0;
}

View File

@ -41,7 +41,7 @@ public:
virtual bool WantsToRead(void) const;
virtual bool WantsToWrite(void) const;
boost::signal<void (const Object::Ptr&, bool&, X509_STORE_CTX *, const shared_ptr<X509>&)> OnVerifyCertificate;
boost::signal<void (const TlsClient::Ptr&, bool&, X509_STORE_CTX *, const shared_ptr<X509>&)> OnVerifyCertificate;
protected:
void HandleSSLError(void);

View File

@ -69,12 +69,11 @@ void ConfigRpcComponent::NewEndpointHandler(const Endpoint::Ptr& endpoint)
endpoint->OnSessionEstablished.connect(boost::bind(&ConfigRpcComponent::SessionEstablishedHandler, this, _1));
}
void ConfigRpcComponent::SessionEstablishedHandler(const Object::Ptr& source)
void ConfigRpcComponent::SessionEstablishedHandler(const Endpoint::Ptr& endpoint)
{
RequestMessage request;
request.SetMethod("config::FetchObjects");
Endpoint::Ptr endpoint = static_pointer_cast<Endpoint>(source);
GetEndpointManager()->SendUnicastMessage(m_ConfigRpcEndpoint, endpoint, request);
}

View File

@ -37,7 +37,7 @@ private:
VirtualEndpoint::Ptr m_ConfigRpcEndpoint;
void NewEndpointHandler(const Endpoint::Ptr& endpoint);
void SessionEstablishedHandler(const Object::Ptr& source);
void SessionEstablishedHandler(const Endpoint::Ptr& endpoint);
void LocalObjectCommittedHandler(const ConfigObject::Ptr& object);
void LocalObjectRemovedHandler(const ConfigObject::Ptr& object);

View File

@ -170,9 +170,8 @@ bool DiscoveryComponent::GetComponentDiscoveryInfo(string component, ComponentDi
* @param ea Event arguments for the component.
* @returns 0
*/
void DiscoveryComponent::NewIdentityHandler(const Object::Ptr& source)
void DiscoveryComponent::NewIdentityHandler(const Endpoint::Ptr& endpoint)
{
Endpoint::Ptr endpoint = static_pointer_cast<Endpoint>(source);
string identity = endpoint->GetIdentity();
if (identity == GetEndpointManager()->GetIdentity()) {

View File

@ -57,7 +57,7 @@ private:
Timer::Ptr m_DiscoveryTimer;
void NewEndpointHandler(const Endpoint::Ptr& endpoint);
void NewIdentityHandler(const Object::Ptr& source);
void NewIdentityHandler(const Endpoint::Ptr& endpoint);
void NewComponentMessageHandler(const RequestMessage& request);
void RegisterComponentMessageHandler(const Endpoint::Ptr& sender, const RequestMessage& request);

View File

@ -128,7 +128,7 @@ void ConfigItem::Commit(void)
dobj->Commit();
ConfigItem::Ptr ci = GetObject(GetType(), GetName());
ConfigItem::Ptr self = static_pointer_cast<ConfigItem>(shared_from_this());
ConfigItem::Ptr self = GetSelf();
if (ci && ci != self) {
ci->m_ConfigObject.reset();
GetAllObjects()->RemoveObject(ci);
@ -140,8 +140,7 @@ void ConfigItem::Unregister(void)
{
// TODO: unregister associated ConfigObject
ConfigItem::Ptr self = static_pointer_cast<ConfigItem>(shared_from_this());
GetAllObjects()->RemoveObject(self);
GetAllObjects()->RemoveObject(GetSelf());
}
ConfigItem::Ptr ConfigItem::GetObject(const string& type, const string& name)

View File

@ -48,7 +48,7 @@ string Endpoint::GetIdentity(void) const
void Endpoint::SetIdentity(string identity)
{
m_Identity = identity;
OnIdentityChanged(shared_from_this());
OnIdentityChanged(GetSelf());
}
/**

View File

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

View File

@ -150,10 +150,10 @@ void EndpointManager::RegisterEndpoint(Endpoint::Ptr endpoint)
if (!endpoint->IsLocal() && endpoint->GetIdentity() != "")
throw invalid_argument("Identity must be empty.");
endpoint->SetEndpointManager(static_pointer_cast<EndpointManager>(shared_from_this()));
endpoint->SetEndpointManager(GetSelf());
m_Endpoints.push_back(endpoint);
OnNewEndpoint(shared_from_this(), endpoint);
OnNewEndpoint(GetSelf(), endpoint);
}
/**
@ -253,14 +253,14 @@ void EndpointManager::SendMulticastMessage(Endpoint::Ptr sender,
*
* @param callback The callback function.
*/
void EndpointManager::ForEachEndpoint(function<void (const Object::Ptr&, const Endpoint::Ptr&)> callback)
void EndpointManager::ForEachEndpoint(function<void (const EndpointManager::Ptr&, const Endpoint::Ptr&)> callback)
{
vector<Endpoint::Ptr>::iterator prev, i;
for (i = m_Endpoints.begin(); i != m_Endpoints.end(); ) {
prev = i;
i++;
callback(shared_from_this(), *prev);
callback(GetSelf(), *prev);
}
}
@ -282,7 +282,7 @@ Endpoint::Ptr EndpointManager::GetEndpointByIdentity(string identity) const
void EndpointManager::SendAPIMessage(Endpoint::Ptr sender,
RequestMessage& message,
function<void(const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&, const ResponseMessage&, bool TimedOut)> callback, time_t timeout)
function<void(const EndpointManager::Ptr&, const Endpoint::Ptr, const RequestMessage&, const ResponseMessage&, bool TimedOut)> callback, time_t timeout)
{
m_NextMessageID++;
@ -337,7 +337,7 @@ void EndpointManager::RequestTimerHandler(void)
map<string, PendingRequest>::iterator it;
for (it = m_Requests.begin(); it != m_Requests.end(); it++) {
if (it->second.HasTimedOut()) {
it->second.Callback(shared_from_this(), Endpoint::Ptr(), it->second.Request, ResponseMessage(), true);
it->second.Callback(GetSelf(), Endpoint::Ptr(), it->second.Request, ResponseMessage(), true);
m_Requests.erase(it);
@ -360,7 +360,7 @@ void EndpointManager::ProcessResponseMessage(const Endpoint::Ptr& sender, const
if (it == m_Requests.end())
return;
it->second.Callback(shared_from_this(), sender, it->second.Request, message, false);
it->second.Callback(GetSelf(), sender, it->second.Request, message, false);
m_Requests.erase(it);
RescheduleRequestTimer();

View File

@ -23,23 +23,6 @@
namespace icinga
{
/**
* Information about a pending API request.
*
* @ingroup icinga
*/
struct I2_ICINGA_API PendingRequest
{
time_t Timeout;
RequestMessage Request;
function<void(const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&, const ResponseMessage&, bool TimedOut)> Callback;
bool HasTimedOut(void) const
{
return time(NULL) > Timeout;
}
};
/**
* Forwards messages between endpoints.
*
@ -72,15 +55,15 @@ public:
void SendMulticastMessage(Endpoint::Ptr sender, const RequestMessage& message);
void SendAPIMessage(Endpoint::Ptr sender, RequestMessage& message,
function<void(const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&, const ResponseMessage&, bool TimedOut)> callback, time_t timeout = 10);
function<void(const EndpointManager::Ptr&, const Endpoint::Ptr, const RequestMessage&, const ResponseMessage&, bool TimedOut)> callback, time_t timeout = 10);
void ProcessResponseMessage(const Endpoint::Ptr& sender, const ResponseMessage& message);
void ForEachEndpoint(function<void (const Object::Ptr&, const Endpoint::Ptr&)> callback);
void ForEachEndpoint(function<void (const EndpointManager::Ptr&, const Endpoint::Ptr&)> callback);
Endpoint::Ptr GetEndpointByIdentity(string identity) const;
boost::signal<void (const Object::Ptr&, const Endpoint::Ptr&)> OnNewEndpoint;
boost::signal<void (const EndpointManager::Ptr&, const Endpoint::Ptr&)> OnNewEndpoint;
private:
string m_Identity;
@ -89,6 +72,23 @@ private:
vector<JsonRpcServer::Ptr> m_Servers;
vector<Endpoint::Ptr> m_Endpoints;
/**
* Information about a pending API request.
*
* @ingroup icinga
*/
struct I2_ICINGA_API PendingRequest
{
time_t Timeout;
RequestMessage Request;
function<void(const EndpointManager::Ptr&, const Endpoint::Ptr, const RequestMessage&, const ResponseMessage&, bool TimedOut)> Callback;
bool HasTimedOut(void) const
{
return time(NULL) > Timeout;
}
};
long m_NextMessageID;
map<string, PendingRequest> m_Requests;
Timer::Ptr m_RequestTimer;

View File

@ -82,7 +82,7 @@ void JsonRpcEndpoint::ProcessResponse(Endpoint::Ptr sender, const ResponseMessag
void JsonRpcEndpoint::NewMessageHandler(const MessagePart& message)
{
Endpoint::Ptr sender = static_pointer_cast<Endpoint>(shared_from_this());
Endpoint::Ptr sender = GetSelf();
if (ResponseMessage::IsResponseMessage(message)) {
/* rather than routing the message to the right virtual
@ -121,7 +121,7 @@ void JsonRpcEndpoint::ClientClosedHandler(void)
// remove the endpoint if there are no more subscriptions */
if (BeginSubscriptions() == EndSubscriptions()) {
Hold();
GetEndpointManager()->UnregisterEndpoint(static_pointer_cast<Endpoint>(shared_from_this()));
GetEndpointManager()->UnregisterEndpoint(GetSelf());
}
m_Client.reset();

View File

@ -38,15 +38,15 @@ bool VirtualEndpoint::IsConnected(void) const
return true;
}
void VirtualEndpoint::RegisterTopicHandler(string topic, function<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback)
void VirtualEndpoint::RegisterTopicHandler(string topic, function<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback)
{
map<string, shared_ptr<boost::signal<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > >::iterator it;
map<string, shared_ptr<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > >::iterator it;
it = m_TopicHandlers.find(topic);
shared_ptr<boost::signal<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > sig;
shared_ptr<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > sig;
if (it == m_TopicHandlers.end()) {
sig = boost::make_shared<boost::signal<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> >();
sig = boost::make_shared<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> >();
m_TopicHandlers.insert(make_pair(topic, sig));
} else {
sig = it->second;
@ -57,7 +57,7 @@ void VirtualEndpoint::RegisterTopicHandler(string topic, function<void (const Ob
RegisterSubscription(topic);
}
void VirtualEndpoint::UnregisterTopicHandler(string topic, function<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback)
void VirtualEndpoint::UnregisterTopicHandler(string topic, function<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback)
{
// TODO: implement
//m_TopicHandlers[method] -= callback;
@ -72,13 +72,13 @@ void VirtualEndpoint::ProcessRequest(Endpoint::Ptr sender, const RequestMessage&
if (!request.GetMethod(&method))
return;
map<string, shared_ptr<boost::signal<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > >::iterator it;
map<string, shared_ptr<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > >::iterator it;
it = m_TopicHandlers.find(method);
if (it == m_TopicHandlers.end())
return;
(*it->second)(shared_from_this(), sender, request);
(*it->second)(GetSelf(), sender, request);
}
void VirtualEndpoint::ProcessResponse(Endpoint::Ptr sender, const ResponseMessage& response)

View File

@ -34,8 +34,8 @@ public:
typedef shared_ptr<VirtualEndpoint> Ptr;
typedef weak_ptr<VirtualEndpoint> WeakPtr;
void RegisterTopicHandler(string topic, function<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback);
void UnregisterTopicHandler(string topic, function<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback);
void RegisterTopicHandler(string topic, function<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback);
void UnregisterTopicHandler(string topic, function<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> callback);
virtual string GetAddress(void) const;
@ -48,7 +48,7 @@ public:
virtual void Stop(void);
private:
map< string, shared_ptr<boost::signal<void (const Object::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > > m_TopicHandlers;
map< string, shared_ptr<boost::signal<void (const VirtualEndpoint::Ptr&, const Endpoint::Ptr, const RequestMessage&)> > > m_TopicHandlers;
};
}

View File

@ -57,7 +57,7 @@ void JsonRpcClient::DataAvailableHandler(void)
return;
message = MessagePart(jsonString);
OnNewMessage(shared_from_this(), message);
OnNewMessage(GetSelf(), message);
} catch (const Exception& ex) {
Application::Log(LogCritical, "jsonrpc", "Exception while processing message from JSON-RPC client: " + string(ex.GetMessage()));
Close();

View File

@ -38,7 +38,7 @@ public:
void SendMessage(const MessagePart& message);
boost::signal<void (const Object::Ptr&, const MessagePart&)> OnNewMessage;
boost::signal<void (const JsonRpcClient::Ptr&, const MessagePart&)> OnNewMessage;
private:
void DataAvailableHandler(void);

View File

@ -301,6 +301,6 @@ char *collapse(char *pattern)
}
while (*m++);
};
return mask;
return pattern;
}