github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/sys/ewindows/wait.go (about)

     1  //go:build windows
     2  // +build windows
     3  
     4  package ewindows
     5  
     6  import (
     7  	"errors"
     8  	"unsafe"
     9  
    10  	"golang.org/x/sys/windows"
    11  )
    12  
    13  const (
    14  	INFINITE = 0xFFFFFFFF
    15  )
    16  
    17  const (
    18  	WAIT_OBJECT_0    = 0
    19  	WAIT_ABANDONED_0 = 0x00000080
    20  	WAIT_TIMEOUT     = 0x00000102
    21  	WAIT_FAILED      = 0xFFFFFFFF
    22  )
    23  
    24  var (
    25  	waitForMultipleObjects = kernel32.NewProc("WaitForMultipleObjects")
    26  	errTimeout             = errors.New("WaitForMultipleObjects timeout")
    27  )
    28  
    29  // WaitForMultipleObjects blocks until any of the objects is triggered or
    30  // timeout.
    31  //
    32  // DWORD WINAPI WaitForMultipleObjects(
    33  //   _In_       DWORD  nCount,
    34  //   _In_ const HANDLE *lpHandles,
    35  //   _In_       BOOL   bWaitAll,
    36  //   _In_       DWORD  dwMilliseconds
    37  // );
    38  func WaitForMultipleObjects(handles []windows.Handle, waitAll bool,
    39  	timeout uint32) (trigger int, abandoned bool, err error) {
    40  
    41  	count := uintptr(len(handles))
    42  	ret, _, err := waitForMultipleObjects.Call(count,
    43  		uintptr(unsafe.Pointer(&handles[0])), boolToUintptr(waitAll), uintptr(timeout))
    44  	switch {
    45  	case WAIT_OBJECT_0 <= ret && ret < WAIT_OBJECT_0+count:
    46  		return int(ret - WAIT_OBJECT_0), false, nil
    47  	case WAIT_ABANDONED_0 <= ret && ret < WAIT_ABANDONED_0+count:
    48  		return int(ret - WAIT_ABANDONED_0), true, nil
    49  	case ret == WAIT_TIMEOUT:
    50  		return -1, false, errTimeout
    51  	default:
    52  		return -1, false, err
    53  	}
    54  }
    55  
    56  func boolToUintptr(b bool) uintptr {
    57  	if b {
    58  		return 1
    59  	}
    60  	return 0
    61  }