@@ -2,7 +2,6 @@ package memdb
2
2
3
3
import (
4
4
"io"
5
- "runtime"
6
5
"sync"
7
6
"time"
8
7
@@ -85,9 +84,10 @@ type memDB struct {
85
84
// +checklocks:memoryMtx
86
85
refs int32
87
86
88
- shared int32 // +checklocks:lockMtx
89
- pending bool // +checklocks:lockMtx
90
- reserved bool // +checklocks:lockMtx
87
+ shared int32 // +checklocks:lockMtx
88
+ pending bool // +checklocks:lockMtx
89
+ reserved bool // +checklocks:lockMtx
90
+ waiter * sync.Cond // +checklocks:lockMtx
91
91
92
92
lockMtx sync.Mutex
93
93
dataMtx sync.RWMutex
@@ -195,8 +195,6 @@ func (m *memFile) Size() (int64, error) {
195
195
return m .size , nil
196
196
}
197
197
198
- const spinWait = 25 * time .Microsecond
199
-
200
198
func (m * memFile ) Lock (lock vfs.LockLevel ) error {
201
199
if m .lock >= lock {
202
200
return nil
@@ -228,13 +226,18 @@ func (m *memFile) Lock(lock vfs.LockLevel) error {
228
226
m .pending = true
229
227
}
230
228
231
- for before := time .Now (); m .shared > 1 ; {
232
- if time .Since (before ) > spinWait {
233
- return sqlite3 .BUSY
229
+ if m .shared > 1 {
230
+ before := time .Now ()
231
+ if m .waiter == nil {
232
+ m .waiter = sync .NewCond (& m .lockMtx )
233
+ }
234
+ defer time .AfterFunc (time .Millisecond , m .waiter .Broadcast ).Stop ()
235
+ for m .shared > 1 {
236
+ if time .Since (before ) > time .Millisecond {
237
+ return sqlite3 .BUSY
238
+ }
239
+ m .waiter .Wait ()
234
240
}
235
- m .lockMtx .Unlock ()
236
- runtime .Gosched ()
237
- m .lockMtx .Lock ()
238
241
}
239
242
}
240
243
@@ -257,7 +260,9 @@ func (m *memFile) Unlock(lock vfs.LockLevel) error {
257
260
m .pending = false
258
261
}
259
262
if lock < vfs .LOCK_SHARED {
260
- m .shared --
263
+ if m .shared -- ; m .pending && m .shared <= 1 && m .waiter != nil {
264
+ m .waiter .Broadcast ()
265
+ }
261
266
}
262
267
m .lock = lock
263
268
return nil
0 commit comments