Emscripten sandwiched by asynchronous Javascript Code











up vote
1
down vote

favorite












I'm trying to use Emscripten to write a Software to run in browser but also on other architectures (e.g. Android, PC-standalone app).



The Software structure is something like this:



main_program_loop() {
if (gui.button_clicked()) {
run_async(some_complex_action, gui.text_field.to_string())
}
if (some_complex_action_has_finished())
{
make_use_of(get_result_from_complex_action());
}
}

some_complex_action(string_argument)
{
some_object = read_local(string_argument);
interm_res = simple_computation(some_object);
other_object = expensive_computation(interm_res);
send_remote(some_object.member_var, other_object);
return other_object.member_var;
}


Let's call main_program_loop the GUI or frontend, some_complex_action the intermediate layer, and read_local, send_remode and expensive_computation the backend or lower layer.



Now the frontend and backend would be architecture specific (e.g. for Javascript read_local could use IndexDB, send_remote could use fetch),
but the intermediate layer should make up more then 50% of the code (that's why I do not want to write it two times in two different languages, and instead write it once in C and transpile it to Javascript, for Android I would use JNI).



Problems come in since in Javascript the functions on the lowest layer (fetch etc) run asyncronously (return a promise or require a callback).



One approach I tried was to use promises and send IDs through the intermediate layer



var promises = {};
var last_id = 0;
handle_click() {
var id = Module.ccall('some_complex_action', 'number', ['string'], [text_field.value]);
promises[id].then((result) => make_us_of(result));
}

recv_remote: function(str) {
promises[last_id] = fetch(get_url(str)).then((response) => response.arrayBuffer());
last_id += 1;
return last_id - 1;
}


It works for the simple case of



some_complex_action(char *str)
{
return recv_remote(str);
}


But for real cases it seem to be getting really complicated, maybe impossible. (I tried some approach where I'd given every function a state and every time a backend function finishes, the function is recalled and advances it's state or so, but the code started getting complicated like hell.) To compare, if I was to call some_complex_action from C or Java, I'd just call it in a thread separate from the GUI thread, and inside the thread everything would happen synchronously.



I wished I could just call some_complex_action from an async function and put await inside recv_remote but of cause I can put await only directly in the async function, not in some function called down the line. So that idea did not work out either.



Ideally if somehow I could stop execution of the intermediate Emscripten transpiled code until the backend function has completed, then return from the backend function with the result and continue executing the transpiled code.



Has anyone used Emterpreter and can imagine that it could help me get to my goal?



Any ideas what I could do?










share|improve this question




























    up vote
    1
    down vote

    favorite












    I'm trying to use Emscripten to write a Software to run in browser but also on other architectures (e.g. Android, PC-standalone app).



    The Software structure is something like this:



    main_program_loop() {
    if (gui.button_clicked()) {
    run_async(some_complex_action, gui.text_field.to_string())
    }
    if (some_complex_action_has_finished())
    {
    make_use_of(get_result_from_complex_action());
    }
    }

    some_complex_action(string_argument)
    {
    some_object = read_local(string_argument);
    interm_res = simple_computation(some_object);
    other_object = expensive_computation(interm_res);
    send_remote(some_object.member_var, other_object);
    return other_object.member_var;
    }


    Let's call main_program_loop the GUI or frontend, some_complex_action the intermediate layer, and read_local, send_remode and expensive_computation the backend or lower layer.



    Now the frontend and backend would be architecture specific (e.g. for Javascript read_local could use IndexDB, send_remote could use fetch),
    but the intermediate layer should make up more then 50% of the code (that's why I do not want to write it two times in two different languages, and instead write it once in C and transpile it to Javascript, for Android I would use JNI).



    Problems come in since in Javascript the functions on the lowest layer (fetch etc) run asyncronously (return a promise or require a callback).



    One approach I tried was to use promises and send IDs through the intermediate layer



    var promises = {};
    var last_id = 0;
    handle_click() {
    var id = Module.ccall('some_complex_action', 'number', ['string'], [text_field.value]);
    promises[id].then((result) => make_us_of(result));
    }

    recv_remote: function(str) {
    promises[last_id] = fetch(get_url(str)).then((response) => response.arrayBuffer());
    last_id += 1;
    return last_id - 1;
    }


    It works for the simple case of



    some_complex_action(char *str)
    {
    return recv_remote(str);
    }


    But for real cases it seem to be getting really complicated, maybe impossible. (I tried some approach where I'd given every function a state and every time a backend function finishes, the function is recalled and advances it's state or so, but the code started getting complicated like hell.) To compare, if I was to call some_complex_action from C or Java, I'd just call it in a thread separate from the GUI thread, and inside the thread everything would happen synchronously.



    I wished I could just call some_complex_action from an async function and put await inside recv_remote but of cause I can put await only directly in the async function, not in some function called down the line. So that idea did not work out either.



    Ideally if somehow I could stop execution of the intermediate Emscripten transpiled code until the backend function has completed, then return from the backend function with the result and continue executing the transpiled code.



    Has anyone used Emterpreter and can imagine that it could help me get to my goal?



    Any ideas what I could do?










    share|improve this question


























      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      I'm trying to use Emscripten to write a Software to run in browser but also on other architectures (e.g. Android, PC-standalone app).



      The Software structure is something like this:



      main_program_loop() {
      if (gui.button_clicked()) {
      run_async(some_complex_action, gui.text_field.to_string())
      }
      if (some_complex_action_has_finished())
      {
      make_use_of(get_result_from_complex_action());
      }
      }

      some_complex_action(string_argument)
      {
      some_object = read_local(string_argument);
      interm_res = simple_computation(some_object);
      other_object = expensive_computation(interm_res);
      send_remote(some_object.member_var, other_object);
      return other_object.member_var;
      }


      Let's call main_program_loop the GUI or frontend, some_complex_action the intermediate layer, and read_local, send_remode and expensive_computation the backend or lower layer.



      Now the frontend and backend would be architecture specific (e.g. for Javascript read_local could use IndexDB, send_remote could use fetch),
      but the intermediate layer should make up more then 50% of the code (that's why I do not want to write it two times in two different languages, and instead write it once in C and transpile it to Javascript, for Android I would use JNI).



      Problems come in since in Javascript the functions on the lowest layer (fetch etc) run asyncronously (return a promise or require a callback).



      One approach I tried was to use promises and send IDs through the intermediate layer



      var promises = {};
      var last_id = 0;
      handle_click() {
      var id = Module.ccall('some_complex_action', 'number', ['string'], [text_field.value]);
      promises[id].then((result) => make_us_of(result));
      }

      recv_remote: function(str) {
      promises[last_id] = fetch(get_url(str)).then((response) => response.arrayBuffer());
      last_id += 1;
      return last_id - 1;
      }


      It works for the simple case of



      some_complex_action(char *str)
      {
      return recv_remote(str);
      }


      But for real cases it seem to be getting really complicated, maybe impossible. (I tried some approach where I'd given every function a state and every time a backend function finishes, the function is recalled and advances it's state or so, but the code started getting complicated like hell.) To compare, if I was to call some_complex_action from C or Java, I'd just call it in a thread separate from the GUI thread, and inside the thread everything would happen synchronously.



      I wished I could just call some_complex_action from an async function and put await inside recv_remote but of cause I can put await only directly in the async function, not in some function called down the line. So that idea did not work out either.



      Ideally if somehow I could stop execution of the intermediate Emscripten transpiled code until the backend function has completed, then return from the backend function with the result and continue executing the transpiled code.



      Has anyone used Emterpreter and can imagine that it could help me get to my goal?



      Any ideas what I could do?










      share|improve this question















      I'm trying to use Emscripten to write a Software to run in browser but also on other architectures (e.g. Android, PC-standalone app).



      The Software structure is something like this:



      main_program_loop() {
      if (gui.button_clicked()) {
      run_async(some_complex_action, gui.text_field.to_string())
      }
      if (some_complex_action_has_finished())
      {
      make_use_of(get_result_from_complex_action());
      }
      }

      some_complex_action(string_argument)
      {
      some_object = read_local(string_argument);
      interm_res = simple_computation(some_object);
      other_object = expensive_computation(interm_res);
      send_remote(some_object.member_var, other_object);
      return other_object.member_var;
      }


      Let's call main_program_loop the GUI or frontend, some_complex_action the intermediate layer, and read_local, send_remode and expensive_computation the backend or lower layer.



      Now the frontend and backend would be architecture specific (e.g. for Javascript read_local could use IndexDB, send_remote could use fetch),
      but the intermediate layer should make up more then 50% of the code (that's why I do not want to write it two times in two different languages, and instead write it once in C and transpile it to Javascript, for Android I would use JNI).



      Problems come in since in Javascript the functions on the lowest layer (fetch etc) run asyncronously (return a promise or require a callback).



      One approach I tried was to use promises and send IDs through the intermediate layer



      var promises = {};
      var last_id = 0;
      handle_click() {
      var id = Module.ccall('some_complex_action', 'number', ['string'], [text_field.value]);
      promises[id].then((result) => make_us_of(result));
      }

      recv_remote: function(str) {
      promises[last_id] = fetch(get_url(str)).then((response) => response.arrayBuffer());
      last_id += 1;
      return last_id - 1;
      }


      It works for the simple case of



      some_complex_action(char *str)
      {
      return recv_remote(str);
      }


      But for real cases it seem to be getting really complicated, maybe impossible. (I tried some approach where I'd given every function a state and every time a backend function finishes, the function is recalled and advances it's state or so, but the code started getting complicated like hell.) To compare, if I was to call some_complex_action from C or Java, I'd just call it in a thread separate from the GUI thread, and inside the thread everything would happen synchronously.



      I wished I could just call some_complex_action from an async function and put await inside recv_remote but of cause I can put await only directly in the async function, not in some function called down the line. So that idea did not work out either.



      Ideally if somehow I could stop execution of the intermediate Emscripten transpiled code until the backend function has completed, then return from the backend function with the result and continue executing the transpiled code.



      Has anyone used Emterpreter and can imagine that it could help me get to my goal?



      Any ideas what I could do?







      javascript asynchronous emscripten






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 17 at 19:47

























      asked Nov 17 at 19:29









      matec

      4461516




      4461516





























          active

          oldest

          votes











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














           

          draft saved


          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53354781%2femscripten-sandwiched-by-asynchronous-javascript-code%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















           

          draft saved


          draft discarded



















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53354781%2femscripten-sandwiched-by-asynchronous-javascript-code%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Costa Masnaga

          Fotorealismo

          Sidney Franklin