Can a UIJob defer to a parallel UIJob at regular intervals? - eclipse

I have an eclipse RCP which performs long-running jobs. The job involves graphics processing. While the job is running, a large animated eggtimer is displayed. The graphics job and the animated eggtimer run in separate UIJobs.
During the graphics processing, one method is called which appears to block the animation job. This method contains nested for-loops which analyse the pixels of an image.
I tried adding a Thread.sleep(0) inside the for-loop but this had no effect.
What can I add to the for-loop to force it to defer to other jobs at regular intervals?
(I assume that there must be something as this for-loop seems to be the only point in the graphics processing - file access, image creation, image manipulation etc - where the animation job is blocked)

This isn't very clear but any long running code must not be in the UI thread (UIJob runs in the UI thread).
You must put the long running code in an ordinary Job (or some other background thread). That Job can use Display.asyncExec to run UI code in the UI thread.
There isn't any way to 'defer' things in a for loop. Using Thread.sleep in the UI thread will block the UI completely.

Related

Swift UIAnimation blocked by for loop

I have a UIAnimation that pulls out a message log, but I need to populate the message log using a for loop as well. I have the animation taking place before the for loop begins, however, the animation doesn't actually begin until after the for loop finishes executing (even though the loop is located after the UIAnimation).
I've tried putting the contents of the for loop within an autoreleasepool (did not work)
I've tried running the for loop on a background thread, however, most of the code within the loop needs to be executed on the main thread, and I haven't had success with that approach.
The for loop is very large, and most of the code is irrelevant to the question, so you can set this up using any UIAnimation, and any relatively time consuming for loop...
for example:
let someView = UIView(frame:CGRect(x:self.view.frame.size.width,y:0,width:self.view.frame.size.width,height:self.view.frame.size.height))
someView.backgroundColor = .red
UIView.animate(withDuration:0.3,animations:{
self.someView.frame.origin.x = 0
})
//You can wrap this with something like:
//DispatchQueue.global(qos: .background).async(execute: {
//But this^ doesn't work on the majority of the code within the loop
for i in 0...1000{
print("hopefully this loop takes a few seconds to finish executing")
print("mainthread tasks being executed")
print("populating UITable in my particular case, and rendering Images/Video/text")
}
The closest that I can get to making it better is to add a "completion" to my UIAnimation, (which will allow the UIView to pull out completely/immediately) but then there is still a second of wait time before the first messages appear...
Also, I am populating a UITableView within the for loop. Not sure if that has any extra relevance to the primary issue I'm having or not...
I'm pretty familiar with DispatchQueue and the differences between async/sync. If you have any potential solutions, or ideas, please let me know.
The animation does not happen immediately, when you call UIView.animate. In stead all the animations are collected and run at some appropriate time. This is why the animation only starts after your for loop is done.
So the way to fix it is to get the animation to run before your for loop runs. Now, accepting what you say, that the for must run on the main thread, you have a number of options. You could put the for loop inside a DispatchQueue.main.async{} or somehow throttle it down so that the animation gets going first. Your idea of using the completion is a good one but you mention some practical issues you picked up with it. So either solve those practical issues, try to run the for inside a DispatchQueue.main.async{} or even, based on practical considerations, start the for loop on the main thread but somewhere else, say in something like didLayoutSubviews (fixed) or as now together with the animation but after a few millis delay to allow the animation to get going.
It's an interesting question. This made me think!
Yes, you mentioned that you understand differences between async/sync but didn't mention if you tried animating in the main thread.
Did you try putting the
UIView.animate(...) in DispatchQueue.main.async{}?

swift stop loop and continue it with a button

is it possible to stop an for in loop and continue it and the stopped position with a button.
i mean something like this:
for x in 0..<5 {
if x == 3 {
// show a button
// this button have to be pressed
// which do some tasks
// when all tasks are finished >
// continue this loop at the stopped point
}
}
is this possible? if yes, how?
Short answer: use a semaphore
Longer answer:
Your situation is an example of the more general case of how to pause some computation, saving its current state (local variables, call stack, etc.), and later to resume it from the same point, with all state restored.
Some languages/systems provide coroutines to support this, others the more esoteric call with current continuation, neither are available to you (currently) Swift...
What you do have is Grand Central Dispatch (GCD), provided in Swift through Dispatch, which provides support for executing concurrent asynchronous tasks and synchronisation between them. Other concurrency mechanisms such as pthread are also available, but GCD tends to be recommended.
Using GCD an outline of a solution is:
Execute you loop as an asynchronous concurrent task. It must not be executing on the main thread or you will deadlock...
When you wish to pause:
Create a semaphore
Start another async task to display the button, run the other jobs etc. This new task must signal the semaphore when it is finished. The new task may call the main thread to perform UI operations.
Your loop task waits on the semaphore, this will block the loop task until the button task signals it.
This may sound complicated but with Swift block syntax and Dispatch it is quite simple. However you do need to read up on GCD first!
Alternatively you can ask whether you can restructure your solution into multiple parts so saving/restoring the current state is not required. You might find designs such as continuation passing style useful, which again is quite easy using Swift's blocks.
HTH

