How does NSUndoManager.groupsByEvent determine the current run loop pass? - cocoa

I'd like to understand/replicate the "group by run loop pass/cycle" feature of NSUndoManger:
NSUndoManager can group multiple calls to registerUndo() into a single "undo" operation when invoked multiple times on the same run loop cycle. This is determined by NSUndoManager.groupsByEvent, which is set to true by default.
So something like this:
// User clicks button... (causes a new run loop event)
undoManager.registerUndo(...) // #1
undoManager.registerUndo(...) // #2
...results in one undo group and clicking Edit → Undo reverts both changes at once.
Somehow NSUndoManager can figure out if two calls to registerUndo() are on the same run loop cycle. How does this work?
My use case:
I have code that sends property change notifications after the user interacts with the UI (e.g. clicks a button). There can be one or more events as the result of a user action. I'd like to group those and update the UI only once at the end of the current run loop.

NSUndoManager normally creates undo groups automatically during the run loop. The first time it is asked to record an undo operation in the run loop, it creates a new group. Then, at the end of the loop, it closes the group.
source: Undo Operations and Groups
NSUndoManager is part of the same framework as NSRunLoop so maybe NSRunLoop signals NSUndoManager to close a group. You don't know and you shouldn't want to know.

Related

Labview events - do a taks in parallel to a running loop

I'm trying to do something very simple:
OK button sums a+b and shows in c
Loop switch button control a infinity loop
Option 1 - Loop outside event
Option 2 - Loop inside event
I just want to be able to keep the loop running and the OK button working at the same time, how can achieve that simple task in Labview "way of life".
Results:
Op 1 - Outside event: One loop occurs after OK click, if loop is running, OK works only at first time
Op 2 - Inside event: Button OK does not work
You can't. You'll need two seperate while loops, one with the count functionality, but don't use the 'loop' variable as the stop condition, make the loop variable control a the count condition.
In the other while loop you'll have your event code.
The only thing you'll have to worry about is stopping the first while loop from the event code.
Here is how you can do it with a Master/Slave configuration. All the user events are handled in the master, the counting is handled in the slave. The loop can be restarted and the stop works for both loops.
To Stop the code you use a different event, in the case the loop conditional is false you don't do anything in the slave loop. Not shown here, but the loop conditional also has it's own event structure to reset the counter if needed.
This master/slave structure is extendable to as many loops as you want.
I see two options:
Similiar to option 2 but do the "loop math" not inside the "Loop Value Canged"-Case but inside the "Timeout"-Case. Then you don't need the while loop, use a if-case (loop = true) instead.
Use two while loops. Inside each of them put a event case. One to handle the "C=A+B"-Event and one for the "Loop Value Changed".
I think the design pattern you are looking for is the Producer/Consumer pattern. This allows you to run parallel loops and if need be share data between them.
A quick google on the term combined with labview will give you enough examples.

Exiting while loop in winapi

My problem is this. I have check box which when checked starts while loop. At that while loop there is createprocess function. While checkbox is marked as checked, function repeats it self again and again. Problem is that while loop is running I can't push check box again to change it's values and stop the process. I think that here is needed something like two parallel process working at the same time, but I am not sure. My question would be:
* Is there a way to access my controls while while loop is running?
* Or maybe I should use something else instead of while process?
Suggestions or some kind of example would be appreciated.
The problem is that you are running the loop in the same thread that owns the CheckBox, and that loop is blocking the thread from processing new messages. That is why you are not able to uncheck the CheckBox (or do anything else with your UI).
You need to either:
move the loop to a worker thread. When the CheckBox becomes checked, start the thread. When the CheckBox becomes unchecked, stop the thread. Do not block the dialog's thread at all. This is the best option.
break apart your loop and make it event-driven. When the CheckBox becomes checked, post a custom window message to yourself. When you receive that message, if the CheckBox is still checked then perform one iteration of your loop and then post the message back to yourself again. Repeat until the CheckBox becomes unchecked. This option does not require any threads, but your UI will still be blocked during each individual iteration (but you will be able to uncheck the CheckBox in between iterations), unless...
Keep your existing loop code, but add an inner loop that calls MsgWaitForMultipleObjects() after CreateProcess() succeeds until the spawned process has exited. While waiting, whenever MsgWaitForMultipleObjects() tells you that a new message is waiting, you can pump the message queue and dispatch any messages that are retrieved. This is the least desirable option, but it requires the least amount of changes to existing code.

Set conditional breakpoint for certain thread only in Xcode/LLDB

I am using some GCD code which dispatches a bunch of similar async blocks. I would like to debug one of these blocks by stepping through it so I've set a breakpoint somewhere near the top of the block, but the debugger hits the breakpoint every time a new block is submitted and so I never manage to step through the block, I just get swapped around different threads on the same line.
My question is how do I set a breakpoint so that its conditional upon a certain thread? i.e. it should only trigger if executed on thread 4?
EDIT
I should add that my block's code is very time intensive, so the scheduler swaps onto another thread before the next line inside the block can be executed, and another freshly scheduled GCD block gets its turn, triggering the same breakpoint.
I don't think this is exposed through the Xcode Breakpoints UI but in lldb you can modify a breakpoint so it only fires when a (1) thread name matches, (2) dispatch queue name matches, (3) thread ID matches, or (4) thread index number matches. You can specify these criteria when you create the breakpoint (breakpoint set) or you can add these criteria to an existing breakpoint with breakpoint modify. See help breakpoint modify in the Debugger console window for a list of the allowed arguments.
To debug in GDC code, you can use $gdb invoke-block.
To have better idea on same..
A Guide to Blocks & Grand Central Dispatch (and the Cocoa API's making use of them)
Debugging with GDB
And also How is dispatch_debug supposed to be used? is already there to guide.

Is it possible for windows event and Windows timer event to execute re-entrantly?

I have "Update" method which is executes in event handler (button click), and in Windows forms Timer callback. Is it possible for two "Update" (re-entrancy) to be executing at the same time? That is, while the timer callback is executing (calling Update method), the user clicks the button, and the click handler executes Update.
Or, is it the case that, the two Update methods are completely serialized since both execute in the UI thread.
Or, is it the case that Update could put the thread in some kind of "Alertable Wait" (I am not very clear on this), and the Click Handler could execute an as APC?
You can see, I am totally mixed up on this...
Any explanations will be highly appreciated!
It depends on a sort of the timer used: one that executes on the main UI thread (System.Windows.Forms.Timer - re-entrancy is impossible) or one executed in its own thread (System.Threading.Timer - re-entrancy is possible).

What is a browser event loop?

I have been doing some web application programming using GWT and have been confused by the term "browser event loop".
I have encountered situations where I need to execute deferred commands and "do something" after the browser event loop completes.
I would like to know as to what exactly it is and what happens during the event loop process and in which order?
A browser event loop is a thread started by the browser that is constantly scanning for and running different events, just like it sounds. As events occur they are put in the event queue and run in turn by the one event thread. Your javascript should not create its own loops waiting for it to complete or anything like that...it will block that one continuous event loop thread. Instead you would use something like setTimeout or setInterval and check for whatever conditions you are waiting for so the browser can do work while it 'waits'.
GWT is nice in that it can co-opt this process somewhat using the scheduler -- in your case where you want to run something after the event loop 'completes' you will probably want to use scheduleFinally or scheduleDeferred. It will inject a handler for a piece of code into the event queue so that it will run after all other code in the current execution context (current execution context == where ever you are in the current JavaScript object hierarchy with the window as the root object) is run but before the next event that is placed in the queue.

Resources