Page 2 of 2

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

Posted: 04 Aug 2018, 15:47
by SAbboushi
WoW! Thanks for explaining and the examples. I just could not see that from the documentation and my testing. Is there some advantage to it working this way that I just can't see, or is the behavior a byproduct of some limitation or something else?

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

Posted: 04 Aug 2018, 23:41
by lexikos
(I didn't see the second page before posting.)

Note the documentation for Critical:
Critical wrote:Prevents the current thread from being interrupted by other threads, or enables it to be interrupted.
There is nothing on that page about changing default settings, because Critical does not change any thread-default settings. This is also true for every other command which changes the current thread's settings.

The settings of the auto-execute section become the default settings only under the conditions described in the documentation that I previously quoted: when the auto-execute section finishes, or after 100ms if it is still running.

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

Posted: 05 Aug 2018, 01:12
by lexikos
I'm not sure whether there is any advantage to it working this way, but I think it is a byproduct of the design and backward-compatibility.

Thread-specific settings are stored in structs of type global_struct. g_default contains the default settings, *g_array points to an array of structs used by running threads (allocated based on #MaxThreads), and *g points to the current thread's settings. When a new thread is launched, we simply ++g and initialize it by copying from g_default to *g. This is avoids the need to allocate a new struct each time a thread is launched and delete it upon thread completion.

While the auto-execute section is running, g_array[0] contains its settings; but after it completes, g_array[0] will be reused by another thread. Instead, g_array[0] could be permanently reserved for both the auto-execute section's settings and the thread-default settings, thus making Critical (etc.) automatically and immediately affect default settings if called from the auto-execute section.

However, global_struct contains everything specific to the thread, including some transient variables that should not be copied across to each new thread, such as for the A_Loop variables, A_ThisFunc, A_ThisLabel, the last found window and current pause status. These transient variables are reinitialized immediately after the settings are copied into g_default; it never needs to be done for new threads, because it is covered by simply copying from g_default into *g.

Perhaps the cost of initializing these variables for each new thread is negligible, or can be minimized by separating them from the part of the struct that needs to be copied (in order to memcpy one part and memset the other). There might still be a marginal cost, but it might be worth it if we want the defaults to take effect immediately.

g_default is also used by the hook thread to evaluate #IfWin criteria. Currently it is possible for the default settings to change either once or twice: once after the auto-execute section has been running for 100ms, and once when it completes. It is theoretically possible for this change to occur while the hook thread is evaluating window criteria, but I think the probability is low. If g_default referred directly to the settings in use by the auto-execute section, it would be more likely for a change in settings to occur while the hook is using them (i.e. because the auto-execute section can keep running indefinitely).

Re: AHK V2: Why does auto-execute thread get interrupted by timers...

Posted: 05 Aug 2018, 01:22
by jeeswg
- Thanks for the interesting info.
- I had wondered if the default settings could be set via directives. (Which would be less hacky than commands having a special change-the-defaults role only within the auto-execute section.)
- E.g. something like '#Set A_DetectHiddenWindows := 1'. Or perhaps '#SetDefault'. It would only set A_ variables.
- But I really don't mind what the specifics of any solution might be.