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  }