Time Bounded Function Calls? #36
Replies: 8 comments 1 reply
-
Sure! this can be accomplished several ways, but they all come down to the
same thing. Every instruction might be the one the VM has to exit on so
every instruction adds an "if()" check. Not a big deal unless you are
trying to squeeze every last ounce of speed out.
So I will add a countdown flag to the VM which will be compiled in if the
operator wants that functionality, it will look like this:
int g_instructionCounter = -1;
wr_run( .... , int instructions=-1 )
{
g_instructionCounter = instructions;
while( g_instructionCounter )
{
if ( g_instructionCounter > 0 ) { --g_instructionCounter; }
// do a VM instruction
}
// FORCE a yield!
}
So an external thread can set g_instructionCounter to '0' and cause the VM
thread to immediately yield (on it's next instruction) or if the countdown
reaches zero on it's own then the time slice is over.
That get the job done for you?
…-Curt
On Mon, Jun 17, 2024 at 5:29 PM Cole Roof ***@***.***> wrote:
Right now we are using Wrench as a sandbox for user created scripts to run
within the context of our application. We'd like the sandbox to be very
safe for the users - so they can't accidentally brick the whole device if
they write a bad script. *(With an infinite loop for example)*
I'm fairly certain this feature doesn't exist already, and I'm not very
familiar with the inner workings of the wrench VM, so I'm mainly asking
conceptually as a future feature. Would it be possible for the VM to do
something like
wr_run_timeout(WRState* w, unsigned char* bytecode, int outlen, int timeout_ms)
// or
wr_callFunction_timeout(WRContext* context, WRFunction* func, int timeout_ms)
or have some way, in an external loop, to time bound the running of the
function
int start_ms = now();
// Externally force the code to only run for a maximum of 1000ms
while( now() - start_ms < 1000 )
{
// Running for a 'tick' could be some arbitrary time slice (1ms) or some number of instructions that run (10 bytecode instructions)
wr_run_tick(...);
}
*The 'tick' number could be some compile time directive like stack size,
or possibly set in the constructor of the context*
Thanks so much!
—
Reply to this email directly, view it on GitHub
<#36>, or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AALIKA3O5ID7PRIFJ336TLTZH5IMHAVCNFSM6AAAAABJOYUFHKVHI2DSMVQWIX3LMV43ERDJONRXK43TNFXW4OZWHAZTENRUHE>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
Would you consider the tick model instead… or as well? Tick would allow for the wrench code to run in a loop function in the Arduino environment without blocking other recurring background checks that are not interrupt based. The user would then be able to write an endless loop in wrench while the main system is unaffected. Eg void loop() {wr_tick()} I guess this is relevant for general execution more than function calls but could be the same concept for both. It would fit very well with a common non-blocking pattern for Arduino libraries, watchdog timers in Esp32 etc. |
Beta Was this translation helpful? Give feedback.
-
Okay I added some more functionality for you, including a basic round-robin scheduler and ticker(), I think this will do what you need? |
Beta Was this translation helpful? Give feedback.
-
… On Tue, Jun 18, 2024 at 1:06 AM madshobye ***@***.***> wrote:
Would you consider the tick model instead… or as well? Tick would allow
for the wrench code to run in a loop function in the Arduino environment
without blocking other recurring background checks that are not interrupt
based. The user would then be able to write an endless loop in wrench while
the main system is unaffected. Eg
void loop() {wr_tick()}
I guess this is relevant for general execution more than function calls
but could be the same concept for both.
It would fit very well with a common non-blocking pattern for Arduino
libraries, watchdog timers in Esp32 etc.
—
Reply to this email directly, view it on GitHub
<#36 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AALIKAZY45QSSB2HNAJK6ZLZH656JAVCNFSM6AAAAABJOYUFHKVHI2DSMVQWIX3LMV43SRDJONRXK43TNFXW4Q3PNVWWK3TUHM4TQMBRGU4DG>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
Sorry, I think I misunderstood the yielding feature, here is a new version of my example code //
// // Example Wrench Script
// // All scripts will 'override' a `run` function
//
// function run( values_hashtable )
// {
// for(;;)
// {
// values_hashtable["random_number"] += 1
// }
// }
//
void run_wrench_script()
{
// Load all the bytecode in to memory some how
std::vector<uint8_t *> scripts;
wr_setInstructionsPerSlice(10); // Force the VM to yeild every 10 jumps
// Safely run all the scripts in series, with a timeout if they ran too long
for( uint8_t *bytecode : scripts)
{
WRState* state = wr_newState();
WRContext* context = wr_run(state, bytecode);
// Start the running of my function
WRValue* retval = wr_callFunction(context, "run");
time_t now = now(); // assume timestamp in ms
while( now() - now < 5000 ) // only allow to run for 5 seconds
{
if( retval == NULL && wr_getYeildInfo(context) )
{
println("The function was force yeilded");
retval = wr_continue(context);
}
else
{
println("The function ended by itself");
break; // We can break from the loop because the function is done
}
}
wr_destroyState( w );
}
} |
Beta Was this translation helpful? Give feedback.
-
Your code had some bugs in it that I fixed up, here is a corrected example with notes. I need to modify the documentation to make clear that calling any of the overloaded
which should work for PC and linux. |
Beta Was this translation helpful? Give feedback.
-
oh and make sure you get latest 6.0.2 I changed some function signatures |
Beta Was this translation helpful? Give feedback.
-
This looks exactly like what we needed! Thanks so much, this new feature is great! |
Beta Was this translation helpful? Give feedback.
-
Right now we are using Wrench as a sandbox for user created scripts to run within the context of our application. We'd like the sandbox to be very safe for the users - so they can't accidentally brick the whole device if they write a bad script. (With an infinite loop for example)
I'm fairly certain this feature doesn't exist already, and I'm not very familiar with the inner workings of the wrench VM, so I'm mainly asking conceptually as a future feature. Would it be possible for the VM to do something like
or have some way, in an external loop, to time bound the running of the function
The 'tick' number could be some compile time directive like stack size, or possibly set in the constructor of the context
Thanks so much!
Beta Was this translation helpful? Give feedback.
All reactions