CriticalSection

Included function to create and initialize a Critical Section Object.


OutputVar := CriticalSection()
Function Example: CriSec := CriticalSection()

Parameters

OutputVar

The name of the variable in which to store the pointer to the Critical Section Object.

General Remarks

A critical section object is useful in a multi-threaded environment (AutoHotkey.dll).
Critical Section Object provides synchronization similar to that provided by a mutex object but is used only by the threads of single process.
When Critical Section is owned by one thread and another thread tries to take ownership it will be halted and only continue once the thread released ownership.
To take ownership call EnterCriticalSection(CriSec), to release ownership call LeaveCriticalSection(CriSec). You can also call TryEnterCriticalSection(CriSec) if you don't want to lock current thread so it can still process messages, use Hotkeys, Timers...

Related

CriticalObject, AutoHotkey.dll

Examples

Example #1

[v2.0-a100+] Synchronizes 2 threads, running in parallel, to take turns in displaying message boxes.
CriSec := CriticalSection() ; Create and retrieve a pointer to a Critical Section Object.

threadScript := "
(
    CriSec := A_Args[1] ; The first command line argument is a pointer to a Critical Section Object.

    Loop 5
    {
        EnterCriticalSection(CriSec) ; Take ownership or wait until you can.
        MsgBox("Critical Section is now owned by AutoHotkey.dll")
        LeaveCriticalSection(CriSec) ; Release ownership.

        ; Allow some time for other threads to take ownership of the Critical Section.
        ; Failure to do so may leave some threads starved.
        Sleep(10)
    }
)"

; Create and start a thread using AutoHotkey.dll
; Command line arguments can only be passed as a string.
; To convert the pointer (an integer), concatenate with an empty string.
Thread := NewThread(threadScript, CriSec . "")

; Instructions executed by the main script thread.
Loop 5
{
    EnterCriticalSection(CriSec)
    MsgBox("Critical Section is now owned by AutoHotkey.exe")
    LeaveCriticalSection(CriSec)
    Sleep(10)
}

Example #2

[v2.0-a100+] Same as Example #1, except without any delays. The threads execute their instructions as fast as possible. Whichever thread manages to take ownership of a Critical Section first is likely to keep reacquiring ownership until the thread finishes. Meanwhile as a result, any other threads trying to take ownership by means of EnterCriticalSection will be left in a blocking wait state and starve.
CriSec := CriticalSection()

; Create and start a new thread.
Thread := NewThread("
(
    CriSec := A_Args[1]

    Loop 5
    {
        EnterCriticalSection(CriSec)
        MsgBox("Critical Section is now owned by the new thread.")
        LeaveCriticalSection(CriSec)

        ; The thread releases ownership and retakes it as soon as possible, leaving no time for other threads to run.
        ; Despite having called EnterCriticalSection, other threads will remain blocked, waiting.
    }
)", CriSec . "")

; It is very likely that by this point the new thread has already been created, started,
; has taken ownership of the Critical Section and the first of five message boxes is currently showing.

Loop 5
{
    ; On the first iteration of the loop, the main script thread tries to take ownership.
    ; It can't because the new thread already has ownership.
    ; The main thread will now block and wait until the new Thread has released its ownership.
    EnterCriticalSection(CriSec)

    MsgBox("Critical Section is now owned by main thread.")
    LeaveCriticalSection(CriSec)
}

; Very rarely will this exact same scenario play out the other way around.