--- Begin Message ---
Hello,
I've looked into Event family classes, and is seems kind of hairy and
messy.
On order to do thread safe events we need today to:
1) Declare a nonsafe event
2) attach a non-safe handler
3) decale a safe event
4) attach a safe handler
The non safe handler have to create a ThreadEvent message and
post it to the QT queue.
So i've experimented a little bit with boost signals
and managed to create a thread safe signal class.
basicly you do:
mtsignal<void (std::string name, int age)> sig;
in one thread you do:
sig.connect(&handler);
and in another:
sig("vadim", 49);
and the internal implementation
will create the message and pass it to the QT queue
Actually it even can check if handler thread is == caller thread in do
direct call
in this case as i do in attached example
Enjoy and
Thanks
Vadim
P.S.
I build the example as following:
g++ -g -o tsig2 -I/usr/local/include/boost-1_33_1/ -L /usr/local/lib
-lboost_signals-gcc-d tsig2.cpp
#include <boost/signals.hpp>
#include <boost/bind.hpp>
#include <iostream>
using namespace boost;
using namespace std;
// Thread id
int gTID = 1000;
struct XComm
{
typedef int TargetID;
struct mess_base
{
virtual void callback() = 0;
};
template<class Slot> struct mess : public mess_base
{
const Slot slot;
mess(const Slot& s) : slot(s) { }
virtual void callback() { slot(); }
};
template<typename T> static void send(TargetID tid, const T& slot)
{
if (tid == get_tid())
{
cout << __FUNCTION__ << ": direct call to: " << tid << endl;
slot();
return;
}
else
{
cout << __FUNCTION__ << ": message sent from: " << get_tid() << " to: " << tid << endl;
mess<T> *m = new mess<T>(slot);
m->callback();
delete m;
}
}
static TargetID get_tid() { return gTID; }
};
// multihread functor
template<typename Sig, typename Comm>
struct mtfunction : public boost::function<Sig>
{
typedef function<Sig> base_type;
typedef typename base_type::result_type result_type;
typename Comm::TargetID tid;
mtfunction() : base_type(), tid(Comm::get_tid()) { }
template<class T>
mtfunction(T f) : base_type(f), tid(Comm::get_tid()) { }
mtfunction(const mtfunction& other) : base_type((const base_type &)other), tid(other.tid) { }
mtfunction& operator=(const mtfunction& other)
{
base_type::operator=(other);
tid = other.tid;
return *this;
}
static void caller0(base_type *fun) { (*fun)(); }
template<class T1>
static void caller1(base_type *fun, T1 a1) { (*fun)(a1); }
template<class T1, class T2>
static void caller2(base_type *fun, T1 a1, T2 a2) { (*fun)(a1,a2); }
template<class T1, class T2, class T3>
static void caller3(base_type *fun, T1 a1, T2 a2, T3 a3) { (*fun)(a1,a2,a3); }
template<class T1, class T2, class T3, class T4>
static void caller4(base_type *fun, T1 a1, T2 a2, T3 a3, T4 a4) { (*fun)(a1,a2,a3,a4); }
template<class T1, class T2, class T3, class T4, class T5>
static void caller5(base_type *fun, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) { (*fun)(a1,a2,a3,a4,a5); }
template<class T1, class T2, class T3, class T4, class T5, class T6>
static void caller6(base_type *fun, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) { (*fun)(a1,a2,a3,a4,a5,a6); }
result_type operator()() const { Comm::send(tid, boost::bind(&caller0, (base_type *)this)); }
template<class T1>
result_type operator()(T1 a1) const { Comm::send(tid, boost::bind(&caller1<T1>, (base_type *)this, a1)); }
template<class T1, class T2>
result_type operator()(T1 a1, T2 a2) const { Comm::send(tid, boost::bind(&caller2<T1,T2>, (base_type *)this, a1, a2)); }
template<class T1, class T2, class T3>
result_type operator()(T1 a1, T2 a2, T3 a3) const { Comm::send(tid, boost::bind(&caller3<T1,T2,T3>, (base_type *)this, a1, a2, a3)); }
template<class T1, class T2, class T3, class T4>
result_type operator()(T1 a1, T2 a2, T3 a3, T4 a4) const { Comm::send(tid, boost::bind(&caller4<T1,T2,T3,T4>, (base_type *)this, a1, a2, a3, a4)); }
template<class T1, class T2, class T3, class T4, class T5>
result_type operator()(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) const
{
Comm::send(tid, boost::bind(&caller5<T1,T2,T3,T4,T5>, (base_type *)this, a1, a2, a3, a4, a5));
}
template<class T1, class T2, class T3, class T4, class T5 , class T6>
result_type operator()(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) const
{
Comm::send(tid, boost::bind(&caller6<T1,T2,T3,T4,T5,T6>, (base_type *)this, a1, a2, a3, a4, a5, a6));
}
};
// multithreaded signals
template<
typename Signature, // function type R (T1, T2, ..., TN)
typename Combiner = last_value<typename function_traits<Signature>::result_type>,
typename Group = int,
typename GroupCompare = std::less<Group>
>
class mtsignal :
public signal<Signature,
Combiner,
Group,
GroupCompare,
mtfunction<Signature, XComm> >
{
typedef signal<Signature,
Combiner,
Group,
GroupCompare,
mtfunction<Signature, XComm> > base_type;
public:
explicit mtsignal(const Combiner& combiner = Combiner(),
const GroupCompare& group_compare = GroupCompare()) :
base_type(combiner, group_compare)
{
}
};
mtsignal<int (int a)> sig1;
mtsignal<void (string data)> sig2;
int s1_handler(int a)
{
cout << "s1_handler:: " << a << endl;
return 0;
}
int s2_rhandler(const string& a)
{
cout << "s2_rhandler:: " << a << endl;
return 0;
}
int s2_handler(string a)
{
cout << "s2_handler:: " << a << endl;
return 0;
}
main(int argc, char *argv[])
{
sig1.connect(&s1_handler);
cout << "sig1 connected" << endl;
sig1(33);
gTID++; // simulate thread switch
sig1(55);
cout << "sig1 done" << endl;
sig2.connect(&s2_rhandler);
gTID++;
sig2.connect(&s2_handler);
sig2("abcd");
}
_______________________________________________
Wengophone-devel mailing list
[email protected]
http://dev.openwengo.com/mailman/listinfo/wengophone-devel
--- End Message ---