Open creynders opened 11 years ago
cc @ondina
Have you seen this comment too? http://knowledge.robotlegs.org/discussions/robotlegs-2/3327-go-modular-for-multiple-games#comment_27433210
Yeah I saw it, but though that's ok as a temporary solution, this is something that needs to be fixed. Need to think on how to fix it though.
Of course.
Wow, you're totally losing me :)
How does that exactly help? You'd still need to do this:
[Inject (name='A-and-B')]
public var eventDispatcher:IEventDispatcher;
eventDispatcher.dispatchEvent(ModularConnectorEvent.A_TO_B_MESSAGE);
Right? We're still talking about a module instance sending events to other instances of the same module, right?
Yeah, I deleted the bs. My intention was to have a dispatcher for the inter-instances communication that doesn’t relay any events and kind of a local interceptor that would decide what to do with the received event, maybe made clear in the mappings or a guard ...weird, I know.
As I understand (still studying the code), the infinite loop is caused by having the same dispatcher as a receiver and as a relayer, listening to and dispatching the same event. The moment it receives the event, it relays it again.
Anyway, I’ll continue studying the ModuleConnector & Co and keep my mouth shut ;)
Anyway, I’ll continue studying the ModuleConnector & Co and keep my mouth shut ;)
No, no, that's how solutions are found. 99% BS and 1% good ideas. At least that's how it is for me. :)
I remember worrying about circular relays.. and even possibly coming up with solution.. and then totally forgetting. The fix probably needs to live in the EventRelay
.
I made another attempt to break the infinite loop. BS or not, but it works.
I couldn't create a gist for some reasons, so here is the code: https://github.com/Ondina/robotlegs-bender-modular-air/wiki/ModuleConnectionConfigurator---breaking-the-infinite-loop
[1] localDispatcher dispatches [2] channelDispatcher listens [3] channelDispatcher dispatches [4] localDispatcher listens [5] localDispatcher dispatches [6] channelDispatcher listens [7] channelDispatcher dispatches and so on
Here is the loop breaker:
public function onEventDispatched(event:*):void
{
if (_channelDispatcher == event.target)
{
_localDispatcher.removeEventListener(event.type, _channelDispatcher.dispatchEvent);
}
else
{
_localDispatcher.addEventListener(event.type, _channelDispatcher.dispatchEvent);
}
}
I looked at the EventRelay and I think it's not the right place to make changes, since all it does is adding and removing listeners and it shouldn't have to know about events being dispatched. In fact, the ModuleConnectionConfigurator should not be burdened with that either, but where else do we have access to the dispatchers and the event types?
I also thought about using event's useCapture and phases or event.stopPropagation() inside of EventRelay , but I couldn't work it out, maybe because it doesn't make sense at all? Sorry for the ramblings, but infinite loops are dizzying...
I'm sure you'll come up with something better, so I'm really very curious about your solution to that ouroboric situation :)
@darscan could you, at least, give me a hint about the solution you had in mind
Interesting solution! I honestly can't remember where my thinking was at regarding this stuff. I'll have another dabble this w/e, and give more thought to your solution as well.
@darscan alright, there is no rush
Another thing I've tried was to have a callback function for each dispatcher, where they'd let the other dispatcher dispatch the event only if it wasn't already dispatched, depending on a counter. I could make it work only for instances of the same module. Somehow the counting was messed up for other modules and I gave up on this approach. I don't know what's better, relaying events manually depending on some condition, or adding/removing event listeners as I showed in my previous message. Anyway, adding/removing listeners was easier for me to implement while keeping the original logic of all the involved classes.
Btw, I changed the code a bit:
public function onEventDispatched(event:Event):void
{
if (_channelDispatcher == event.target)
_localToChannelRelay.removeType(event.type);
else
_localToChannelRelay.addType(event.type);
}
and added the type (EventRelay.addType) to the _types only if the type is not in _types.
[EDIT] I made it work (relaying events manually based on a counter) for all modules - different instances of same module *and different modules as well. I had to reset the counter in case the module did not have a mapping for receiving an event type. Still, not convinced it's a good approach.
Progress report
https://github.com/Ondina/robotlegs-bender-modular-air/wiki/ModuleConnectionConfigurator---take-2
It's just a draft.
I add listeners to the parentDispatcher:
_parentDispatcher.addEventListener(ModularRouterEvent.LOCAL_TO_PARENT, parentToLocalRouter);
and to the localDispatcher:
public function addListener(eventType:String):void
{
_eventTypeDispatched[eventType] = false;
_localDispatcher.addEventListener(eventType, localToParentRouter);
}
The handlers:
private function localToParentRouter(event:Event):void
{
if (!_eventTypeDispatched[event.type])
{
_eventTypeDispatched[event.type] = true;
_parentDispatcher.dispatchEvent(new ModularRouterEvent(ModularRouterEvent.LOCAL_TO_PARENT, _context, event, event.type));
}
_eventTypeDispatched[event.type] = false;
}
private function parentToLocalRouter(event:ModularRouterEvent):void
{
if (_context != event.context)
{
_eventTypeDispatched[event.eventType] = true;
_localDispatcher.dispatchEvent(event.eventClass);
}
}
What about creating a lifecycle for the modular events?
https://gist.github.com/Ondina/6138055 (https://github.com/Ondina/robotlegs-bender-modular-air/wiki/ModuleConnectionConfigurator---ModularRouter)
If you try to have several instance of the same module communicate with each other through the module connector, you run into an infinite loop:
see http://knowledge.robotlegs.org/discussions/robotlegs-2/3327-go-modular-for-multiple-games