Long running async method vs firing an event upon completion - events

I have to create a library that communicates with a device via a COM port.
In the one of the functions, I need to issue a command, then wait for several seconds as it performs a test (it varies from 10 to 1000 seconds) and return the result of the test:
One approach is to use async-await pattern:
public async Task<decimal> TaskMeasurementAsync(CancellationToken ctx = default)
{
PerformTheTest();
// Wait till the test is finished
await Task.Delay(_duration, ctx);
return ReadTheResult();
}
The other that comes to mind is to just fire an event upon completion.
The device performs a test and the duration is specified prior to performing it. So in either case I would either have to use Task.Delay() or Thread.Sleep() in order to wait for the completion of the task on the device.
I lean towards async-await as it easy to build in the cancellation and for the lack of a better term, it is self contained, i.e. I don't have to declare an event, create a EventArgs class etc.
Would appreciate any feedback on which approach is better if someone has come across a similar dilemma.
Thank you.

There are several tools available for how to structure your code.
Events are a push model (so is System.Reactive, a.k.a. "LINQ over events"). The idea is that you subscribe to the event, and then your handler is invoked zero or more times.
Tasks are a pull model. The idea is that you start some operation, and the Task will let you know when it completes. One drawback to tasks is that they only represent a single result.
The coming-soon async streams are also a pull model - one that works for multiple results.
In your case, you are starting an operation (the test), waiting for it to complete, and then reading the result. This sounds very much like a pull model would be appropriate here, so I recommend Task<T> over events/Rx.

Related

Find time between mono runnable subscribe call and runnable actually being executed

I have a mono created from a runnable. I am using an ExecutorService with fixed thread size to create Scheduler instance. I am creating multiple Mono's using below code and subscribing to them.
Mono.fromRunnable(new Runnable() {
//Some business logic
}).subscribeOn(scheduler)
These subscriptions can happen parallel due to invocations from multiple calls and we are using a common ExecutorService for all these invocations, there could be possibility of lag between when it is subscribed and when "Some business logic" block mentioned below is actually executed due to limited thread size set for ExecutorService. Is there a way to find this time lag between when it is subscribed and when it actually got a thread to be executed?
There's no built-in way that I know of, so the best you'll likely do is use doOnSubscribe() (on the Mono object) to save one timestamp, and then create another timestamp as the first line of the run() method in that Runnable.
Those timestamps can then be compared to work out what, if any, lag is present.

How to efficiently check the time to fire an event?

This is a larger question about how computers are able to fire tasks based off a time trigger.
I'm building a game in Unity with a GameManager singleton Instance that runs a game clock. I want events to happen periodically throughout the game, but it seems inefficient and counter-intuitive to run a time variable through a series of if-statements to know when an event should happen.
I've also been developing mobile apps, and I've always wondered how an alarm works (is this similar to the above context?). Does the device/underlying tasks run 24hours of the day and wait by checking the equivalent of an if-statement to know when to alert the alarm event?
What you've described is basically how computers do events. most event-driven programs including the OS itself use what is called a pooling system where the system will go throw a large list of all existing events and check if their firing condition is met. This firing condition can be a time or other triggers such as input being received from a device like a keyboard or network card.
The Unity engine actually does this too. Behind the scenes, Unity will have a main process running constantly checking if the firing conditions for all the built-in monobehaviour methods have been met and then firing the methods if they have. For example, the FixedUpdate method is guaranteed to be called so many times per second, i believe its 30 times a second but i'm not sure off the top of my head. so the calling method for fixed update would simply be something like this.
timer += Time.deltaTime();
while(timer >= (1.0f/30.0f))
{
FixedUpdate();
timer -= (1.0f/30.0f);
}
This code would run as often as the processor would allow, constantly checking if enough time has passed to perform another call to FixedUpdate(), this code also performs backdating so if the processor become overloaded and this code doesn't get called for say 2 seconds then the next time it gets called it will perform enough calls for the 2 seconds that were missed.
Now for your unity application, if this is going to be small class say only around 10 time conditions then i would just use if statements as you suggest any more than that and i would start considering taking a more oop approach and have a abstract class with two methods
abstract class ConditionEvent{
bool ConditionMet();
void Process();
}
Then in your MonoBehavour call i would have a list of filled with these classes with a loop that calls the ConditionMet function. If the function returns true then call Process.

Creating a simple scheduler

