mojox, events need to run on new fiber

About Monkey 2 Forums Monkey 2 Development mojox, events need to run on new fiber

This topic contains 18 replies, has 4 voices, and was last updated by  CopperCircle 2 years, 5 months ago.

Viewing 15 posts - 1 through 15 (of 19 total)
  • Author
    Posts
  • #4822

    skn3
    Participant

    Sorry for the topic spam. I am spending some time this weekend coding, so just posting stuff as I find it.

    So I have come across an issue in my app, and isolated it to a runnable example:

    [/crayon]

    Upon clicking any list item the app throws *Can’t suspend main fiber*. By looking at the mojox code this makes sense, the event handler is not run on a fiber.

    At first it confused me as I had a toolbar action lambda trigger that worked fine. It seems that the mojox toolbar currently has some built-in code to circumvent this with an Async flag, indicating if the callbacks should be run on a fiber. It appears this is the only place that has this functionality.

    What is the best course of action here?

    Can we perhaps be allowed to instruct mojox/mojo to **always** handle events on a fiber?

    #4824

    skn3
    Participant

    I created a small util function:

    [/crayon]

    Which is used like:

    [/crayon]

    It doesn’t work. Now it fails to build with

    C:/dev/projects/monkey1/conveyor/tools/itemMaker/itemMaker.buildv1.0.91/windows_debug/src/itemMaker_classes_2utils.cpp:192:27: error: declaration of ‘t_std_fiber_Fiber l_func’ shadows a parameter

    t_std_fiber_Fiber(l_func);

    If I change it to the follow, then it works:

    [/crayon]

    But this does seem a bit cludge!

    #4825

    Mark Sibly
    Keymaster

    (I HATE this fancy JS editor!)

    Anyway…

    At first it confused me as I had a toolbar action lambda trigger that worked fine.

    This is due to the ‘Action’ class which has an Async property which, if true (the default), runs triggered on a fiber. Except on emscripten, which doesn’t support fibers…

     

    Can we perhaps be allowed to instruct mojox/mojo to **always** handle events on a fiber?

    This is an interesting idea and something I tried once but couldn’t get working. But there have been several bugfixes since then so perhaps it’s worth trying again.

    But there’s also the issue of which callbacks from App to run on a fiber. Event handlers? App.Idle? AppActivated? Everything?

    Currently, Mojo is ‘fiber free’ which means it works everywhere, and callbacks at least know which fiber they’re running on! it’s a pretty simple/clean setup and I want to think pretty carefully before sacrificing that.

    Anyway, this should fix your problem for now:

    Perhaps mojox should *always* create fibers for OnClicked etc code?

    #4826

    Mark Sibly
    Keymaster

    The other alternative is:

    #4828

    skn3
    Participant

    Yeah the JS editor is a pain in the ass when adding code! Is there a markdown plugin for wordpress? Would be nice to use that instead! (https://en.support.wordpress.com/markdown/)

    Well I guess everything would have to be on a fiber. Anything else and you are always going to find a scenario where this may happen?

    Could we potentially tag our functions/lambdas as async, which indicates their calling mechanism? So it could be used like so:

    [/crayon]

    or

    [/crayon]

    I am surprised that emscripten doesn’t support fibers. future versions of JS will have generators, which are similar… https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*

    #4830

    Mark Sibly
    Keymaster

    Yeah, Async’s an option, but I’m not ready to go down that road just yet, ie: having to return a ‘future’ for non-void async funcs etc. Want to explore alternatives here, as this stuff gets confusing.

    Also, it doesn’t improve the situation much anyway as you can still forget to add async and end up in the same situation, althoguh it does make it easier to solve. Running ALL event handlers on a fiber does fix things, but in a too-blunt-for-my-liking way right now anyway.

    The best solution for now IMO is to tweak mojox so it creates fibers when necessary so the user doesn’t even have to think about it, but I’m gonna think on this one for a while…

    #4836

    skn3
    Participant

    When I was writing the previous reply, trying to ponder the ramifications of the Async suggestion, I did burn a few thousand braincells in the process! So yeah thats gonna be a long trip down the rabbit hole if you go that route!

    The mojox thing does sound like a decent stop gap, as your not gonna break anything core in monkey2.

    .

    #4837

    skn3
    Participant

    .

    #4838

    Mark Sibly
    Keymaster

    I think the general idea is more like:

    …so the AsyncFunc returns it’s ‘future’ result immediately (so it can run asynchronously – calling Get() effectively blocks) and it’s up to caller to actually await the result – or not, it can also just return the future without awaiting on it and itself return immediately, leaving it up to *its* caller to await etc.

    Adding ‘true’ (as in, this is what languages seem to be doing these days) async support to monkey2 would mean you’d be able to write the above async func something like this:

    The compiler would then internally create the future and fiber for you, and convert ‘return’ to ‘future.Set’.

    Note that my knowledge of this is purely academic – I haven’t had much experience coding like this ( a little in WinRT). I think I get it, but I also think it’s a style of coding you’ve got to really be ‘all in’ on, as it’s true benefit seems to lie in passing the future around. Perhaps someone here could clarify whether I’ve even got this right?!?

    But most of all, I’m curious if I can make it easier to use…

    #4839

    skn3
    Participant

    I removed my code above as was getting it to work. And here is the finished result 😀

    [/crayon]
    #4841

    skn3
    Participant

    Well clearly myn is a fugly LOL! I was trying to make it a self contained pattern, also similar to javascript with the commands passed to the callback/promise.

    Anyway, I just tried your version and this works a charm. My example modified to yours:

    [/crayon]

    So your correct about the theory. Once you start pushing around those async operations you have to keep doing so.

    I have had most experience using Promises in Javascript. With those you fire off a ton of operations which signal to the promise when they are complete. Like so:

    [/crayon]

    The awesomeness is you can keep returning new promises from your promise, or your .then() to chain together functionality into you callbacks. So you can break your code up into say, fetchUser(), generateImage(), updateCounters(), etc and have each return a promise. You can then piece together complex tasks and receive your result back in a chain of .then()’s.

    There is also Promise.All([]) which fires off a list of promises at once, and then() is called once all have finished.

    But anyway…

    #4843

    Mark Sibly
    Keymaster

    I believe promises are pretty much the same as futures, or more precisely, they’re the ‘other end’ of a future, ie: you ‘get’ the promise and ‘set’ the future (or vice versa). This decouples storage from sync mechanism (apparently). Your promise code doesn’t make much sense to me though – what ‘type’ are ‘resolve’ and ‘reject’?

    The ‘then’ stuff confuses me too. I encountered it in WinRT and it just didn’t make any sense. Why do this…

    …when you can (or should be able to) simpy do this:

    …as all you’re doing is executing some stuff in sequence?

    Even if dothis(), dothat() are async, surely ‘await dothis()’, ‘await dothat()’ is nicer?

    The WinRT demos were full of convoluted ‘then’ chains like this (with some very complex rules for exception handling) often just to load a bunch of resources, connect to servers etc. It just seemed nuts to me.

    But thinking about it now, I guess the point is to be able to sequence *any* series of functions decided upon at runtime, passing the output of one to the input of the next? Or am I still missing the point?

    #4847

    skn3
    Participant

    Well how about something like this:

    [/crayon]

    I can create modular promises that can perform async operations, and then have one final destination for catching exceptions.

    async and await are nice, but at the same time promises do have their merits. They fall down when you need to pass around more information then just one thing. You either have to contain the data in the parent closure, or build objects by passing it down the .then() chain. Its also possible to use Promise.all([]) and then build your object at the end. The .then() of Promise.all([]) receives an array with each promises result.

    #4850

    Mark Sibly
    Keymaster

    Nah, still don’t get it sorry. To me, that just look like an incredibly long windowed way of executing fetchUserData followed by downloadImage!

    Actually, just looking through MDN docs for promises and it’s a bit clearer now, but I can’t help feeling JS is stuck with promises because it don’t have fibers or async functions. But mx2 does and I don’t know if there’s any need for then() because of this, eg:

    #4851

    skn3
    Participant

    I think the benefit of promises cant really be shown in just one small snippet. For promises to be useful, everything has to be promises. So fetching from database, a promise. Creating an object, promise. Everything a promise. Then you can just encapsulate all your routines as promises. You can flow them together without really thinking. You can have one catch to rule them all as well. Regardless of which library the promise lives.

    But pretty much your correct. Promises are are to *fix* javascript lack of async/fiber. They were also introduced to solve the problem of a nested nightmare of callbacks.

    However javascript does have async/await on the horizon https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function it’s just not fully mainstream yet. I get the impression they are implementing this to *fix* the issues that promises brought with it.

    But yeah going off topic a little. I agree with tyou, mx2 should not go the promise route. The async/await using fibers/futures is much nicer!

Viewing 15 posts - 1 through 15 (of 19 total)

You must be logged in to reply to this topic.