/*
* freescope - Free source browser
* Copyright (C) 2001 Olivier Deme
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
// FILE: siglink.cpp
/************/
/* INCLUDES */
/************/
#include <assert.h>
#include <signal.h>
#include "siglink.h"
/**************************/
/* STATIC INITIALIZATIONS */
/**************************/
SigLink* SigLink::m_instance = NULL;
Signal_map SigLink::m_signalhdl;
/*
* FUNCTION: SigLink::~SigLink
*
* DESCRIPTION: Destructor
*
* IN:
* IN-OUT:
* RETURN CODE:
*/
SigLink::~SigLink ()
{
}
/*
* FUNCTION: SigLink::instance
*
* DESCRIPTION: This function creates an instance of SigLink if this one is
* not already existing, or returns a pointer to it otherwise
* (cf singleton).
*
* IN:
* IN-OUT:
* RETURN CODE: A pointer to THE SigLink object.
*/
SigLink* SigLink::instance ()
throw (bad_alloc)
{
if (m_instance == NULL)
m_instance = new SigLink;
return m_instance;
};
/*
* FUNCTION: SigLink::Register
*
* DESCRIPTION: This function registers a callback function with a signal
* inside the handlers attribute
*
* IN: signo The signal
* handler The callback function
* arg An optional argument passed to the callback
* IN-OUT:
* RETURN CODE:
*/
void SigLink::Register (int signo,
Handler handler,
void* arg)
throw (bad_alloc, SigLink_Exception)
{
assert ((signo >= 0) && (handler != NULL));
Handler_map* handlers;
// Check if we have already a map corresponding to this signal
if (m_signalhdl.find(signo) == m_signalhdl.end())
{
// No handler registered yet for this signal...
handlers = new Handler_map;
m_signalhdl.insert(make_pair(signo, handlers));
// Insert signal handler
handlers->insert(make_pair(handler, arg));
}
else
{
handlers = m_signalhdl[signo];
if (handlers->find(handler) != handlers->end())
{
return; // Handler already registered!
}
handlers->insert(make_pair(handler, arg));
}
// Register the signal
if (signal(signo, SigHandler) == SIG_ERR)
throw(SigLink_Exception(SigLink_Exception::SIGLINK_SIGNAL_FAILED));
}
/*
* FUNCTION: SigLink::Deregister
*
* DESCRIPTION: This function de-registers a callback function associated
* with a signal.
*
* IN: signo The signal
* handler The callback function
* IN-OUT:
* RETURN CODE:
*/
void SigLink::Deregister (int signo,
Handler handler)
throw (SigLink_Exception)
{
assert ((signo >= 0) && (handler != NULL));
if (m_signalhdl.find(signo) == m_signalhdl.end())
{
throw(SigLink_Exception::SIGLINK_NO_SUCH_HANDLER);
return;
}
Handler_map* handlers;
Handler_map::iterator it;
handlers = m_signalhdl[signo];
if ((it = handlers->find(handler)) == handlers->end())
{
throw(SigLink_Exception::SIGLINK_NO_SUCH_HANDLER);
return;
}
// Remove handler from list.
handlers->erase(it);
// Check if we still need to be notified for the signal
if (handlers->empty() == true)
{
// remove handlers map from signal map
m_signalhdl.erase(signo);
signal(signo, SIG_IGN);
}
}
/*
* FUNCTION: SigLink::SigHandler
*
* DESCRIPTION: This function calls all the handlers that have been registered
* for this particular signal
*
* IN: signo The signal
* IN-OUT:
* RETURN CODE:
*/
void SigLink::SigHandler (int signo)
throw()
{
signal(signo, SIG_IGN);
// Check that at least one handler has registered for this signal!
assert(m_signalhdl.find(signo) != m_signalhdl.end());
Handler_map* handlers;
Handler_map::iterator it;
handlers = m_signalhdl[signo];
// Call all the callbacks
for (it = handlers->begin(); it != handlers->end(); it++)
(*it).first(signo, (*it).second);
signal(signo, SigLink::SigHandler);
}
/*
* FUNCTION: SigLink_Exception::what
*
* DESCRIPTION: This function returns a string description of an error
* code.
*
* IN:
* IN-OUT:
* RETURN CODE: A string description of the exception
*/
string SigLink_Exception::what () const
throw ()
{
string description("SigLink exception -> ");
switch (m_error)
{
case SIGLINK_SIGNAL_FAILED:
description.append("signal() failed");
break;
case SIGLINK_NO_SUCH_HANDLER:
description.append("Signal handler not registered");
break;
default: description.append("No description");
break;
}
return description;
}
syntax highlighted by Code2HTML, v. 0.9.1