Interesting, thanks. This summer I am hoping an intern will work on investigating sync/async transformations, this stuff is very relevant to that.
- Alon On Mon, Mar 17, 2014 at 3:38 PM, Joel Croteau <[email protected]> wrote: > The syntax is a little different, but the C++11 promise/future template > offers essentially the same functionality. See > http://www.cplusplus.com/reference/future/promise/ for the usage of this, > and http://promises-aplus.github.io/promises-spec/ for the proposed > Javascript spec. > On Mar 17, 2014 3:16 PM, "Alon Zakai" <[email protected]> wrote: > >> I didn't know about the JavaScript Promises stuff, that's interesting. To >> allow sync-looking code on the C++ side, it would need to integrate with >> something there, if there is a c++11 feature that works there, as you say, >> then this might work very well. >> >> - Alon >> >> >> >> On Sun, Mar 16, 2014 at 11:44 PM, Joel Croteau <[email protected]>wrote: >> >>> I was able to implement this using Javascript Promises (I haven't made >>> this a pull request because it's rather experimental): >>> >>> emscripten_sync_wget2_data: function(url, request, param, arg, free, >>> onload, onerror, onprogress) { >>> var _url = Pointer_stringify(url); >>> var _request = Pointer_stringify(request); >>> var _param = Pointer_stringify(param); >>> >>> var promise = new Promise(function(resolve, reject) { >>> var http = new XMLHttpRequest(); >>> http.open(_request, _url, true); >>> http.responseType = 'arraybuffer'; >>> >>> // LOAD >>> http.onload = function http_onload(e) { >>> if (http.status == 200 || _url.substr(0,4).toLowerCase() != >>> "http") { >>> resolve(http.response); >>> } >>> else { >>> reject(http.status, http.statusText); >>> } >>> }; >>> >>> // ERROR >>> http.onerror = function http_onerror(e) { >>> reject(http.status, http.statusText); >>> }; >>> >>> // PROGRESS >>> http.onprogress = function http_onprogress(e) { >>> if (onprogress) Runtime.dynCall('viii', onprogress, [arg, >>> e.loaded, e.lengthComputable || e.lengthComputable === undefined ? e.total >>> : 0]); >>> }; >>> >>> // Useful because the browser can limit the number of redirection >>> try { >>> if (http.channel instanceof Ci.nsIHttpChannel) >>> http.channel.redirectionLimit = 0; >>> } catch (ex) { /* whatever */ } >>> >>> if (_request == "POST") { >>> //Send the proper header information along with the request >>> http.setRequestHeader("Content-type", >>> "application/x-www-form-urlencoded"); >>> http.setRequestHeader("Content-length", _param.length); >>> http.setRequestHeader("Connection", "close"); >>> http.send(_param); >>> } else { >>> http.send(null); >>> } >>> }); >>> >>> promise.then(function(data) { >>> var byteArray = new Uint8Array(data); >>> var buffer = _malloc(byteArray.length); >>> HEAPU8.set(byteArray, buffer); >>> if (onload) Runtime.dynCall('viii', onload, [arg, buffer, >>> byteArray.length]); >>> if (free) _free(buffer); >>> }, function(status, statusText) { >>> if (onerror) Runtime.dynCall('viii', onerror, [arg, status, >>> statusText]); >>> }); >>> }, >>> >>> Promises are still fairly new, and only supported by the most recent >>> versions of Chrome and Firefox, but they do give us the functionality we >>> want here. I think the best way to implement this in code would be if I >>> could use the C++ promise and future APIs. You can use these if you compile >>> with -std=c++11. All this seems to do at present is send the code into an >>> infinite loop, but if they could map into equivalent Javascript promise >>> calls, I think it could work quite well. At least in the case of >>> emscripten_sync_wget2_data, it could be set to use synchronous XHRs as a >>> fallback. This would still work, just require some extra conversion work, >>> and wouldn't call onprogress events. >>> >>> On Sunday, March 16, 2014 7:17:56 PM UTC-7, Alon Zakai wrote: >>> >>>> It can capture its environment, so you can put the second half of the >>>> function in a lambda, and call the lambda later on when you want to, in >>>> response to something. >>>> >>>> - Alon >>>> >>>> >>>> >>>> On Sun, Mar 16, 2014 at 7:12 PM, Joel Croteau <[email protected]>wrote: >>>> >>>>> I can understand using Javascript generators, but how would c++ >>>>> lambdas help? >>>>> On Mar 16, 2014 3:47 PM, "Alon Zakai" <[email protected]> wrote: >>>>> >>>>>> Currently not. It would require a very different code generation >>>>>> approach than we currently have. >>>>>> >>>>>> In theory something similar could be done using generators, in very >>>>>> recent versions of firefox and chrome. But even with the help of >>>>>> generators, this is not easy to do, and it is not clear how it would >>>>>> affect >>>>>> performance - likely very adversely. >>>>>> >>>>>> One similar thing you can do is manage your own code using c++11 >>>>>> lambdas. You could write a little system that continues to run the >>>>>> current >>>>>> function once a callback triggers that. >>>>>> >>>>>> - Alon >>>>>> >>>>>> >>>>>> >>>>>> On Sun, Mar 16, 2014 at 1:43 AM, Joel Croteau <[email protected]>wrote: >>>>>> >>>>>>> I would like to have a function that makes an async call, and >>>>>>> returns control to the browser during the call, then resumes once the >>>>>>> async >>>>>>> call is complete. However, I would like this to appear to the calling >>>>>>> code >>>>>>> to be a synchronous call. So for instance, I could do something like >>>>>>> this: >>>>>>> >>>>>>> struct FileInfo >>>>>>> { >>>>>>> void* buffer; >>>>>>> unsigned size; >>>>>>> }; >>>>>>> >>>>>>> FileInfo loadUrl(const char* url) >>>>>>> { >>>>>>> FileInfo info; >>>>>>> emscripten_async_wget2_data(url, "GET", "", &info, false, >>>>>>> onload, onerror, onprogress); >>>>>>> emscripten_pause(); // Blocks until emscripten_resume() is called >>>>>>> return info; >>>>>>> } >>>>>>> >>>>>>> void onerror(void* ptr, int code, const char* desc) >>>>>>> { >>>>>>> // Handle not found, etc. >>>>>>> } >>>>>>> >>>>>>> void onprogress(void* ptr, int loaded, int total) >>>>>>> { >>>>>>> // Update progress bar >>>>>>> } >>>>>>> >>>>>>> void onload(void* ptr, void* buffer, unsigned size) >>>>>>> { >>>>>>> static_cast<FileInfo*>(ptr)->buffer = buffer; >>>>>>> static_cast<FileInfo*>(ptr)->size = size; >>>>>>> >>>>>>> emscripten_resume(); // Now loadUrl resumes and returns FileInfo. >>>>>>> } >>>>>>> >>>>>>> Is there any way to do this? >>>>>>> >>>>>>> -- >>>>>>> You received this message because you are subscribed to the Google >>>>>>> Groups "emscripten-discuss" group. >>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>> send an email to [email protected]. >>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>> >>>>>> >>>>>> -- >>>>>> You received this message because you are subscribed to a topic in >>>>>> the Google Groups "emscripten-discuss" group. >>>>>> To unsubscribe from this topic, visit https://groups.google.com/d/ >>>>>> topic/emscripten-discuss/Op5ifeMjauA/unsubscribe. >>>>>> To unsubscribe from this group and all its topics, send an email to >>>>>> [email protected]. >>>>>> >>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>> >>>>> -- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "emscripten-discuss" group. >>>>> To unsubscribe from this group and stop receiving emails from it, send >>>>> an email to [email protected]. >>>>> For more options, visit https://groups.google.com/d/optout. >>>>> >>>> >>>> -- >>> You received this message because you are subscribed to the Google >>> Groups "emscripten-discuss" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to [email protected]. >>> For more options, visit https://groups.google.com/d/optout. >>> >> >> -- >> You received this message because you are subscribed to a topic in the >> Google Groups "emscripten-discuss" group. >> To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/emscripten-discuss/Op5ifeMjauA/unsubscribe >> . >> To unsubscribe from this group and all its topics, send an email to >> [email protected]. >> For more options, visit https://groups.google.com/d/optout. >> > -- > You received this message because you are subscribed to the Google Groups > "emscripten-discuss" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "emscripten-discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
