Should twrConsoleCanvas.twrConDrawSeq use noBlock?
The noBlock twrLibrary option causes a the "RPC" message (sent from the Worker proxy to the JS Main Thread) to not wait for a return. It can be used on functions that return a void. For many functions this works fine and increases performance (the C code does not block, and two cores are potentially used -- the Worker and the Main thread). For twrConDrawSeq, i think this would work, with the exception that certain calls (like measure text) need to fill in the results before the C code unblocks. Think about if there is a way to solve for this. For example, we could add a "WaitForDrawSeqToComplete" type call that is optional. Or We could move functions like "measure text" out of twrConDrawSeq. You might have other ideas.
I'll think about it, but from the options you suggested I think something like WaitForDrawSeqToRecomplete would be the easiest for the user. It ensures that twrConDrawSeq is called for all of the currently queued commands so that calls like measuretext have up to date info without having to flush everything. In addition, if flushing (because it uses twrConDrawSeq) is non-blocking, it could cause issues with already external functions (like load image) that might require flush() to be fully called before running.
WaitForDrawSeqToComplete seems like a simple solution. Another, more backwards compatible options would be to add twrConDrawSeqNoWait. (or twrConDrawSeqAsync at the risk of overusing the term Async)
That sounds good to me. Though, does backwards compatibility matter in this case? Shouldn't the user be using d2d_start_draw_sequence, d2d_end_draw_sequence, and d2d_flush rather than directly calling twrConDrawSeq directly? In that case, either works and all that would need changing is deciding which internal API is called depending on the function.
I did think of two things though:
- What happens if two non-blocking calls or a non-blocking and blocking call are called back to back before the first one is actually processed. Does javascript ensure that the events are parsed in the proper order without anything being dropped?
- What happens if non-blocking calls are made faster than typescript can parse them? I'm not sure if this will really be an issue with the canvas, but I'm wondering how much trouble code in C is processing and queuing functions faster than typescript can handle them could cause.
good point. But the same issue exists with the C APIs (how to get the benefits of noBlock without breaking existing apps).
Regarding your 2nd questions -- here is some text from my latest doc update:
Note that the messages sent from the proxy thread to the JS main thread (for function execution) will cause execution of function calls to serialize, and so if a function that blocks (waits for results from JS main thread) is called after a call with noBlock, everything should work as expected.
Do not use noBlock if:
- the function returns a value
- the C code should not continue executing until the function completes execution.
- if the following scenario could arise:
- funcA (with noBlock) called
- funcB called and returns a value or otherwise depends on funcA completing execution, and funcA uses async keyword.
Use noBlock carefully.
Regarding your 2nd concern: The C call causes a message to be sent, so that will allocate memory and queue up messages to the JavaScript main thread. If too many are made before they can process, i imagine eventually there would be a memory issue. It could also cause a lag in the results. If that were to happen, the api users would need to start waiting (which wouldn't really solve their problem, but would probably make more clear what is happening)..