Boost logo

Boost Users :

Subject: Re: [Boost-users] [RFC] Signals bound to phoenix functions
From: Stephan Menzel (stephan.menzel_at_[hidden])
Date: 2010-06-23 11:42:49


Hi,

maybe I managed to narrow it down a little.

This works for both functors and member functions:

class Queue {
...
   template<typename SlotSignature, typename SlotFunction>
   boost::signals2::connection
connect(boost::signals2::signal<SlotSignature> &n_signal, SlotFunction
n_method) {
      return n_signal.connect(m_iosrv.wrap( n_method));
   };
...
}

io_service::wrap basically does what I needed all the time. No more wrapper.

Unless I want to add something. Unfortunately I can't always take
wrap()s output but have to modify a little. In fact, my Queue needs to
be templatized as well, modifying the behaviour of the functor. I have
a template parameter "Calling". When it is true, another function
shall be called by the functor after the method was posted. Now I
wanted to do this by phoenix:

template <bool Calling>
class Queue {
   template<typename Handler>
   void post(Handler n_handler) {
      m_iosrv.post(n_handler);
   };
...
   template<typename SlotSignature, typename SlotFunction>
   boost::signals2::connection
connect(boost::signals2::signal<SlotSignature> &n_signal, SlotFunction
n_method) {
      return n_signal.connect(
                                  if_( CallingBack ) [
                                     post(n_method) , m_signal_callback()
                                  ] .else_ [
                                     m_iosrv.wrap( n_method )
                                  ] );
   };
...

private:
  boost::function<void ()> m_callback;
  boost::asio::io_service m_iosrv;
}

Now as I understand phoenix the if_ statement is supposed to give me a
functor that is composed of either what is in the true section or the
false section, depending on the expression at compile time. Which I
guess is what I want.
Alas, even after some days of trial and error I can't get it to compile.

It seems like the if_ operator is not accepted properly. Or I am
completely misunderstanding phoenix.

...
no match for »operator[]« in »boost::phoenix::if_ [with Cond =
bool](((const bool&)((const bool*)(& false))))[(Queue<Calling>::post
[with Handler = queue_testsuite::testslot, bool Calling =
false]((n_method, queue_testsuite::testslot())),
((Queue<false>*)this)->Queue<false>::m_signal_callback.boost::function<void()>::<anonymous>.boost::function0<R>::operator()
[with R = void]())]«
...

Any ideas anyone??

Cheers,
Stephan

On Mon, Jun 21, 2010 at 11:14 AM, Stephan Menzel
<stephan.menzel_at_[hidden]> wrote:
> G'day,
>
> I'd like to get your opinion on a problem that puzzles me for a while.
> Basically, I'm trying to do sort of a delayed signals2 notification
> mechanism. I have a class wrapped around ASIOs io_service object that
> I normally use as a thread multiplexer and function storage.  Now in
> this case I want to use it without working threads so a current thread
> can process whatever handlers are in it. Which works fine but now I
> want to connect signals to it. I have several data classes that
> contain signals. These are to be connected to slots, but not directly.
> Instead, these slots are to be wrapped in little handlers and these
> handlers shall be put in the io_service object. So the signal's slot
> should not be executed straight away but by another thread that
> executes everything in the io_service.
>
> Now this strikes me as something that could be done nicely with
> phoenix. I want to use phoenix to create a little function that I can
> connect to the signal and that will do nothing more but post the
> handler into the io_service when the signal is triggered. I just can't
> figure out if that can actually work. Here's what I have so far
> (simplyfied). I try to illustrate on an example with a one-parameter
> slot.
>
> class Queue : public boost::noncopyable {
>
> public:
>   template<typename Handler>
>   void post(Handler n_handler) {
>       m_iosrv.post(n_handler);
>   }
>
>   std::size_t process(boost::system::error_code & n_errcode) {
>      return m_iosrv.poll(n_errcode);
>   };
>
>   template<typename Slot>
>   boost::signals2::connection connect(boost::signals2::signal<void()>
> &n_signal, Slot n_method) {
>     return n_signal.connect(boost::bind(&CommandQueue::slotWrapper<Slot>,
> this, n_method));
>  };
>   template<typename Slot, typename T1>
>   boost::signals2::connection
> connect(boost::signals2::signal<void(T1)>& n_signal, Slot n_method) {
>      return n_signal.connect(boost::bind(&CommandQueue::slotWrapper<Slot,
> T1>, this, n_method, _1));
>   }
> // ... more to come with more parameters T2, T3.....
>
> private:
>   template<typename Slot>
>   void slotWrapper(Slot n_method) {
>       post(n_method);
>   }
>
>  template<typename Slot, typename T1>
>  void slotWrapper(Slot n_method, T1 t1) {
>      boost::function<void(T1)> f(n_method);
>      post(boost::bind(f, t1));
>  }
> // ... more to come with more parameters ...
>
>   boost::asio::io_service     m_iosrv;
> };
>
>
> Now I can use this like this:
>
> struct testslot_one {
>  void operator()(int n_arg) const {
>      std::cout << "testslot 1: " << n_arg << std::endl;
>  }
> };
>
> main {
>  Queue q;
>  boost::signals2::signal<void (int)> sig1;
>
>  struct testslot_one t1;
>  q.connect(sig1, t1);
>
>  // signal not yet executed but only the handler posted
>  sig1(42);
>
>  boost::system::error_code errc;
>  // here we execute the accumulated signals
>  q.process(errc);
> }
>
> Now this works OK so far but I have two problems:
>
> First of all, the standard use case will be to bind member functions
> and not seperate functors such as "testslot_one" in this example.
> Which is when the connect fails. For reasons unknown to me. But that
> must work.
> Second, I want to get rid of the "slotWrapper" functions and replace
> them by a phoenix expression. If that makes sense, which I'm not sure
> of.
>
> Also, I am not certain about the whole thing. Can a phoenix generated
> function actually serve this way? Just post the handler when the
> signal is triggered?
>
> Any opinions are appreciated!
>
> Cheers,
> Stephan
>


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