/*
* Copyright (C) 2004 Alo Sarv <madcat_@users.sourceforge.net>
*
* 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
*/
#include <hn/event.h>
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
// intrusive-ptr requirements
// --------------------------
std::map<void*, uint32_t> ptrs;
typedef std::map<void*, uint32_t>::iterator Iter;
template<typename T>
void intrusive_ptr_add_ref(T *ptr) {
Iter i = ptrs.find(ptr);
if (i == ptrs.end()) {
i = ptrs.insert(ptrs.end(), std::make_pair(ptr, 1));
} else {
(*i).second++;
}
std::cerr << (*i).first << ": refcnt=" << (*i).second << std::endl;
}
template<typename T>
void intrusive_ptr_release(T *ptr) {
Iter i = ptrs.find(ptr);
if (i != ptrs.end() && (*i).second == 1) {
std::cerr << (*i).first << ": Deleting." << std::endl;
delete (*i).first;
ptrs.erase(i);
} else {
(*i).second--;
std::cerr << (*i).first << ": refcnt=" << (*i).second << std::endl;
}
}
// Event object. This is the event being passed from MySource to MyHandler
// through event tables.
class MyEvent {
public:
MyEvent(const std::string &msg) : m_data(msg) {}
friend std::ostream& operator<<(std::ostream &o, const MyEvent &evt) {
return o << evt.m_data;
}
std::string m_data;
};
// Event source class. Notice how there is no references to event tables in
// this class.
class MySource {
public:
MySource() {
// Post an event during construction to test the usage of `this'
EHS::postEvent(this, MyEvent("Constructing MySource"));
}
~MySource() {
// Post an event in destructor to verify we don't crash this way
EHS::postEvent(this, MyEvent("Destroying MySource"));
}
};
// Event handler class
class MyHandler {
public:
MyHandler() {}
// Overloaded event handler, used for different ways MySource posts
// events.
void handler(MySource *src, MyEvent evt) {
std::cerr << "Received event: " << evt << std::endl;
}
void handler(boost::intrusive_ptr<MySource> src, MyEvent evt) {
std::cerr << "Received (intrusive) event: " << evt << std::endl;
}
void handler(boost::shared_ptr<MySource> src, MyEvent evt) {
std::cerr << "Received (shared) event: " << evt << std::endl;
}
};
// Driver
int main() {
// Initialize objects.
MyHandler *h = new MyHandler;
MySource *s = new MySource;
// Set up handler, and post an event "externally"
EHS::addHandler(s, h, &MyHandler::handler);
EHS::postEvent(s, MyEvent("Hello world!"));
delete s; // delete the source
EventMain::instance().handlePending();
{ // event source is in intrusive_ptr wrapper
boost::intrusive_ptr<MySource> src(new MySource);
EHS::addHandler(src, h, &MyHandler::handler);
EHS::addHandler(src.get(), h, &MyHandler::handler);
EHS::postEvent(src, MyEvent("Intrusive hello!"));
EventMain::instance().handlePending();
}
{ // event source is in shared_ptr wrapper
boost::shared_ptr<MySource> src(new MySource);
EHS::addHandler(src, h, &MyHandler::handler);
EHS::addHandler(src.get(), h, &MyHandler::handler);
EHS::postEvent(src, MyEvent("Shared hello!"));
EventMain::instance().handlePending();
}
delete h;
// (just don't close the console window yet (win32-specific))
std::cin.get();
}