I would like to create a class whose methods can be called from multiple threads. but instead of executing the method in the thread from which it was called, it should perform them all in it's own thread. No result needs to be returned and It shouldn't block the calling thread.
A first attempt Implementation I have included below. The public methods insert a function pointer and data into a job Queue, which the worker thread then picks up. However it's not particularily nice code and adding new methods is cumbersome.
Ideally I would like to use this as a base class which I can easy add methods (with a variable number of arguments) with minimum hastle and code duplication.
What is a better way to do this? Is there any existing code available which does something similar? Thanks
#include <queue>
using namespace std;
class GThreadObject
{
class event
{
public:
void (GThreadObject::*funcPtr)(void *);
void * data;
};
public:
void functionOne(char * argOne, int argTwo);
private:
void workerThread();
queue<GThreadObject::event*> jobQueue;
void functionOneProxy(void * buffer);
void functionOneInternal(char * argOne, int argTwo);
};
#include <iostream>
#include "GThreadObject.h"
using namespace std;
/* On a continuous loop, reading tasks from queue
* When a new event is received it executes the attached function pointer
* It should block on a condition, but Thread code removed to decrease clutter
*/
void GThreadObject::workerThread()
{
//New Event added, process it
GThreadObject::event * receivedEvent = jobQueue.front();
//Execute the function pointer with the attached data
(*this.*receivedEvent->funcPtr)(receivedEvent->data);
}
/*
* This is the public interface, Can be called from child threads
* Instead of executing the event directly it adds it to a job queue
* Then the workerThread picks it up and executes all tasks on the same thread
*/
void GThreadObject::functionOne(char * argOne, int argTwo)
{
//Malloc an object the size of the function arguments
int argumentSize = sizeof(char*)+sizeof(int);
void * myData = malloc(argumentSize);
//Copy the data passed to this function into the buffer
memcpy(myData, &argOne, argumentSize);
//Create the event and push it on to the queue
GThreadObject::event * myEvent = new event;
myEvent->data = myData;
myEvent->funcPtr = >hreadObject::functionOneProxy;
jobQueue.push(myEvent);
//This would be send a thread condition signal, replaced with a simple call here
this->workerThread();
}
/*
* This handles the actual event
*/
void GThreadObject::functionOneInternal(char * argOne, int argTwo)
{
cout << "We've made it to functionTwo char*:" << argOne << " int:" << argTwo << endl;
//Now do the work
}
/*
* This is the function I would like to remove if possible
* Split the void * buffer into arguments for the internal Function
*/
void GThreadObject::functionOneProxy(void * buffer)
{
char * cBuff = (char*)buffer;
functionOneInternal((char*)*((unsigned int*)cBuff), (int)*(cBuff+sizeof(char*)));
};
int main()
{
GThreadObject myObj;
myObj.functionOne("My Message", 23);
return 0;
}
There's Futures library making its way into Boost and the C++ standard library. There's also something of the same sort in ACE, but I would hate to recommend it to anyone (as #lothar already pointed out, it's Active Object.)
Below is an implementation which doesn't require a "functionProxy" method. Even though it is easier to add new methods, it's still messy.
Boost::Bind and "Futures" do seem like they would tidy a lot of this up. I guess I'll have a look at the boost code and see how it works. Thanks for your suggestions everyone.
GThreadObject.h
#include <queue>
using namespace std;
class GThreadObject
{
template <int size>
class VariableSizeContainter
{
char data[size];
};
class event
{
public:
void (GThreadObject::*funcPtr)(void *);
int dataSize;
char * data;
};
public:
void functionOne(char * argOne, int argTwo);
void functionTwo(int argTwo, int arg2);
private:
void newEvent(void (GThreadObject::*)(void*), unsigned int argStart, int argSize);
void workerThread();
queue<GThreadObject::event*> jobQueue;
void functionTwoInternal(int argTwo, int arg2);
void functionOneInternal(char * argOne, int argTwo);
};
GThreadObject.cpp
#include <iostream>
#include "GThreadObject.h"
using namespace std;
/* On a continuous loop, reading tasks from queue
* When a new event is received it executes the attached function pointer
* Thread code removed to decrease clutter
*/
void GThreadObject::workerThread()
{
//New Event added, process it
GThreadObject::event * receivedEvent = jobQueue.front();
/* Create an object the size of the stack the function is expecting, then cast the function to accept this object as an argument.
* This is the bit i would like to remove
* Only supports 8 byte argument size e.g 2 int's OR pointer + int OR myObject8bytesSize
* Subsequent data sizes would need to be added with an else if
* */
if (receivedEvent->dataSize == 8)
{
const int size = 8;
void (GThreadObject::*newFuncPtr)(VariableSizeContainter<size>);
newFuncPtr = (void (GThreadObject::*)(VariableSizeContainter<size>))receivedEvent->funcPtr;
//Execute the function
(*this.*newFuncPtr)(*((VariableSizeContainter<size>*)receivedEvent->data));
}
//Clean up
free(receivedEvent->data);
delete receivedEvent;
}
void GThreadObject::newEvent(void (GThreadObject::*funcPtr)(void*), unsigned int argStart, int argSize)
{
//Malloc an object the size of the function arguments
void * myData = malloc(argSize);
//Copy the data passed to this function into the buffer
memcpy(myData, (char*)argStart, argSize);
//Create the event and push it on to the queue
GThreadObject::event * myEvent = new event;
myEvent->data = (char*)myData;
myEvent->dataSize = argSize;
myEvent->funcPtr = funcPtr;
jobQueue.push(myEvent);
//This would be send a thread condition signal, replaced with a simple call here
this->workerThread();
}
/*
* This is the public interface, Can be called from child threads
* Instead of executing the event directly it adds it to a job queue
* Then the workerThread picks it up and executes all tasks on the same thread
*/
void GThreadObject::functionOne(char * argOne, int argTwo)
{
newEvent((void (GThreadObject::*)(void*))>hreadObject::functionOneInternal, (unsigned int)&argOne, sizeof(char*)+sizeof(int));
}
/*
* This handles the actual event
*/
void GThreadObject::functionOneInternal(char * argOne, int argTwo)
{
cout << "We've made it to functionOne Internal char*:" << argOne << " int:" << argTwo << endl;
//Now do the work
}
void GThreadObject::functionTwo(int argOne, int argTwo)
{
newEvent((void (GThreadObject::*)(void*))>hreadObject::functionTwoInternal, (unsigned int)&argOne, sizeof(int)+sizeof(int));
}
/*
* This handles the actual event
*/
void GThreadObject::functionTwoInternal(int argOne, int argTwo)
{
cout << "We've made it to functionTwo Internal arg1:" << argOne << " int:" << argTwo << endl;
}
main.cpp
#include <iostream>
#include "GThreadObject.h"
int main()
{
GThreadObject myObj;
myObj.functionOne("My Message", 23);
myObj.functionTwo(456, 23);
return 0;
}
Edit: Just for completeness I did an implementation with Boost::bind. Key Differences:
queue<boost::function<void ()> > jobQueue;
void GThreadObjectBoost::functionOne(char * argOne, int argTwo)
{
jobQueue.push(boost::bind(>hreadObjectBoost::functionOneInternal, this, argOne, argTwo));
workerThread();
}
void GThreadObjectBoost::workerThread()
{
boost::function<void ()> func = jobQueue.front();
func();
}
Using the boost implementation for 10,000,000 Iterations of functionOne() it took ~19sec. However the non boost implementation took only ~6.5 sec. So Approx 3x slower. I'm guessing finding a good non-locking queue will be the biggest performance bottle neck here. But it's still quite a big difference.
The POCO library has something along the same lines called ActiveMethod (along with some related functionality e.g. ActiveResult) in the threading section. The source code is readily available and easily understood.
You might be interested in Active Object one of the ACE Patterns of the ACE framework.
As Nikolai pointed out futures are planned for standard C++ some time in the future (pun intended).
For extensibility and maintainability (and other -bilities) you could define an abstract class (or interface) for the "job" that thread is to perform. Then user(s) of your thread pool would implement this interface and give reference to the object to the thread pool. This is very similar to Symbian Active Object design: every AO subclasses CActive and have to implement methods such as Run() and Cancel().
For simplicity your interface (abstract class) might be as simple as:
class IJob
{
virtual Run()=0;
};
Then the thread pool, or single thread accepting requests would have something like:
class CThread
{
<...>
public:
void AddJob(IJob* iTask);
<...>
};
Naturally you would have multiple tasks that can have all kinds of extra setters / getters / attributes and whatever you need in any walk of life. However, the only must is to implement method Run(), which would perform the lengthy calculations:
class CDumbLoop : public IJob
{
public:
CDumbJob(int iCount) : m_Count(iCount) {};
~CDumbJob() {};
void Run()
{
// Do anything you want here
}
private:
int m_Count;
};
You can solve this by using Boost's Thread -library. Something like this (half-pseudo):
class GThreadObject
{
...
public:
GThreadObject()
: _done(false)
, _newJob(false)
, _thread(boost::bind(>hreadObject::workerThread, this))
{
}
~GThreadObject()
{
_done = true;
_thread.join();
}
void functionOne(char *argOne, int argTwo)
{
...
_jobQueue.push(myEvent);
{
boost::lock_guard l(_mutex);
_newJob = true;
}
_cond.notify_one();
}
private:
void workerThread()
{
while (!_done) {
boost::unique_lock l(_mutex);
while (!_newJob) {
cond.wait(l);
}
Event *receivedEvent = _jobQueue.front();
...
}
}
private:
volatile bool _done;
volatile bool _newJob;
boost::thread _thread;
boost::mutex _mutex;
boost::condition_variable _cond;
std::queue<Event*> _jobQueue;
};
Also, please note how RAII allow us to get this code smaller and better to manage.
Here's a class I wrote for a similar purpose (I use it for event handling but you could of course rename it to ActionQueue -- and rename its methods).
You use it like this:
With function you want to call: void foo (const int x, const int y) { /*...*/ }
And: EventQueue q;
q.AddEvent (boost::bind (foo, 10, 20));
In the worker thread
q.PlayOutEvents ();
Note: It should be fairly easy to add code to block on condition to avoid using up CPU cycles.
The code (Visual Studio 2003 with boost 1.34.1):
#pragma once
#include <boost/thread/recursive_mutex.hpp>
#include <boost/function.hpp>
#include <boost/signals.hpp>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <string>
using std::string;
// Records & plays out actions (closures) in a safe-thread manner.
class EventQueue
{
typedef boost::function <void ()> Event;
public:
const bool PlayOutEvents ()
{
// The copy is there to ensure there are no deadlocks.
const std::vector<Event> eventsCopy = PopEvents ();
BOOST_FOREACH (const Event& e, eventsCopy)
{
e ();
Sleep (0);
}
return eventsCopy.size () > 0;
}
void AddEvent (const Event& event)
{
Mutex::scoped_lock lock (myMutex);
myEvents.push_back (event);
}
protected:
const std::vector<Event> PopEvents ()
{
Mutex::scoped_lock lock (myMutex);
const std::vector<Event> eventsCopy = myEvents;
myEvents.clear ();
return eventsCopy;
}
private:
typedef boost::recursive_mutex Mutex;
Mutex myMutex;
std::vector <Event> myEvents;
};
I hope this helps. :)
Martin Bilski
You should take a look at the Boost ASIO library. It is designed to dispatch events asynchronously. It can be paired with the Boost Thread library to build the system that you described.
You would need to instantiate a single boost::asio::io_service object and schedule a series of asynchronous events (boost::asio::io_service::post or boost::asio::io_service::dispatch). Next, you call the run member function from n threads. The io_service object is thread-safe and guarantees that your asynchronous handlers will only be dispatched in a thread from which you called io_service::run.
The boost::asio::strand object is also useful for simple thread synchronization.
For what it is worth, I think that the ASIO library is a very elegant solution to this problem.
Related
For University I have to write a program like space Invaders.
Now we have to write the "bullet" - Class for the main spaceShip, to shoot bullets.
Every bullet has to create its own thread. The thread has to execute the run method.
Bullet.hpp
ifndef BULLET_HPP_
define BULLET_HPP_
include "TriangleMesh.hpp"
include <GL/glu.h>
include <GL/glut.h>
include <thread>
include <chrono>
namespace asteroids
{
class Bullet : public TriangleMesh
{
public:
/**
* #brief Contructor. Build a bullet on the given Fighter's
* position. The bullet will move on the
* given axis.
* #param fighter_position Position of the fighter that shoots this bullet
* #param fighter_axis Axis the bullet will move on
*/
Bullet(Vertex<float> fighter_position, Vertex<float> fighter_axis);
~Bullet();
/**
* #brief Moves the bullet until it's lifetime is over.
*/
void run();
/**
* #brief Starts bullet movement
*/
void start();
/*
* #brief Stops bullet movement
*/
void stop();
/**
* #brief Renders the bullet via glutSolidSphere.
*/
void render();
/**
* #brief Returns the status of this bullet.
* #return false, if the bullet's lifetime is over and true otherwise
*/
bool isAlive();
private:
// Lifetime, i.e., how many timesteps the bullet visible
static const int m_lifetime = 9000;
// True, if the bullet's lifetime isn't over yet
bool m_alive;
// Flight direction of the bullet
Vertex<float> m_fighterAxis;
//position of the fighter
Vertex<float> m_fighterPosition;
static void staticRun(Bullet * bullet);
bool isRunning;
/// TODO: ADD TIMING AND THREAD FUNCTIONALITY
void stopThread();
void startThread();
void sleep(int n)
{
std::this_thread::sleep_for(std::chrono::milliseconds(n));
}
};
} // namespace asteroids
#endif /* BULLET_HPP_ */
/**
* Bullet.cpp
*
*/
BULLET.CPP
#include "Bullet.hpp"
using namespace std;
namespace asteroids
{
Bullet::Bullet(Vertex<float> fighter_position, Vertex<float> fighter_axis)
: m_alive(true)
{
// TODO: Implement Ctor logic
m_fighterAxis = fighter_axis;
m_fighterPosition = fighter_position;
m_position = fighter_position;
startThread();
}
void Bullet::stopThread()
{
currentThread->join();
}
//creates a static-member option for starting the thread with an argument.
void Bullet::staticRun(Bullet* bullet)
{
bullet->run();
}
//Logic to create and start a Thread with out static function to execute
void Bullet::startThread()
{
Bullet* bullet = this;
std::thread t1(&Bullet::staticRun, bullet);
currentThread = t1; //Here i wanted to set the pointer equal the existing thread
//But compiler says that i cant convert a thread type to a //pointer type
}
Bullet::~Bullet() {}
bool Bullet::isAlive()
{
return m_alive;
}
void Bullet::stop()
{
m_alive = false;
}
void Bullet::start()
{
if (isAlive())
{
// TODO: Implement thread start logic
startThread();
}
}
void Bullet::run()
{
Vertex<float> move = Vertex<float>(1, 1, 1);
for (int i = 0; i < m_lifetime; i++)
{
m_position = m_fighterAxis + move;
render();
sleep(1000);
//this->sleep(1000);
}
stop();
}
void Bullet::render()
{
// Compute transformation matrix
computeMatrix();
// Push old transformation of the OpenGL matrix stack and
// start rendering the bullet in according to the
// internal transformation matrix
glPushMatrix();
glMultMatrixf(m_transformation);
glutSolidSphere(10, 16, 16);
// Pop transformation matrix of this object
// to restore the previous state of the OpenGL
// matrix stack
glPopMatrix();
}
} // namespace asreroids
Now my question is: is it the right way to create the thread in a separate method and create a pointer which holds it?
Or how would you implement a thread-logic without a thread-parent-class?
Thank you for help guys, and excuse me if the layout is not the right way to post a commend here, its my first post ever ^^
You should bind the function to the variable that you're trying to pass, in this case I suggest you to bind it to the instance that you're creating and then the arguments that the function will receive, usually you declare the function as a member function and then bind the instance to it, then pass it to the thread that you're creating.
We're using mutex below in order to protect the running boolean from multiple thread access. You should use a mutex to protect the variables that could be accessed by multiple threads.
currentThread.join(); awaits for the thread to finish.
#include <thread>
#include <mutex>
#include <chrono>
class Bullet{
public:
void startThread(){
currentThread = std::thread(std::bind(&Bullet::run, this));
}
void run(){
while (isRunning()){
std::this_thread::sleep_for(std::chrono::milliseconds(200));
//Do something.
}
}
void Bullet::stopThread()
{
runMutex.lock();
running = false;
runMutex.unlock();
currentThread.join();
}
bool isRunning(){
bool isRunning = false;
runMutex.lock();
isRunning = running;
runMutex.unlock();
return isRunning;
}
private:
std::thread currentThread;
std::mutex runMutex;
bool running;
};
int main()
{
Bullet bullet;
bullet.startThread();
bullet.stopThread();
return 0; //return.
}
Having too many "bullet" objects and each running it's own thread would make it that harder to debug later on if the need arises....One way that this could be done could be through the use of ThreadPool pattern..A single thread pool can be used not just for bullets, but other entities in the system too...You will have a central repository of all threads and you can monitor them if the need arises...
https://codereview.stackexchange.com/questions/40536/simple-thread-pool-in-c
Bullet* bullet = this;
std::thread t1(&Bullet::staticRun, bullet);
currentThread = t1;
As far as the above code goes, is currentThread a class member??I havent used much of c++11 threading, but, doesn't std::thread t1(&Bullet::staticRun, bullet); go out of scope once the method execution completes??
How to specify lambda, std::bind result or any other std::function as argument for unix signal function?
I'm trying the following
std::function<void(int)> handler1 = std::bind(&cancellation_token::cancel, &c);
std::function<void(int)> handler2 = [&c](int) { c.cancel(); };
but it doesn't work, because both
handler1.target<void(int)>()
and
handler2.target<void(int)>()
return null
It works if I initialize handler with free function pointer
void foo(int) { ... }
std::function<void(int)> handler = foo;
but this is absolutely useless. I need to capture some local variables, so I need either bind or lambda.
Actually I understand why it doesn't work. Documentation says that target function returns a pointer to the stored function if target_type() == typeid(T), otherwise a null pointer. I don't understand how to make it work.
Any suggestions?
Since it's constructed by bind, or lambda with captured-data, you cannot convert it to free function, since target function works by typeid, std::function saves it in runtime, not for type T, with which function is templated. For std::bind it will be some library-type and for lambda it will be some unnamed type.
You can use a dispatcher-like approach associating signal numbers to std::functions through a map.
You just need a map to hold the std::functions accesible from a free function:
std::unordered_map<int, std::function<void(int)>> signalHandlers;
And a generic handler (free function) to map the signal number to the function:
void dispatcher(int signal) {
// this will call a previously saved function
signalHandlers.at(signal)(signal);
}
Implementation example
main.cpp
#include <iostream>
#include <thread>
#include <csignal>
#include "cppsignal.hpp"
int main() {
bool stop = false;
// set a handler as easy as this
CppSignal::setHandler(SIGINT, [&stop] (int) { stop = true; });
while (!stop) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "Bye" << std::endl;
return 0;
}
cppsignal.cpp
#include <cstring> // strsignal
#include <csignal>
#include <string>
#include <stdexcept>
#include <unordered_map>
#include <mutex>
#include "signal.hpp"
namespace CppSignal {
std::timed_mutex signalHandlersMutex;
std::unordered_map<int, std::function<void(int)>> signalHandlers;
// generic handler (free function) to set as a handler for any signal
void dispatcher(int signal) {
std::unique_lock<std::timed_mutex> lock(signalHandlersMutex, std::defer_lock);
if (!lock.try_lock_for(std::chrono::seconds(1))) {
// unable to get the lock. should be a strange case
return;
}
auto it = signalHandlers.find(signal);
if (it != signalHandlers.end()) {
it->second(signal);
}
}
void registerHandler(int signal, const std::function<void(int)>& handler) {
std::lock_guard<std::timed_mutex> lock(signalHandlersMutex);
signalHandlers.emplace(signal, handler);
}
// this is the only method you will use
void setHandler(int signal, const std::function<void(int)>& handler, int flags) {
// configure sigaction structure
struct sigaction action;
if (sigfillset(&action.sa_mask) == -1) {
throw std::runtime_error("sigfillset failed");
}
action.sa_flags = flags;
action.sa_handler = dispatcher;
// set handler for the signal
if (sigaction(signal, &action, nullptr) == -1 && signal < __SIGRTMIN) {
throw std::runtime_error("Fail at configuring handler for signal: " + std::string(strsignal(signal)));
}
registerHandler(signal, handler);
}
}
cppsignal.hpp
#ifndef __CPPSIGNAL_HPP
#define __CPPSIGNAL_HPP
#include <functional>
namespace CppSignal {
void setHandler(int signal, const std::function<void(int)>& handler, int flags=0);
}
#endif
sighandler_t is defined to be a pointer to a function with the following definition:
void func(int);
Since std::bind and lambdas return functors, it is not possible to directly use them as signal handler. As a workaround you can use your own wrapper functions like
class SignalHandlerBase
{
public:
virtual void operator(int) = 0;
};
template <class T>
class SignalHandler : public SignalHandlerBase
{
T t;
public:
SignalHandler(T _t) : t(_t) { }
void operator(int i)
{
t(i);
}
};
class SignalManager
{
int sig;
SignalHandlerBase *shb;
static void handlerFunction(int i)
{
shb(i);
}
public:
SignalManager(int signal) : sig(signal), shb(nullptr) { signal(signal, &handlerFunction); }
template <class T>
void installHandler(T t)
{
delete shb;
shb = new SignalHandler<T>(t);
}
};
Use global instances of SignalManager to manage individual signals
C++11 1.9 [intro.execution]/6:
When the processing of the abstract machine is interrupted by receipt of a signal, the values of objects which
are neither
of type volatile std::sig_atomic_t nor
lock-free atomic objects (29.4)
are unspecified during the execution of the signal handler, and the value of any
object not in either of these
two categories that is modified by the handler becomes undefined.
The only action you can realistically take portably in a signal handler is to change the value of a flag whose type is volatile std::sig_atomic_t or a lock-free std::atomic (Note that not all std::atomic objects are lock-free). Non-signal handling code can then poll that flag to respond to the occurrence of the signal.
N3787 has some interesting discussion about how to fix C++11 basically breaking signal handlers as a concept.
I am very new to C++.
I have a class, and I want to create a thread inside a class's function. And that thread(function) will call and access the class function and variable as well.
At the beginning I tried to use Pthread, but only work outside a class, if I want to access the class function/variable I got an out of scope error.
I take a look at Boost/thread but it is not desirable because of I don't want to add any other library to my files(for other reason).
I did some research and cannot find any useful answers.
Please give some examples to guide me. Thank you so much!
Attempt using pthread(but I dont know how to deal with the situation I stated above):
#include <pthread.h>
void* print(void* data)
{
std::cout << *((std::string*)data) << "\n";
return NULL; // We could return data here if we wanted to
}
int main()
{
std::string message = "Hello, pthreads!";
pthread_t threadHandle;
pthread_create(&threadHandle, NULL, &print, &message);
// Wait for the thread to finish, then exit
pthread_join(threadHandle, NULL);
return 0;
}
You can pass a static member function to a pthread, and an instance of an object as its argument. The idiom goes something like this:
class Parallel
{
private:
pthread_t thread;
static void * staticEntryPoint(void * c);
void entryPoint();
public:
void start();
};
void Parallel::start()
{
pthread_create(&thread, NULL, Parallel::staticEntryPoint, this);
}
void * Parallel::staticEntryPoint(void * c)
{
((Parallel *) c)->entryPoint();
return NULL;
}
void Parallel::entryPoint()
{
// thread body
}
This is a pthread example. You can probably adapt it to use a std::thread without much difficulty.
#include <thread>
#include <string>
#include <iostream>
class Class
{
public:
Class(const std::string& s) : m_data(s) { }
~Class() { m_thread.join(); }
void runThread() { m_thread = std::thread(&Class::print, this); }
private:
std::string m_data;
std::thread m_thread;
void print() const { std::cout << m_data << '\n'; }
};
int main()
{
Class c("Hello, world!");
c.runThread();
}
Before I present the code which is found at the bottom of this post I would like to talk about the issue and the fix's that I do not desire. Okay basically I've created a GUI from scratch sort of and one requirement I wanted for this was allow components to have their own click executions so if i click a button or tab etc.. It would call Component->Execute(); Well normally you would do something like a switch statement of ids and if that components ID equaled n number then it would perform this action. Well that seemed kinda dumb to me and I thought there has to be a better way. I eventually tried to incorporate a feature in JAVA where you would do like Component.AddActionListener(new ActionListener( public void execute(ActionEvent ae) { })); or something like that and I thought that this feature has to be possible in C++. I eventually came across storing void functions into a variable in which could be executed at any time and modified at any time. However I hadn't noticed an issue and that was this only worked with static functions. So below you'll see my problem. I've patched the problem by using a pointer to SomeClass however this would mean having an individual function call for every class type is there no way to store a function callback to a non-static class member without doing the below strategy? and instead doing a strategy like the commented out code?
//Main.cpp
#include <iostream> //system requires this.
#include "SomeClass.h"
void DoSomething1(void)
{
std::cout << "We Called Static DoSomething1\n";
}
void DoSomething2(void)
{
std::cout << "We Called Static DoSomething2\n";
}
int main()
{
void (*function_call2)(SomeClass*);
void (*function_call)() = DoSomething1; //This works No Problems!
function_call(); //Will Call the DoSomething1(void);
function_call = DoSomething2; //This works No Problems!
function_call(); //Will Call the DoSomething2(void);
SomeClass *some = new SomeClass(); //Create a SomeClass pointer;
function_call = SomeClass::DoSomething3; //Static SomeClass::DoSomething3();
function_call(); //Will Call the SomeClass::DoSomething3(void);
//function_call = some->DoSomething4; //Non-Static SomeClass::DoSomething4 gives an error.
//function_call(); //Not used because of error above.
function_call2 = SomeClass::DoSomething5; //Store the SomeClass::DoSomething(SomeClass* some);
function_call2(some); //Call out SomeClass::DoSomething5 which calls on SomeClass::DoSomething4's non static member.
system("pause");
return 0;
}
//SomeClass.hpp
#pragma once
#include <iostream>
class SomeClass
{
public:
SomeClass();
~SomeClass();
public:
static void DoSomething3(void);
void DoSomething4(void);
static void DoSomething5(SomeClass* some);
};
//SomeClass.cpp
#include "SomeClass.h"
SomeClass::SomeClass(void)
{
}
SomeClass::~SomeClass(void)
{
}
void SomeClass::DoSomething3(void)
{
std::cout << "We Called Static DoSomething3\n";
}
void SomeClass::DoSomething4(void)
{
std::cout << "We Called Non-Static DoSomething4\n";
}
void SomeClass::DoSomething5(SomeClass *some)
{
some->DoSomething4();
}
Secondary Fix for what I'll do not an exact answer I wanted but it meets my needs for now along with allowing additional features which would have become overly complicate had this not existed.
//Component.hpp
#pragma once
#include <iostream>
#include <windows.h>
#include <d3dx9.h>
#include <d3d9.h>
#include "Constants.hpp"
#include "ScreenState.hpp"
#include "ComponentType.hpp"
using namespace std;
class Component
{
static void EMPTY(void) { }
static void EMPTY(int i) { }
public:
Component(void)
{
callback = EMPTY;
callback2 = EMPTY;
callback_id = -1;
}
Component* SetFunction(void (*callback)())
{
this->callback = callback;
return this;
}
Component* SetFunction(void (*callback2)(int), int id)
{
this->callback_id = id;
this->callback2 = callback2;
return this;
}
void execute(void)
{
callback();
callback2(callback_id);
}
}
The syntax for pointers-to-member-functions is as follows:
struct Foo
{
void bar(int, int);
void zip(int, int);
};
Foo x;
void (Foo::*p)(int, int) = &Foo::bar; // pointer
(x.*p)(1, 2); // invocation
p = &Foo::zip;
(x.*p)(3, 4); // invocation
Mind the additional parentheses in the function invocation, which is needed to get the correct operator precedence. The member-dereference operator is .* (and there's also ->* from an instance pointer).
I’m aware of the tutorial at boost.org addressing this:
Boost.org Signals Tutorial, but the examples are not complete and somewhat over simplified. The examples there don’t show the include files and some sections of the code are a little vague.
Here is what I need:
ClassA raises multiple events/signals
ClassB subscribes to those events (Multiple classes may subscribe)
In my project I have a lower-level message handler class that raises events to a business class that does some processing of those messages and notifies the UI (wxFrames). I need to know how these all might get wired up (what order, who calls who, etc).
The code below is a minimal working example of what you requested. ClassA emits two signals; SigA sends (and accepts) no parameters, SigB sends an int. ClassB has two functions which will output to cout when each function is called. In the example there is one instance of ClassA (a) and two of ClassB (b and b2). main is used to connect and fire the signals. It's worth noting that ClassA and ClassB know nothing of each other (ie they're not compile-time bound).
#include <boost/signal.hpp>
#include <boost/bind.hpp>
#include <iostream>
using namespace boost;
using namespace std;
struct ClassA
{
signal<void ()> SigA;
signal<void (int)> SigB;
};
struct ClassB
{
void PrintFoo() { cout << "Foo" << endl; }
void PrintInt(int i) { cout << "Bar: " << i << endl; }
};
int main()
{
ClassA a;
ClassB b, b2;
a.SigA.connect(bind(&ClassB::PrintFoo, &b));
a.SigB.connect(bind(&ClassB::PrintInt, &b, _1));
a.SigB.connect(bind(&ClassB::PrintInt, &b2, _1));
a.SigA();
a.SigB(4);
}
The output:
Foo
Bar: 4
Bar: 4
For brevity I've taken some shortcuts that you wouldn't normally use in production code (in particular access control is lax and you'd normally 'hide' your signal registration behind a function like in KeithB's example).
It seems that most of the difficulty in boost::signal is in getting used to using boost::bind. It is a bit mind-bending at first! For a trickier example you could also use bind to hook up ClassA::SigA with ClassB::PrintInt even though SigA does not emit an int:
a.SigA.connect(bind(&ClassB::PrintInt, &b, 10));
Hope that helps!
Here is an example from our codebase. Its been simplified, so I don't guarentee that it will compile, but it should be close. Sublocation is your class A, and Slot1 is your class B. We have a number of slots like this, each one which subscribes to a different subset of signals. The advantages to using this scheme are that Sublocation doesn't know anything about any of the slots, and the slots don't need to be part of any inheritance hierarchy, and only need implement functionality for the slots that they care about. We use this to add custom functionality into our system with a very simple interface.
Sublocation.h
class Sublocation
{
public:
typedef boost::signal<void (Time, Time)> ContactSignal;
typedef boost::signal<void ()> EndOfSimSignal;
void endOfSim();
void addPerson(Time t, Interactor::Ptr i);
Connection addSignalContact(const ContactSignal::slot_type& slot) const;
Connection addSignalEndOfSim(const EndOfSimSignal::slot_type& slot) const;
private:
mutable ContactSignal fSigContact;
mutable EndOfSimSignal fSigEndOfSim;
};
Sublocation.C
void Sublocation::endOfSim()
{
fSigEndOfSim();
}
Sublocation::Connection Sublocation::addSignalContact(const ContactSignal::slot_type& slot) const
{
return fSigContact.connect(slot);
}
Sublocation::Connection Sublocation::addSignalEndOfSim(const EndOfSimSignal::slot_type& slot) const
{
return fSigEndOfSim.connect(slot);
}
Sublocation::Sublocation()
{
Slot1* slot1 = new Slot1(*this);
Slot2* slot2 = new Slot2(*this);
}
void Sublocation::addPerson(Time t, Interactor::Ptr i)
{
// compute t1
fSigOnContact(t, t1);
// ...
}
Slot1.h
class Slot1
{
public:
Slot1(const Sublocation& subloc);
void onContact(Time t1, Time t2);
void onEndOfSim();
private:
const Sublocation& fSubloc;
};
Slot1.C
Slot1::Slot1(const Sublocation& subloc)
: fSubloc(subloc)
{
subloc.addSignalContact(boost::bind(&Slot1::onContact, this, _1, _2));
subloc.addSignalEndSim(boost::bind(&Slot1::onEndSim, this));
}
void Slot1::onEndOfSim()
{
// ...
}
void Slot1::onContact(Time lastUpdate, Time t)
{
// ...
}
Did you look at boost/libs/signals/example ?
When compiling MattyT's example with newer boost (f.e. 1.61) then it gives a warning
error: #warning "Boost.Signals is no longer being maintained and is now deprecated. Please switch to Boost.Signals2. To disable this warning message, define BOOST_SIGNALS_NO_DEPRECATION_WARNING."
So either you define BOOST_SIGNALS_NO_DEPRECATION_WARNING to suppress the warning or you could easily switch to boost.signal2 by changing the example accordingly:
#include <boost/signals2.hpp>
#include <boost/bind.hpp>
#include <iostream>
using namespace boost::signals2;
using namespace std;
Boost like QT provides its own implementation of signals and slots. Following are some example of its implementation.
Signal and Slot connection for namespace
Consider a namespace called GStreamer
namespace GStremer
{
void init()
{
....
}
}
Here is how to create and trigger the signal
#include<boost/signal.hpp>
...
boost::signal<void ()> sigInit;
sigInit.connect(GStreamer::init);
sigInit(); //trigger the signal
Signal and Slot connection for a Class
Consider a Class called GSTAdaptor with function called func1 and func2 with following signature
void GSTAdaptor::func1()
{
...
}
void GSTAdaptor::func2(int x)
{
...
}
Here is how to create and trigger the signal
#include<boost/signal.hpp>
#include<boost/bind.hpp>
...
GSTAdaptor g;
boost::signal<void ()> sigFunc1;
boost::signal<void (int)> sigFunc2;
sigFunc1.connect(boost::bind(&GSTAdaptor::func1, &g);
sigFunc2.connect(boost::bind(&GSTAdaptor::func2, &g, _1));
sigFunc1();//trigger the signal
sigFunc2(6);//trigger the signal
Above answer is great with signal2 same answer shoule be rewritten:
#include <boost/signals2.hpp>
#include <boost/bind.hpp>
#include <iostream>
using namespace boost;
using namespace std;
struct ClassA
{
signals2::signal<void ()> SigA;
signals2::signal<void (int)> SigB;
};
struct ClassB
{
void PrintFoo() { cout << "Foo" << endl; }
void PrintInt(int i) { cout << "Bar: " << i << endl; }
};
int main()
{
ClassA a;
ClassB b, b2;
a.SigA.connect(bind(&ClassB::PrintFoo, &b));
a.SigB.connect(bind(&ClassB::PrintInt, &b, _1));
a.SigB.connect(bind(&ClassB::PrintInt, &b2, _1));
a.SigA();
a.SigB(4);
}