github.com/searKing/golang/go@v1.2.117/sync/filelock/lockedfile.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Copied from go/gc/src/cmd/go/internal/lockedfile/lockedfile.go 6 7 package filelock 8 9 import ( 10 "fmt" 11 "io/fs" 12 "os" 13 "runtime" 14 ) 15 16 type LockedFile[T File] struct { 17 File T 18 closed bool 19 } 20 21 // NewLockedFile returns a locked file. 22 // If flag includes os.O_WRONLY or os.O_RDWR, the file is write-locked; 23 // otherwise, it is read-locked. 24 func NewLockedFile(file *os.File) (*LockedFile[*os.File], error) { 25 var f LockedFile[*os.File] 26 f.File = file 27 28 // Although the operating system will drop locks for open files when the go 29 // command exits, we want to hold locks for as little time as possible, and we 30 // especially don't want to leave a file locked after we're done with it. Our 31 // Close method is what releases the locks, so use a finalizer to report 32 // missing Close calls on a best-effort basis. 33 runtime.SetFinalizer(&f, func(f *LockedFile[*os.File]) { 34 panic(fmt.Sprintf("lockedfile.File %s became unreachable without a call to Close", f.File.Name())) 35 }) 36 return &f, nil 37 } 38 39 // Close unlocks and closes the underlying file. 40 // 41 // Close may be called multiple times; all calls after the first will return a 42 // non-nil error. 43 func (f *LockedFile[T]) Close() error { 44 if f.closed { 45 return &fs.PathError{ 46 Op: "close", 47 Path: f.File.Name(), 48 Err: fs.ErrClosed, 49 } 50 } 51 f.closed = true 52 53 err := closeFile(f.File) 54 runtime.SetFinalizer(f, nil) 55 return err 56 } 57 func (f *LockedFile[T]) Lock() error { 58 return Lock(f.File) 59 } 60 61 func (f *LockedFile[T]) TryLock() (bool, error) { 62 return TryLock(f.File) 63 } 64 65 func (f *LockedFile[T]) Unlock() error { 66 return Unlock(f.File) 67 } 68 69 func (f *LockedFile[T]) RLock() error { 70 return RLock(f.File) 71 } 72 73 func (f *LockedFile[T]) RUnlock() error { 74 return Unlock(f.File) 75 }