Boost logo

Boost Users :

From: Robert Dailey (rcdailey_at_[hidden])
Date: 2008-03-28 16:34:38


On Fri, Mar 28, 2008 at 1:03 PM, Steven Watanabe <watanabesj_at_[hidden]>
wrote:

> AMDG
>
> Robert Dailey wrote:
> > Subscription doesn't seem as simple as you proposed. I looked into
> > possible designs for subscribing to the signals and nothing is working
> > out. There's no way to generate a second map to provide slot
> > connections, since the signal object is actually owned by the first
> > map, and thus the two cannot share them. Secondly, the slots (given
> > the design above) each have a different signature for each packet,
> > which further complicates things.
> >
> > Any suggestions? I'm having trouble thinking outside the box...
>
> #include <boost/signal.hpp>
> #include <boost/function.hpp>
> #include <boost/unordered_map.hpp>
> #include <boost/shared_ptr.hpp>
> #include <boost/mpl/integral_c.hpp>
> #include <vector>
> #include <utility>
> #include <iostream>
>
> struct Packet {};
>
> struct WalkPacket : Packet {};
>
> enum PacketID {
> PID_WALKPACKET
> };
>
> template<class T>
> struct GetPacketID;
>
> template<>
> struct GetPacketID<WalkPacket> : boost::mpl::integral_c<PacketID,
> PID_WALKPACKET> {};
>
> template<class T>
> struct StaticCaster {
> StaticCaster(boost::shared_ptr<boost::signal<void(T const&)> >
> const& signal) : signal(signal) {}
> boost::shared_ptr<boost::signal<void(T const&)> > signal;
> void operator()(Packet const& packet) const {
> (*signal)(static_cast<T const&>(packet));
> }
> };
>
> class SignalHolder {
> public:
> template<class T, class F>
> void register_function(F f) {
> const PacketID id = GetPacketID<T>::value;
> dispatcher_t::iterator iter = dispatcher.find(id);
> if(iter == dispatcher.end()) {
> boost::shared_ptr<boost::signal<void(T const&)> > signal(new
> boost::signal<void(T const&)>());
> iter = dispatcher.insert(std::make_pair(id,
> std::make_pair(static_cast<boost::shared_ptr<void> >(signal),
> StaticCaster<T>(signal)))).first;
> }
> boost::static_pointer_cast<boost::signal<void(T const&)>
> >(iter->second.first)->connect(f);
> };
> void operator()(PacketID id, const Packet& packet) {
> dispatcher[id].second(packet);
> }
> private:
> typedef boost::unordered_map<PacketID,
> std::pair<boost::shared_ptr<void>, boost::function<void(Packet const&)>
> > > dispatcher_t;
> dispatcher_t dispatcher;
> };
>
> void test(WalkPacket const&) {
> std::cout << "Got a WalkPacket" << std::endl;
> }
>
> int main() {
>
> SignalHolder holder;
>
> holder.register_function<WalkPacket>(&test);
>
> WalkPacket packet;
>
> holder(PID_WALKPACKET, packet);
> }
>
> In Christ,
> Steven Watanabe
>

Thanks, this is a great idea. However, while you're doing the insert() I
noticed you're using statc_cast<>(). I'm actually surprised this compiles.
This is basically like casting something to an unrelated type, so I'm not
sure how the compiler is allowing this behavior. This also seems very
inconsistent in that you're using boost::static_pointer_cast() for going
from basically a void* to a signal object.



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net