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.
Related
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.
How comes Unity uses polling for all the Input events, is't it very inefficient to check each update loop if there is a new event? If I have 1 mio objects doing it each update cycle I would assume the constant polling would slow down the system significantly..
public void Update() {
if (Input.GetKeyUp(KeyCode.Escape)) {
// escape clicked
}
}
why is there nothing like this:
public void Start() {
Input.addKeyUpListener(KeyCode.Escape, delegate {
// escape clicked
});
}
Note that Unity is not polling the system every time you call one of those methods - it is instead polling once per frame and then caching the value, as evidenced by the ResetInputAxes function.
This is not the only place Unity does something seemingly insane, but which may be more efficient in the lower levels of code - keep in mind that Unity maintains a lot of customization to the runtime (particularly with garbage collection and construction) that works differently from standard C#.
Note also that callback logic, while great for handlers and generally long-lived objects such as singletons and systems, is not so great for scripts which are normally collected and created several times throughout the lifetime of the game. Since Unity only exposes the ability to make scripts with code, it thus makes more sense to poll, rather than use callbacks which would need attach, handle, and detach behaviours to prevent errors.
I am writing a Mac application (target 10.9+, using Xcode 6 Beta 3 on Mavericks) in Swift where I have a number of NSTextFields (labels) updating several times per second for extended periods of time by modifying their .stringvalue from a background thread. This seems to work well for a varying duration of time (anywhere between five minutes to 2 hours), but then the application window seems to stop updating. The text stops updating, hovering over the 'stoplight' controls on the upper-left does not show the symbols, and clicking in text boxes, etc., does not highlight the box/show the I-beam. However, my indeterminate progress wheel DOES continue to spin, and when I resize/minimize/zoom the window, or scroll in an NSScrollView box, the window updates during the movement.
My first guess was that some sort of window buffer was being used instead of a live image, so I tried to force an update using window.update(), window.flushWindowIfNeeded(), and window.flushWindow(), all to no avail. Can someone please tell me what's going on, why my window stops updating, and how to fix this problem?
Your problem is right here:
I have a number of NSTextFields (labels) updating several times per
second for extended periods of time by modifying their .stringvalue
from a background thread.
In OSX (and iOS), UI updates must occur in the main thread/queue. Doing otherwise is undefined behavior; sometimes it'll work, sometimes it won't, sometimes it'll just crash.
A quick fix to your issue would be to simply use Grand Central Dispatch (GCD) to dispatch those updates to the main queue with dispatch_async like:
dispatch_async(dispatch_get_main_queue(), ^{
textField.stringValue = "..."
});
The simplified version of what that does is it puts the block/closure (the code between {}) in a queue that the default run loop (which runs on the main thread/queue) checks on each pass through its loop. When the run loop sees a new block in the queue, it pops it off and executes it. Also, since that's using dispatch_async (as opposed to dispatch_sync), the code that did the dispatch won't block; dispatch_async will queue up the block and return right away.
Note: If you haven't read about GCD, I highly recommend taking a look at this link and the reference link above (this is also a good one on general concurrency in OSX/iOS that touches on GCD).
Using a timer to relieve strain on your UI
Edit: Several times a second really isn't that much, so this section is probably overkill. However, if you get over 30-60 times a second, then it will become relevant.
You don't want to run in to a situation where you're queueing up a backlog of UI updates faster than they can be processed. In that case it would make more sense to update your NSTextField with a timer.
The basic idea would be to store the value that you want displayed in your NSTextField in some intermediary variable somewhere. Then, start a timer that fires a function on the main thread/queue tenth of a second or so. In that function, update your NSTextField with the value stored in that intermediary variable. Since the timer will already be running on the main thread/queue, you'll already be in the right place to do your UI update.
I'd use NSTimer to setup the timer. It would look something like this:
var timer: NSTimer?
func startUIUpdateTimer() {
// NOTE: For our purposes, the timer must run on the main queue, so use GCD to make sure.
// This can still be called from the main queue without a problem since we're using dispatch_async.
dispatch_async(dispatch_get_main_queue()) {
// Start a time that calls self.updateUI() once every tenth of a second
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target:self, selector:"updateUI", userInfo: nil, repeats: true)
}
}
func updateUI() {
// Update the NSTextField(s)
textField.stringValue = variableYouStoredTheValueIn
}
Note: as #adv12 pointed out, you should think about data synchronization when you're accessing the same data from multiple threads.
Note: you can also use GCD for timers using dispatch sources, but NSTimer is easier to work with (see here if interested).
Using a timer like that should keep your UI very responsive; no need to worry about "leaving the main thread as empty as possible". If, for some reason, you start losing some responsiveness, simply change the timer so that it doesn't update as often.
Update: Data Synchronization
As #adv12 pointed out, you should synchronize your data access if you're updating data on a background thread and then using it to update the UI in the main thread. You can actually use GCD to do this rather easily by creating a serial queue and making sure you only read/write your data in blocks dispatched to that queue. Since serial queues only execute one block at a time, in the order the blocks are received, it guarantees that only one block of code will be accessing your data at the same time.
Setup your serial queue:
let dataAccessQueue = dispatch_queue_create("dataAccessQueue", DISPATCH_QUEUE_SERIAL)
Surround your reads and write with:
dispatch_sync(dataAccessQueue) {
// do reads and/or writes here
}
I am fixing a MFC applivation written in C++. It is a GUI and it communicates with an external module connected to the PC via USB.
I want to avoid using a separate thread. Is there a way I can add things to the mainloop so that it runs continously rather than being event based?
I want the mainloop to make a call to a function runCommStack() in every loop.
Some possible approaches:
You can use CWnd::SetTimer to set a timer.
You can override CWinApp::OnIdle (called by CWinApp::Run).
You can override CWinApp:Run, copying and modifying the original MFC's CWinApp:Run. This definitely is not the easiest solution.
You can create a background thread.
It depends on the requirements of runCommStack(). Is this function running long times? Then you probably won't want to run it in the GUI thread. Does runCommStack need to get called every n milliseconds? Then it might also be better to run it in it's own thread. In other cases you can just use the timer or OnIdle approach.
Regarding solution 1: as Tim pointed out WM_TIMER messages are low priority messages and will not be passed to the application while other higher-priority messages are in the message queue. See also Determine priority of a window message.
With solution 2 you should remind that OnIdle will only be called if no window message is available. So this is quite the same as solution 1 (in fact a little worse).
Also keep in mind that solutions 2 and 3 might result in your runCommStack not getting called if a dialog's DoModal() is called or if a message box is displayed. This is because during MessageBox() the control is not returned to CWinApp::Run().
I'ld implement solution 1 or 4.
When there are no messages (like keys, mouse, repaint) arriving the main loop suspends the program, waiting for the next message. So the idea of adding a call to the main loop will give you very erratic operation. For example, minimizing your window will stop all the USB communication.
Using SetTimer and calling your runCommStack function in a WM_TIMER handler will probably be much more satisfactory.
You can use idle processing with CWinApp::OnIdle; this will work if reading your USB device takes only a short amount of time, otherwise the user interface will be blocked during long reads.
But using a separate thread is definitely a better method.
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.