This repository has been archived by the owner on Feb 7, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgflock.go
121 lines (108 loc) · 4.26 KB
/
gflock.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
// Package gflock implements a concurrent-safe sync.Locker interface for file locking.
package gflock
import (
"github.com/theckman/go-flock"
"os"
"path/filepath"
)
// File locker.
type Locker struct {
flock *flock.Flock // Underlying file locker.
}
// New creates and returns a new file locker with given <file>.
// The parameter <file> usually is a absolute file path.
func New(file string) *Locker {
dir := filepath.Join(os.TempDir(), "gflock")
if _, err := os.Stat(dir); os.IsNotExist(err) {
err := os.MkdirAll(dir, os.ModePerm)
if err != nil {
return nil
}
}
path := filepath.Join(dir, file)
lock := flock.New(path)
return &Locker{
flock: lock,
}
}
// Path returns the file path of the locker.
func (l *Locker) Path() string {
return l.flock.Path()
}
// IsLocked returns whether the locker is locked.
func (l *Locker) IsLocked() bool {
return l.flock.Locked()
}
// IsRLocked returns whether the locker is rlocked.
func (l *Locker) IsRLocked() bool {
return l.flock.RLocked()
}
// TryLock tries get the writing lock of the locker.
// It returns true if success, or else returns false immediately.
func (l *Locker) TryLock() bool {
ok, _ := l.flock.TryLock()
return ok
}
// TryRLock tries get the reading lock of the locker.
// It returns true if success, or else returns false immediately.
func (l *Locker) TryRLock() bool {
ok, _ := l.flock.TryRLock()
return ok
}
// Lock is a blocking call to try and take an exclusive file lock. It will wait
// until it is able to obtain the exclusive file lock. It's recommended that
// TryLock() be used over this function. This function may block the ability to
// query the current Locked() or RLocked() status due to a RW-mutex lock.
//
// If we are already exclusive-locked, this function short-circuits and returns
// immediately assuming it can take the mutex lock.
//
// If the *Flock has a shared lock (RLock), this may transparently replace the
// shared lock with an exclusive lock on some UNIX-like operating systems. Be
// careful when using exclusive locks in conjunction with shared locks
// (RLock()), because calling Unlock() may accidentally release the exclusive
// lock that was once a shared lock.
func (l *Locker) Lock() (err error) {
return l.flock.Lock()
}
// Unlock is a function to unlock the file. This file takes a RW-mutex lock, so
// while it is running the Locked() and RLocked() functions will be blocked.
//
// This function short-circuits if we are unlocked already. If not, it calls
// syscall.LOCK_UN on the file and closes the file descriptor. It does not
// remove the file from disk. It's up to your application to do.
//
// Please note, if your shared lock became an exclusive lock this may
// unintentionally drop the exclusive lock if called by the consumer that
// believes they have a shared lock. Please see Lock() for more details.
func (l *Locker) Unlock() (err error) {
return l.flock.Unlock()
}
// RLock is a blocking call to try and take a ahred file lock. It will wait
// until it is able to obtain the shared file lock. It's recommended that
// TryRLock() be used over this function. This function may block the ability to
// query the current Locked() or RLocked() status due to a RW-mutex lock.
//
// If we are already shared-locked, this function short-circuits and returns
// immediately assuming it can take the mutex lock.
func (l *Locker) RLock() (err error) {
return l.flock.RLock()
}
// Unlock is a function to unlock the file. This file takes a RW-mutex lock, so
// while it is running the Locked() and RLocked() functions will be blocked.
//
// This function short-circuits if we are unlocked already. If not, it calls
// syscall.LOCK_UN on the file and closes the file descriptor. It does not
// remove the file from disk. It's up to your application to do.
//
// Please note, if your shared lock became an exclusive lock this may
// unintentionally drop the exclusive lock if called by the consumer that
// believes they have a shared lock. Please see Lock() for more details.
func (l *Locker) RUnlock() (err error) {
return l.flock.Unlock()
}