Re: [sigc] Handling signal loops (Solved)



On Tue, 2005-09-27 at 09:58 +0400, Andrew E. Makeev wrote:
> Timothy M. Shead wrote:
> 
> >On Mon, 2005-09-26 at 10:25 +0400, Andrew E. Makeev wrote:
> >  
> >
> >>Timothy M. Shead wrote:
> >>
> >>    
> >>
> >>>I'm wondering if anyone has come across a way to handle signal "loops" -
> >>>that is to say, if signal A is connected to signal B, and B to A, is
> >>>there any way to prevent emission of either from entering an infinite
> >>>loop?  I tried creating a custom accumulator, but discovered that a new
> >>>instance of the accumulator is created every time emit() is called.  I
> >>>know it sounds crazy, but I'd like to find a way to see that every
> >>>signal in a given loop gets called, then the loop is broken.
> >>>
> >>>
> >>> 
> >>>
> >>>      
> >>>
> >>Try static member for accumulator class, and increase it in each signal 
> >>callback, so, when you hit "odd" number, for example, stop the signal 
> >>emission with accumulator return state.
> >>Guess, that's clear.
> >>    
> >>
> >
> >Seems like I could use this to impose an arbitrary limit on the number
> >of emissions that take place, and thus prevent infinite loops, but I
> >would have know way of knowing whether I'd hit every signal
> >once-and-only-once, or whether I terminated too soon ... unless I'm
> >missing something?
> >  
> >
> Using static flags you could do whatever you would to.
> One way:
> flag = 0 - no signal
> flag = 1 - 1st signal
> flag = 2 - 2nd signal
> When enter 1st slot, check if (flag == 0 || flag == 2) else (duplicate, 
> stop). if (flag == 2) then (flag = 0, stop) else (flag = 1).
> When enter 2nd slot, check if (flag == 0 || flag == 1) else (duplicate, 
> stop). if (flag == 1) then (flag = 0, stop) else (flag = 2).

Andrew:

Seems like this approach assumes that you know in advance how many
signals are connected and in what topology.  As background, we are using
signals in an arbitrary network of nodes to propagate changes in one
node to its dependencies.  The network is extremely dynamic, and we've
been wanting to allow arbitrary loops.

You did get me thinking of alternatives, until I realized that a custom
function object does the trick - I ended-up replacing

	A.connect(B.make_slot());

with

	A.connect(make_loop_safe_slot(B));

I've copied my function object below for others.

Many thanks for the ideas!
Tim




template<typename SignalT>
class loop_safe_slot
{
public:
        loop_safe_slot(SignalT& Signal) :
                signal(Signal),
                emitting(false)
        {
        }

        void operator()()
        {
                if(emitting)
                        return;

                emitting = true;
                signal.emit();
                emitting = false;
        }

private:
        SignalT& signal;
        bool emitting;
};

template<typename SignalT>
loop_safe_slot<SignalT> make_loop_safe_slot(SignalT& Signal)
{
        return loop_safe_slot<SignalT>(Signal);
}








[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]