Boost logo

Boost Users :

From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2008-03-28 14:03:50


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


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