How to force a redraw within a loop?

I am using processing within Scala (although I don't think this is really relevant to my question).
I am constructing a searchtree within a loop that runs until a valid path has been found. That can take a few seconds and I would like to draw the graphical representation of the tree while it is being build so the user can see something is happening.
I tried to solve this by calling redraw() within the loop but that doesn't work. I guess because redraw() doesn't force a redraw but only sets a flag that a redraw should be done.
So is there a way I can force a redraw or how would you normally solve such a problem?
#George Profenza's comment is correct. Processing tasks all happen on the Animation Thread. Any tasks you execute within draw() will lock that thread until they complete. If you want to update the screen while a task is executing, either run the task on a separate thread (beyond the scope of the Processing API, you have to use Java for this), or break the task up into segments and let the draw() method return at the end of each segment so PApplet can render to the screen.

What's the strategy in game engines to perform secure state changes?

I created a run loop in OpenGL ES which is called by a CADisplayLink at 60fps. AFAIK CADisplayLink calls it's target on a background thread.
I have about 100 state variables which are used by the run loop.
The problem: From the main thread, I want to change state variables which are used in the run loop to draw something. A frame must be drawn only after all state variables have been set to their target values.
I am afraid that at some point when I change a state variable, and I'm not done yet changing them all (in one big method in same run loop iteration on main thread), for example position of a geometric shape, there is multi-threading related crash or problem where the CADisplayLink will kick in right in the middle of my method that updates the state variables, and then draw garbage or crash.
Obviously when I just use synchronized or atomic properties it won't help because it is still not transactional. I think I need transactions.
My naive approach is this:
Instance variable read by run loop:
BOOL updatingState;
The run loop method will skip drawing if updatingState reads YES.
Then before starting to change state I set it to YES. And when everything is changed, I set it back to NO.
Now of course, problem: What if -while I am changing this- the run loop method is reading the values?
How do game engines deal with this problem? What kind of locking mechanisms do they have so the changing of the state variables can be finished before the next frame is going to be drawn?
You might find a read-copy-update strategy useful. One possible implementation is that each object actually contains two copies of the rendering parameters and an atomic flag is used to tell the rendering thread which to use. You will need to use a read memory barrier in the renderer to make sure that the flag is read before reading any of the parameters and a write memory barrier in the updater thread to make sure that all of the parameter updates are written before flipping the flag.
The usual way how this is done is that all state updates happen at each run loop iteration, before the drawing is done. That is, the run loop looks schematically like this:
updateState();
draw();
With this model, the drawing only happens after the a consistent state has been reached.
For this to work, you need to have a model where events such as key presses are polled for on each updateState() instead of happening asychronously, and a time measurement on each iteration to tell you how much time elapsed since the last frame.
I can't help you how this is realized in the concrete case of iOS programming, though, as I don't know anything about that. But I hope I could point you in the right direction.
I think this is a common problem in concurrency, so there are several ways to do it:
Use an immutable state class to hold the state variables.
Use a locking mechanism (if an immutable class cannot be used) to protect the state variables.
Have multiple states which you can modify, but only one is "active." This will allow you to reuse states and it will reduce copying and memory allocation.
Additionally, consider this situation:
Thread 1. Start drawing something.
Thread 1. Read 1/2 of the state 01 parameters (first state).
Thread 2. Swap out state 01 with state 02 (second state).
Thread 1. Reads the other 1/2 of state 02, but it's different from the state 01 parameters.
So the best option is not to allow the update of the state during the drawing, so option 3 might be the best way to do it because you would simply pick up the latest state and draw it. Let's say you have two states: drawingState and nonDrawingState. In your draw function you will always use the drawingState to draw while other threads modify the nonDrawingState. Once you're done drawing, then you can swap the states and continue drawing with the latest state modifications.

How a runloop actually works

Earlier this month I asked this question 'What is a runloop?' After reading the answers and did some tries I got it to work, but still I do not understand it completely. If a runloop is just an loop that is associated with an thread and it don't spawn another thread behind the scenes how can any of the other code in my thread(mainthread to keep it simple) execute without getting "blocked"/not run because it somewhere make an infinite loop?
That was question number one. Then over to my second.
If I got something right about this after having worked with this, but not completely understood it a runloop is a loop where you attach 'flags' that notify the runloop that when it comes to the point where the flag is, it "stops" and execute whatever handler that is attached at that point? Then afterwards it keep running to the next in que.
So in this case no events is placed in que in connections, but when it comes to events it take whatever action associated with tap 1 and execute it before it runs to connections again and so on. Or am I as far as I can be from understanding the concept?
"Sort of."
Have you read this particular documentation?
It goes into considerable depth -- quite thorough depth -- into the architecture and operation of run loops.
A run loop will get blocked if it dispatches a method that takes too long or that loops forever.
That's the reason why an iPhone app will want to do everything which won't fit into 1 "tick" of the UI run loop (say at some animation frame rate or UI response rate), and with room to spare for any other event handlers that need to be done in that same "tick", either broken up asynchronously, on dispatched to another thread for execution.
Otherwise stuff will get blocked until control is returned to the run loop.