So I've been using an event range rather than an event loop or event/listener system; because I realized I could process events more effectively using a recursive descent parser on them. So I made this class to strip the events into different ranges and send them to different parsers:

auto demultiplex(alias attrFunc, string functional, Range)(Range r)
{
        alias attr = std.functional.unaryFun!(attrFunc);
        alias T    = ElementType!(Range);
        
        struct SlaveRange {
        private T**               _front;
        private Fiber _fiber;           
                this(T ** it) { 
                        _front = it;
                        _fiber = Fiber.getThis();
                }
                
                @property bool empty() const { return *_front is null; }
                @property T    front() const { return *(*_front); }
                          void popFront()    { _fiber.call(); }
        }
                
        struct MasterRange {
                private SlaveRange        _slave;
                private Range             _input;
                private T                 _cur;
                private T               * _front;
                private Fiber _fiber;
                
                private void run() {
                        mixin("_slave." ~ functional ~ ";");
                }
                
                private void call() {
                        if(_fiber.state != Fiber.State.TERM)
                                _fiber.call();
                }
                
                this(Range ins) {
                        _input = ins;
                        _fiber = new Fiber(&run);
                        _slave = &_front;
                        popFront();
                        _front = &_cur;
                }
                
                @property T    front() const { return *_front; }
                @property bool empty() const { return _front is null; }         
                
                void popFront()    {
                        while(!_input.empty) {
                                _cur = _input.front;
                                _input.popFront();
                                
                                final switch(attr(_cur)) {
                                case -1: break;
                                case  0: return;
                                case  1: call(); break;
                                case  2: call(); return;
                                }
                        }                       
                        _front = null;
                }
        }

        return MasterRange(r);
}

the problem is that when the SlaveRange is constructed it needs to know the current fiber, but if it isn't called from a fiber then it returns null and can't switch back. And I can't use yeild because I don't want to return to the calling fiber, that doesn't help me.

Reply via email to