github.com/hy3/cuto@v0.9.8-0.20160830082821-aa6652f877b7/util/lock_windows.go (about)

     1  // Copyright 2015 unirita Inc.
     2  // Created 2015/04/10 shanxia
     3  
     4  package util
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"os"
    10  	"syscall"
    11  	"unsafe"
    12  )
    13  
    14  // ミューテックスハンドルを保持する。
    15  type LockHandle struct {
    16  	handle uintptr
    17  	isLock bool
    18  }
    19  
    20  const (
    21  	wAIT_OBJECT_0  int = 0
    22  	wAIT_ABANDONED int = 128
    23  	wAIT_TIMEOUT   int = 258
    24  )
    25  
    26  var ErrBusy = errors.New("Locked by other process.")
    27  
    28  // プロセス間で共通に使用する名前を指定する。
    29  func InitLock(name string) (*LockHandle, error) {
    30  	mutexName := fmt.Sprintf("Global\\%s", name)
    31  	hMutex, _, _ := procCreateMutexW.Call(
    32  		0, 0, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(mutexName))))
    33  	if hMutex == 0 {
    34  		lastErr := syscall.GetLastError()
    35  		fmt.Fprintf(os.Stderr, "Failed InitMutexW() EC = %v", lastErr)
    36  		return nil, lastErr
    37  	}
    38  	return &LockHandle{hMutex, false}, nil
    39  }
    40  
    41  // ロックを開始する。
    42  // 引数でタイムアウト時間(ミリ秒)を指定する。
    43  func (l *LockHandle) Lock(timeout_milisec int) error {
    44  	r1, _, _ := procWaitForSingleObject.Call(l.handle, uintptr(timeout_milisec))
    45  	if int(r1) == wAIT_OBJECT_0 || int(r1) == wAIT_ABANDONED {
    46  		// Lock成功
    47  		l.isLock = true
    48  		return nil
    49  	} else if int(r1) == wAIT_TIMEOUT {
    50  		fmt.Fprintf(os.Stderr, "Lock Timeout.\n")
    51  		return ErrBusy
    52  	}
    53  	return fmt.Errorf("Lock Unknown Error. EC( %v )", syscall.GetLastError())
    54  }
    55  
    56  // ロック中であれば、解除する。
    57  func (l *LockHandle) Unlock() error {
    58  	if l.isLock {
    59  		r1, _, _ := procReleaseMutex.Call(l.handle)
    60  		if int(r1) == 0 { // 失敗
    61  			return fmt.Errorf("Unlock Error. EC( %v )", syscall.GetLastError())
    62  		}
    63  		l.isLock = false
    64  		return nil
    65  	}
    66  	return nil
    67  }
    68  
    69  // 自プロセスがロックしているかの確認
    70  func (l *LockHandle) IsLock() bool {
    71  	isLock := false
    72  	r1, _, _ := procWaitForSingleObject.Call(l.handle, 0)
    73  	if int(r1) == wAIT_OBJECT_0 || int(r1) == wAIT_ABANDONED {
    74  		isLock = l.isLock
    75  		procReleaseMutex.Call(l.handle)
    76  		return isLock
    77  	}
    78  	return isLock
    79  }
    80  
    81  // InitMutexで確保したミューテックスオブジェクトを破棄する。
    82  func (l *LockHandle) TermLock() error {
    83  	procCloseHandle.Call(l.handle)
    84  	return nil
    85  }