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.
Related
So I a attempting to shut down a long running function if something takes too long, maybe is just a solution to treating the symptoms rather than cause, but in any case for my situation it didn't really worked out.
I did it like this:
func foo(abort <- chan struct{}) {
for {
select{
case <-abort:
return
default:
///long running code
}
}
}
And in separate function I have which after some time closes the passed chain, which it does, if I cut the body returns the function. However if there is some long running code, it does not affect the outcome it simply continues the work as if nothing has happened.
I am pretty new to GO, but it feels like it should work, but it does not. Is there anything I am missing. After all routers frameworks have timeout function, after which whatever is running is terminated. So maybe this is just out of curiosity, but I would really want how to od it.
your code only checks whether the channel was closed once per iteration, before executing the long running code. There's no opportunity to check the abort chan after the long running code starts, so it will run to completion.
You need to occasionally check whether to exit early in the body of the long running code, and this is more idiomatically accomplished using context.Context and WithTimeout for example: https://pkg.go.dev/context#example-WithTimeout
In your "long running code" you have to periodically check that abort channel.
The usual approach to implement that "periodically" is to split the code into chunks each of which completes in a reasonably short time frame (given that the system the process runs on is not overloaded).
After executing each such chunk you check whether the termination condition holds and then terminate execution if it is.
The idiomatic approach to perform such a check is "select with default":
select {
case <-channel:
// terminate processing
default:
}
Here, the default no-op branch is immediately taken if channel is not ready to be received from (or closed).
Some alogrithms make such chunking easier because they employ a loop where each iteration takes roughly the same time to execute.
If your algorithm is not like this, you'd have to chunk it manually; in this case, it's best to create a separate function (or a method) for each chunk.
Further points.
Consider using contexts: they provide a useful framework to solve the style of problems like the one you're solving.
What's better, the fact they can "inherit" one another allow one to easily implement two neat things:
You can combine various ways to cancel contexts: say, it's possible to create a context which is cancelled either when some timeout passes or explicitly by some other code.
They make it possible to create "cancellation trees" — when cancelling the root context propagates this signal to all the inheriting contexts — making them cancel what other goroutines are doing.
Sometimes, when people say "long-running code" they do not mean code actually crunching numbers on a CPU all that time, but rather the code which performs requests to slow entities — such as databases, HTTP servers etc, — in which case the code is not actually running but sleeping on the I/O to deliver some data to be processed.
If this is your case, note that all well-written Go packages (of course, this includes all the packages of the Go standard library which deal with networked services) accept contexts in those functions of their APIs which actually make calls to such slow entities, and this means that if you make your function to accept a context, you can (actually should) pass this context down the stack of calls where applicable — so that all the code you call can be cancelled in the same way as yours.
Further reading:
https://go.dev/blog/pipelines
https://blog.golang.org/advanced-go-concurrency-patterns
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.
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.
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.
I was wondering if there is a way how to perform actions in a function after it returning a value.
i.e there is a method which returns a string. Now after the string is returned I want the method to perform another action like checking whether a condition is met so it can send out a notification or something else. Is that somehow possible?
The thing is that I am using a framework called core plot to add some plots to my application. Unfortunately this framework does not have a didFinishAddingPlot method. So I have to manually program a mechanism which notifies me whenever the plot finished plotting. When the addPlot method is called another method is called which goes through an array of values and returns a value for a specific index to plot. My idea was to put in a "if (condition)" block to check if the index is equal to the count of my values array so I know that it is now fetching the last value. However it first needs to return the value before sending a message that it finished plotting. Otherwise the last value won't get passed.
As soon as a function hits a return statement the function stops running. You would need to perform whatever other action you want to do before you return.
So, you want to return a value from your function or method, which by definition returns control (as well as your answer) to the call site. On the face of it, it's not possible; you've returned control, so you're done.
But you could spawn a new Thread during your method execution, to (for example) perform some cleanup tasks later on.
Since you tagged the question as Cocoa, check out Apple's Threaded Programming Guide, which will teach you about NSThread, POSIX threads, and more.