Files
rtabmap/utilite/src/UEventsManager.cpp

470 lines
10 KiB
C++
Raw Normal View History

/*
* utilite is a cross-platform library with
* useful utilities for fast and small developing.
* Copyright (C) 2010 Mathieu Labbe
*
* utilite is free library: 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.
*
* utilite 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rtabmap/utilite/UEventsManager.h"
#include "rtabmap/utilite/UEvent.h"
#include <list>
#include "rtabmap/utilite/UStl.h"
UEventsManager* UEventsManager::instance_ = 0;
UDestroyer<UEventsManager> UEventsManager::destroyer_;
void UEventsManager::addHandler(UEventsHandler* handler)
{
if(!handler)
{
UERROR("Handler is null!");
return;
}
else
{
UEventsManager::getInstance()->_addHandler(handler);
}
}
void UEventsManager::removeHandler(UEventsHandler* handler)
{
if(!handler)
{
UERROR("Handler is null!");
return;
}
else
{
UEventsManager::getInstance()->_removeHandler(handler);
}
}
void UEventsManager::post(UEvent * event, bool async, const UEventsSender * sender)
{
if(!event)
{
UERROR("Event is null!");
return;
}
else
{
UEventsManager::getInstance()->_postEvent(event, async, sender);
}
}
void UEventsManager::createPipe(
const UEventsSender * sender,
const UEventsHandler * receiver,
const std::string & eventName)
{
if(!sender || !receiver)
{
UERROR("Sender and/or receiver is null!");
return;
}
else
{
UEventsManager::getInstance()->_createPipe(sender, receiver, eventName);
}
}
void UEventsManager::removePipe(
const UEventsSender * sender,
const UEventsHandler * receiver,
const std::string & eventName)
{
if(!sender || !receiver)
{
UERROR("Sender and/or receiver is null!");
return;
}
else
{
UEventsManager::getInstance()->_removePipe(sender, receiver, eventName);
}
}
void UEventsManager::removeAllPipes(const UEventsSender * sender)
{
if(!sender)
{
UERROR("Sender is null!");
return;
}
else
{
UEventsManager::getInstance()->_removeAllPipes(sender);
}
}
void UEventsManager::removeNullPipes(const UEventsSender * sender)
{
if(!sender)
{
UERROR("Sender is null!");
return;
}
else
{
UEventsManager::getInstance()->_removeNullPipes(sender);
}
}
UEventsManager* UEventsManager::getInstance()
{
if(!instance_)
{
instance_ = new UEventsManager();
destroyer_.setDoomed(instance_);
instance_->start(); // Start the thread
}
return instance_;
}
UEventsManager::UEventsManager()
{
}
UEventsManager::~UEventsManager()
{
join(true);
// Free memory
for(std::list<std::pair<UEvent*, const UEventsSender*> >::iterator it=events_.begin(); it!=events_.end(); ++it)
{
delete it->first;
}
events_.clear();
handlers_.clear();
instance_ = 0;
}
void UEventsManager::mainLoop()
{
postEventSem_.acquire();
if(!this->isKilled())
{
dispatchEvents();
}
}
void UEventsManager::mainLoopKill()
{
postEventSem_.release();
}
void UEventsManager::dispatchEvents()
{
if(events_.size() == 0)
{
return;
}
std::list<std::pair<UEvent*, const UEventsSender*> >::iterator it;
std::list<std::pair<UEvent*, const UEventsSender*> > eventsBuf;
// Copy events in a buffer :
// Other threads can post events
// while events are handled.
eventsMutex_.lock();
{
eventsBuf = events_;
events_.clear();
}
eventsMutex_.unlock();
// Past events to handlers
for(it=eventsBuf.begin(); it!=eventsBuf.end(); ++it)
{
dispatchEvent(it->first, it->second);
delete it->first;
}
eventsBuf.clear();
}
void UEventsManager::dispatchEvent(UEvent * event, const UEventsSender * sender)
{
std::list<UEventsHandler*> handlers;
// Verify if there are pipes with the sender for his type of event
if(sender)
{
handlers = getPipes(sender, event->getClassName());
}
handlersMutex_.lock();
if(handlers.size() == 0)
{
//No pipes, send to all handlers
handlers = handlers_;
}
for(std::list<UEventsHandler*>::iterator it=handlers.begin(); it!=handlers.end(); ++it)
{
// Check if the handler is still in the
// handlers_ list (may be changed if addHandler() or
// removeHandler() is called in EventsHandler::handleEvent())
if(std::find(handlers_.begin(), handlers_.end(), *it) != handlers_.end())
{
UEventsHandler * handler = *it;
handlersMutex_.unlock();
// Don't process event if the handler is the same as the sender
if(handler != sender)
{
// To be able to add/remove an handler in a handleEvent call (without a deadlock)
// @see _addHandler(), _removeHandler()
handler->handleEvent(event);
}
handlersMutex_.lock();
}
}
handlersMutex_.unlock();
}
void UEventsManager::_addHandler(UEventsHandler* handler)
{
if(!this->isKilled())
{
handlersMutex_.lock();
{
//make sure it is not already in the list
bool handlerFound = false;
for(std::list<UEventsHandler*>::iterator it=handlers_.begin(); it!=handlers_.end(); ++it)
{
if(*it == handler)
{
handlerFound = true;
}
}
if(!handlerFound)
{
handlers_.push_back(handler);
}
}
handlersMutex_.unlock();
}
}
void UEventsManager::_removeHandler(UEventsHandler* handler)
{
if(!this->isKilled())
{
handlersMutex_.lock();
{
for (std::list<UEventsHandler*>::iterator it = handlers_.begin(); it!=handlers_.end(); ++it)
{
if(*it == handler)
{
handlers_.erase(it);
break;
}
}
}
handlersMutex_.unlock();
pipesMutex_.lock();
{
for(std::list<Pipe>::iterator iter=pipes_.begin(); iter!= pipes_.end(); ++iter)
{
if(iter->receiver_ == handler)
{
iter->receiver_ = 0; // set to null
}
}
}
pipesMutex_.unlock();
}
}
void UEventsManager::_postEvent(UEvent * event, bool async, const UEventsSender * sender)
{
if(!this->isKilled())
{
if(async)
{
eventsMutex_.lock();
{
events_.push_back(std::make_pair(event, sender));
}
eventsMutex_.unlock();
// Signal the EventsManager that an Event is added
postEventSem_.release();
}
else
{
dispatchEvent(event, sender);
delete event;
}
}
else
{
delete event;
}
}
std::list<UEventsHandler*> UEventsManager::getPipes(
const UEventsSender * sender,
const std::string & eventName)
{
std::list<UEventsHandler*> pipes;
pipesMutex_.lock();
for(std::list<Pipe>::iterator iter=pipes_.begin(); iter!= pipes_.end(); ++iter)
{
if(iter->sender_ == sender && iter->eventName_.compare(eventName) == 0)
{
bool added = false;
if(iter->receiver_)
{
handlersMutex_.lock();
for(std::list<UEventsHandler*>::iterator jter=handlers_.begin(); jter!=handlers_.end(); ++jter)
{
if(*jter == iter->receiver_)
{
pipes.push_back(*jter);
added = true;
break;
}
}
handlersMutex_.unlock();
}
if(!added)
{
// Add nulls
pipes.push_back(0);
}
}
}
pipesMutex_.unlock();
return pipes;
}
void UEventsManager::_createPipe(
const UEventsSender * sender,
const UEventsHandler * receiver,
const std::string & eventName)
{
pipesMutex_.lock();
bool exist = false;
for(std::list<Pipe>::iterator iter=pipes_.begin(); iter!= pipes_.end();++iter)
{
if(iter->sender_ == sender && iter->receiver_ == receiver && iter->eventName_.compare(eventName) == 0)
{
exist = true;
break;
}
}
if(!exist)
{
bool handlerFound = false;
handlersMutex_.lock();
for(std::list<UEventsHandler*>::iterator iter=handlers_.begin(); iter!=handlers_.end(); ++iter)
{
if(*iter == receiver)
{
handlerFound = true;
break;
}
}
handlersMutex_.unlock();
if(handlerFound)
{
pipes_.push_back(Pipe(sender, receiver, eventName));
}
else
{
UERROR("Cannot create the pipe because the receiver is not yet "
"added to UEventsManager's handlers list.");
}
}
else
{
UWARN("Pipe between sender %p and receiver %p with event %s was already created.",
sender, receiver, eventName.c_str());
}
pipesMutex_.unlock();
}
void UEventsManager::_removePipe(
const UEventsSender * sender,
const UEventsHandler * receiver,
const std::string & eventName)
{
pipesMutex_.lock();
bool removed = false;
for(std::list<Pipe>::iterator iter=pipes_.begin(); iter!= pipes_.end();)
{
if(iter->sender_ == sender && iter->receiver_ == receiver && iter->eventName_.compare(eventName) == 0)
{
iter = pipes_.erase(iter);
removed = true;
}
else
{
++iter;
}
}
if(!removed)
{
UWARN("Pipe between sender %p and receiver %p with event %s didn't exist.",
sender, receiver, eventName.c_str());
}
pipesMutex_.unlock();
}
void UEventsManager::_removeAllPipes(const UEventsSender * sender)
{
pipesMutex_.lock();
for(std::list<Pipe>::iterator iter=pipes_.begin(); iter!=pipes_.end();)
{
if(iter->sender_ == sender)
{
iter = pipes_.erase(iter);
}
else
{
++iter;
}
}
pipesMutex_.unlock();
}
void UEventsManager::_removeNullPipes(const UEventsSender * sender)
{
pipesMutex_.lock();
for(std::list<Pipe>::iterator iter=pipes_.begin(); iter!=pipes_.end();)
{
if(iter->receiver_ == 0)
{
iter = pipes_.erase(iter);
}
else
{
++iter;
}
}
pipesMutex_.unlock();
}