| 1816 | |
| 1817 | |
| 1818 | void InitNewThread(int aPriority, bool aSkipUninterruptible, bool aIncrementThreadCountAndUpdateTrayIcon |
| 1819 | , bool aIsCritical) |
| 1820 | // The value of aIsCritical is ignored when aSkipUninterruptible==true. |
| 1821 | // To reduce the expectation that a newly launched hotkey or timed subroutine will |
| 1822 | // be immediately interrupted by a timed subroutine or hotkey, interruptions are |
| 1823 | // forbidden for a short time (user-configurable). If the subroutine is a quick one -- |
| 1824 | // finishing prior to when ExecUntil() or the Timer would have set g_AllowInterruption to be |
| 1825 | // true -- we will set it to be true afterward so that it gets done as quickly as possible. |
| 1826 | // The following rules of precedence apply: |
| 1827 | // If either UninterruptibleTime or UninterruptedLineCountMax is zero, newly launched subroutines |
| 1828 | // are always interruptible. Otherwise: If both are negative, newly launched subroutines are |
| 1829 | // never interruptible. If only one is negative, newly launched subroutines cannot be interrupted |
| 1830 | // due to that component, only the other one (which is now known to be positive otherwise the |
| 1831 | // first rule of precedence would have applied). |
| 1832 | { |
| 1833 | if (aIncrementThreadCountAndUpdateTrayIcon) |
| 1834 | { |
| 1835 | ++g_nThreads; // It is the caller's responsibility to avoid calling us if the thread count is too high. |
| 1836 | // Once g_array[0] is used by AutoExec section, it's never used by any other thread because: |
| 1837 | // 1) the auto-execute thread might never finish, in which case it needs to keep consulting the values in g_array[0]. |
| 1838 | // 2) it's used to retain the default settings for each newly launched thread. |
| 1839 | ++g; |
| 1840 | } |
| 1841 | // Copy only settings, not state, from the auto-execute thread. |
| 1842 | memcpy(static_cast<ScriptThreadSettings*>(g), static_cast<ScriptThreadSettings*>(&g_default), sizeof(ScriptThreadSettings)); |
| 1843 | |
| 1844 | global_struct &g = *::g; // Must be done AFTER the ++g above. Reduces code size and may improve performance. |
| 1845 | global_clear_state(g); |
| 1846 | g.Priority = aPriority; |
| 1847 | |
| 1848 | // If the current quasi-thread is paused, the thread we're about to launch will not be, so the tray icon |
| 1849 | // needs to be checked unless the caller said it wasn't needed. In any case, if the tray icon is already |
| 1850 | // in the right state (which it usually, since paused threads are rare), UpdateTrayIcon() is a very fast call. |
| 1851 | if (aIncrementThreadCountAndUpdateTrayIcon) |
| 1852 | g_script.UpdateTrayIcon(); // Must be done ONLY AFTER updating "g" (e.g, ++g) and/or g->IsPaused. |
| 1853 | |
| 1854 | if (aSkipUninterruptible) |
| 1855 | return; |
| 1856 | |
| 1857 | if (!g.ThreadIsCritical) |
| 1858 | g.ThreadIsCritical = aIsCritical; |
| 1859 | |
| 1860 | if (g_script.mUninterruptibleTime && g_script.mUninterruptedLineCountMax // Both components must be non-zero to start off uninterruptible. |
| 1861 | || g.ThreadIsCritical) // v1.0.38.04. |
| 1862 | { |
| 1863 | g.AllowThreadToBeInterrupted = false; |
| 1864 | if (!g.ThreadIsCritical) |
| 1865 | { |
| 1866 | if (g_script.mUninterruptibleTime < 0) // A setting of -1 (or any negative) means the thread's uninterruptibility never times out. |
| 1867 | g.UninterruptibleDuration = -1; // "Lock in" the above because for backward compatibility, above is not supposed to affect threads after they're created. Override the default value contained in g_default. |
| 1868 | //g.ThreadStartTime doesn't need to be set when g.UninterruptibleDuration < 0. |
| 1869 | else // It's now known to be >0 (due to various checks above). |
| 1870 | { |
| 1871 | // For backward compatibility, "lock in" the time this thread will become interruptible |
| 1872 | // because that's how previous versions behaved (i.e. 'Thread "Interrupt", NewTimeout' |
| 1873 | // doesn't affect the current thread, only the thread creation behavior in the future). |
| 1874 | // This also makes it more predictable, since AllowThreadToBeInterrupted is only changed |
| 1875 | // when IsInterruptible() is called, which might not happen in between changes to the setting. |
no test coverage detected