Skip to content

Commit

Permalink
Merge pull request #12 from femaref/non-blocking-lock
Browse files Browse the repository at this point in the history
Non blocking lock
  • Loading branch information
alexflint authored Apr 3, 2020
2 parents 0181f11 + f02b7bf commit 392c3ab
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 1 deletion.
5 changes: 5 additions & 0 deletions filemutex.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package filemutex

import "errors"

var AlreadyLocked = errors.New("lock already acquired")
12 changes: 12 additions & 0 deletions filemutex_flock.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ func (m *FileMutex) Lock() error {
return nil
}

func (m *FileMutex) TryLock() error {
if err := syscall.Flock(m.fd, syscall.LOCK_EX|syscall.LOCK_NB); err != nil {
if errno, ok := err.(syscall.Errno); ok {
if errno == syscall.EWOULDBLOCK {
return AlreadyLocked
}
}
return err
}
return nil
}

func (m *FileMutex) Unlock() error {
if err := syscall.Flock(m.fd, syscall.LOCK_UN); err != nil {
return err
Expand Down
21 changes: 21 additions & 0 deletions filemutex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,27 @@ func TestLockUnlock(t *testing.T) {
require.NoError(t, err)
}

func TestTryLockUnlock(t *testing.T) {
dir, err := ioutil.TempDir("", "")
require.NoError(t, err)
defer os.RemoveAll(dir)

path := filepath.Join(dir, "x")
m, err := New(path)
require.NoError(t, err)
m2, err := New(path)
require.NoError(t, err)

err = m.Lock()
require.NoError(t, err)
err = m2.TryLock()
require.Equal(t, AlreadyLocked, err)
err = m.Unlock()
require.NoError(t, err)
err = m2.TryLock()
require.NoError(t, err)
}

func TestRLockUnlock(t *testing.T) {
dir, err := ioutil.TempDir("", "")
require.NoError(t, err)
Expand Down
16 changes: 15 additions & 1 deletion filemutex_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ var (
)

const (
lockfileExclusiveLock = 2
lockfileFailImmediately = 1
lockfileExclusiveLock = 2
)

func lockFileEx(h syscall.Handle, flags, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) {
Expand Down Expand Up @@ -58,6 +59,19 @@ func New(filename string) (*FileMutex, error) {
return &FileMutex{fd: fd}, nil
}

func (m *FileMutex) TryLock() error {
var ol syscall.Overlapped
if err := lockFileEx(m.fd, lockfileFailImmediately|lockfileExclusiveLock, 0, 1, 0, &ol); err != nil {
if errno, ok := err.(syscall.Errno); ok {
if errno == syscall.Errno(0x21) {
return AlreadyLocked
}
}
return err
}
return nil
}

func (m *FileMutex) Lock() error {
var ol syscall.Overlapped
if err := lockFileEx(m.fd, lockfileExclusiveLock, 0, 1, 0, &ol); err != nil {
Expand Down

0 comments on commit 392c3ab

Please sign in to comment.