How would I go about creating a simple Scheduler that say, delays every item by a second? I want to use it for an Observable, and yes, I know that can be done in multiple other ways, I jsut want to accomplish it using a custom Scheduler.
There's some related tutorial here: http://codebetter.com/matthewpodwysocki/2010/05/12/introduction-to-the-reactive-extensions-for-javascript-custom-schedulers/ but it is quite outdated and the API looks very different now.
The current docs are not very usefuleither, but I guess I should be using Rx.Scheduler.prototype.schedulePeriodic, although I don't know what the action parameter should be.
To create a new scheduler from the base scheduler you should have a look at scheduler.js. Essentially you need to understand how to do 4 things and you will automatically get all the periodic, recursive, exception handling extensions for free.
The function signature of Scheduler is
function Scheduler(now, schedule, scheduleRelative, scheduleAbsolute){}
To break it down:
now - A function that represents the schedulers notion of time, at any point when this is called it should return what the scheduler thinks now is. The default is to simply return new Date()
schedule - A function called when the action should be executed as soon as possible This function has the signature
function scheduleNow(state, action) {}
where action will have the signature
function action(scheduler, state) {}
It is used to schedule immediate actions on the scheduler. Immediate will have different meanings depending on your scheduler, however, for most cases (immediateScheduler aside) you will want that to occur in the next tick, whatever that means to your scheduler. You can have a look at the defaultScheduler, which does a little work to figure out what the best method would be in the environment (setImmediate is the first choice). In your case, since immediate will really mean "one second from now", you could probably just route it to scheduleRelative with this.scheduleRelativeWithState(state, 1000, action)
scheduleRelative This is called when the action should occur sometime in the future relative to now:
function scheduleRelative(state, dueTime, action) {}
Again this will likely use setTimeout with dueTime as the time parameter.
scheduleAbsolute This is probably the easiest to implement, it has the same signature as scheduleRelative, however instead of taking a time relative to now it is taking an absolute time irrespective of now (usually a Date object), to convert it you really just need to subtract now from it and pass it into this.scheduleWithRelativeAndState (see I told you you'll get free stuff).
In all cases the 3 schedule methods return a Disposable, this is used for best effort cancellation of the action. In the case of setTimeout this would be clearing the timeout using the returned id.
To finally answer your question, if you wanted to delay everything by 1 second the best way will probably be to apply a shift in scheduleRelative adding 1 second/1000 milliseconds to each scheduled event.

What's the proper way to use coroutines for event handling?

I'm trying to figure out how to handle events using coroutines (in Lua). I see that a common way of doing it seems to be creating wrapper functions that yield the current coroutine and then resume it when the thing you're waiting for has occured. That seems like a nice solution, but what about these problems? :
How do you wait for multiple events at the same time, and branch depending on which one comes first? Or should the program be redesigned to avoid such situations?
How to cancel the waiting after a certain period? The event loop can have timeout parameters in its socket send/receive wrappers, but what about custom events?
How do you trigger the coroutine to change its state from outside? For example, I would want a function that when called, would cause the coroutine to jump to a different step, or start waiting for a different event.
EDIT:
Currently I have a system where I register a coroutine with an event, and the coroutine gets resumed with the event name and info as parameters every time the event occurs. With this system, 1 and 2 are not issues, and 3 can solved by having the coro expect a special event name that makes it jump to the different step, and resuming it with that name as an arg. Also custom objects can have methods to register event handlers the same way.
I just wonder if this is considered the right way to use coroutines for event handling. For example, if I have a read event and a timer event (as a timeout for the read), and the read event happens first, I have to manually cancel the timer. It just doesn't seem to fit the sequential nature or handling events with coroutines.
How do you wait for multiple events at the same time, and branch depending on which one comes first?
If you need to use coroutines for this, rather than just a Lua function that you register (for example, if you have a function that does stuff, waits for an event, then does more stuff), then this is pretty simple. coroutine.yield will return all of the values passed to coroutine.resume when the coroutine is resumed.
So just pass the event, and let the script decide for itself if that's the one it's waiting for or not. Indeed, you could build a simple function to do this:
function WaitForEvents(...)
local events = {...}
assert(#... ~= 0, "You must pass at least one parameter")
do
RegisterForAnyEvent(coroutine.running()) --Registers the coroutine with the system, so that it will be resumed when an event is fired.
local event = coroutine.yield()
for i, testEvt in ipairs(events) do
if(event == testEvt) then
return
end
end
until(false)
end
This function will continue to yield until one of the events it is given has been fired. The loop assumes that RegisterForAnyEvent is temporary, registering the function for just one event, so you need to re-register every time an event is fired.
How to cancel the waiting after a certain period?
Put a counter in the above loop, and leave after a certain period of time. I'll leave that as an exercise for the reader; it all depends on how your application measures time.
How do you trigger the coroutine to change its state from outside?
You cannot magic a Lua function into a different "state". You can only call functions and have them return results. So if you want to skip around within some process, you must write your Lua function system to be able to be skippable.
How you do that is up to you. You could have each set of non-waiting commands be a separate Lua function. Or you could just design your wait states to be able to skip ahead. Or whatever.

data structures for scheduling workflow?

I'm wondering what kind(s) of data structures / algorithms might help facilitate handling the following situation; I'm not sure if I need a single FIFO, or a priority queue, or multiple FIFOs.
I have N objects that must proceed through a predefined workflow. Each object must complete step 1, then step 2, then step 3, then step 4, etc. Each step is either done quickly or involves a "wait" that depends on something external to finish (like the completion of a file operation or whatever). Each object maintains its own state. If I had to define an interface for these objects, it would be something like this (written below in pseudo-Java, but this question is language-agnostic):
public interface TaskObject
{
public enum State { READY, WAITING, DONE };
// READY = ready to execute next step
// WAITING = awaiting some external condition
// DONE = finished all steps
public int getCurrentStep();
// returns # of current step
public int getEndStep();
// returns # of step which is the DONE case.
public State getState();
// checks state and returns it.
// multiple calls will always be identical,
// except WAITING which can transition to READY or DONE.
public State executeStep();
// if READY, executes next step and returns getState().
// otherwise, returns getState().
}
I need to write a single-threaded scheduler that calls executeStep() on the "next" object. My problem is, I'm not sure exactly what technique I should use to determine what the "next" object is. I want it to be fair (first-come, first-serve for objects not in the WAITING state).
My gut call is to have 3 FIFOs, READY, WAITING and DONE. In the beginning all objects are placed in the READY queue, and the scheduler repeats a loop where it takes the first object off the READY queue, calls executeStep(), and places it onto the queue that's appropriate the the result of executeStep(). Except that items in the WAITING queue need to be put into the READY or DONE queue when their state changes.... argh!
Any advice?
If this has to be single threaded you can use a single FIFO queue for the ready and waiting objects and use your thread to process each object as it comes out. If it's state changes to WAITING then simply stick it back into the queue and it will be reprocessed.
Something like (psuedocode):
var item = queue.getNextItem();
var state = item.executeStep ();
if (state == WAITING)
queue.AddItem (item);
else if (state == DONE)
// add to collection of done objects
Depending on the time executeStep takes to run you may need to introduce a delay (Sleep not for) to prevent a tight polling loop. Ideally you would have the objects publish state change events and do-away with the polling altogether.
This is the kind of timeslicing approach that was commonplace in hardware and comms software before multithreading was widespread.
You don't have any way for the task object to notify you when it changes from WAITING to READY except polling it, so the WAITING and READY queues could really just be one. You can just loop around it calling executeStep() on each one in turn. If as a return value from executeStep() you receive DONE, then you remove it from that queue and stick it on the DONE queue and forget about it.
If you wanted to give "more priority" towards READY objects and attempt to run through all possible READY objects before wasting any resources polling WAITING you can maintain 3 queues like you said and only process the WAITING queue when you have nothing in the READY queue.
I personally would spend some effort to eliminate the polling of the state, and instead define an interface that the object could use to notify your scheduler when a state changes.
You might want to study the design of an operating system scheduler. Check out the Linux and *BSD for example.
Some pointers for the Linux scheduler: Inside the Linux scheduler and Understanding the Linux Kernel
NOTE - this does not address your question of how to schedule, but I would use a separate state class that defines the states and transitions. The objects should not know what states they should go through. They can be informed of what "Step" they are at, etc.
there are some patterns for that as well.
You should read up a little on operating systems - specifically the scheduler. Your example is a scaled down set of that problem and if you copy the relevant parts it should work great for you.
You can then add priority, etc.
The simplest technique that satisfies the requirements in your question is to repeatedly iterate over all TaskObjects calling executeStep() on each one.
This requires only one construct to hold the TaskObjects, and it can be any iterable structure, e.g. an array.
Since a TaskObject can transition from WAITING to READY asynchronously, you have to poll every TaskObject that you don't know is DONE.
The performance gained from not polling the DONE TaskObjects may be negligible. It depends on the processing load of calling executeStep() on a DONE TaskObject, which should be small.
A simple round-robin polling assures that once a READY TaskObject has executed a step, it will not execute another step until all other TaskObjects have had a chance to execute.
One obvious additional requirement is detecting when all TaskObjects are in the DONE state so you can stop processing.
To avoid polling DONE TaskObjects you will need to either maintain a flag for each one, or chain the TaskObjects in two queues: READY/WAITING and DONE.
If you store the TaskObjects in an array, make it an array of records, with members DoneFlag and TaskObject.
If for some reason you are storing the TaskObjects in a queue, with available enqueue() and dequeue() methods, then the overhead of two queues instead of one may be small.
-Al.
Take a look a this link.
Boost state machines vs uml
Boost has state machines. Why reinvent?

Resources