|
5 | 5 | "fmt" |
6 | 6 | "strconv" |
7 | 7 | "strings" |
| 8 | + "time" |
8 | 9 | ) |
9 | 10 |
|
10 | 11 | var ( |
@@ -49,10 +50,24 @@ func (l *Lock) Lock() error { |
49 | 50 | return l.LockWithData([]byte{}) |
50 | 51 | } |
51 | 52 |
|
| 53 | +// TryLock attempts to acquire the lock before a timeout. It works like LockWithData, but it doesn't |
| 54 | +// write any data to the lock node. |
| 55 | +func (l *Lock) TryLock(timeout time.Duration) error { |
| 56 | + return l.TryLockWithData([]byte{}, timeout) |
| 57 | +} |
| 58 | + |
52 | 59 | // LockWithData attempts to acquire the lock, writing data into the lock node. |
53 | 60 | // It will wait to return until the lock is acquired or an error occurs. If |
54 | 61 | // this instance already has the lock then ErrDeadlock is returned. |
55 | 62 | func (l *Lock) LockWithData(data []byte) error { |
| 63 | + return l.TryLockWithData(data, time.Duration(-1)) |
| 64 | +} |
| 65 | + |
| 66 | +// TryLockWithData attempts to acquire the lock, writing data into the lock node. |
| 67 | +// It will wait to return until the lock is acquired, an error occurs, or the timeout. If |
| 68 | +// this instance already has the lock then ErrDeadlock is returned. A negative |
| 69 | +// timeout is waiting forever |
| 70 | +func (l *Lock) TryLockWithData(data []byte, timeout time.Duration) error { |
56 | 71 | if l.lockPath != "" { |
57 | 72 | return ErrDeadlock |
58 | 73 | } |
@@ -97,6 +112,8 @@ func (l *Lock) LockWithData(data []byte) error { |
97 | 112 | return err |
98 | 113 | } |
99 | 114 |
|
| 115 | + start := time.Now() |
| 116 | + |
100 | 117 | for { |
101 | 118 | children, _, err := l.c.Children(l.path) |
102 | 119 | if err != nil { |
@@ -134,9 +151,25 @@ func (l *Lock) LockWithData(data []byte) error { |
134 | 151 | continue |
135 | 152 | } |
136 | 153 |
|
137 | | - ev := <-ch |
138 | | - if ev.Err != nil { |
139 | | - return ev.Err |
| 154 | + if timeout >= 0 { |
| 155 | + wait := start.Add(timeout).Sub(time.Now()) |
| 156 | + if wait < 0 { |
| 157 | + wait = time.Duration(1) |
| 158 | + } |
| 159 | + delay := time.NewTimer(wait) |
| 160 | + select { |
| 161 | + case ev := <-ch: |
| 162 | + if ev.Err != nil { |
| 163 | + return ev.Err |
| 164 | + } |
| 165 | + case <-delay.C: |
| 166 | + return ErrTimeout |
| 167 | + } |
| 168 | + } else { |
| 169 | + ev := <-ch |
| 170 | + if ev.Err != nil { |
| 171 | + return ev.Err |
| 172 | + } |
140 | 173 | } |
141 | 174 | } |
142 | 175 |
|
|
0 commit comments