github.com/searKing/golang/go@v1.2.117/sync/filelock/filelock.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  // Package filelock provides a platform-independent API for advisory file
     6  // locking. Calls to functions in this package on platforms that do not support
     7  // advisory locks will return errors for which IsNotSupported returns true.
     8  //
     9  // Copied from go/gc/src/cmd/go/internal/lockedfile/internal/filelock/filelock.go
    10  
    11  package filelock
    12  
    13  import (
    14  	"errors"
    15  	"io/fs"
    16  	"os"
    17  )
    18  
    19  // A File provides the minimal set of methods required to lock an open file.
    20  // File implementations must be usable as map keys.
    21  // The usual implementation is *os.File.
    22  type File interface {
    23  	// Name returns the name of the file.
    24  	Name() string
    25  
    26  	// Fd returns a valid file descriptor.
    27  	// (If the File is an *os.File, it must not be closed.)
    28  	Fd() uintptr
    29  
    30  	// Stat returns the FileInfo structure describing file.
    31  	Stat() (fs.FileInfo, error)
    32  }
    33  
    34  // Lock places an advisory write lock on the file, blocking until it can be
    35  // locked.
    36  //
    37  // If Lock returns nil, no other process will be able to place a read or write
    38  // lock on the file until this process exits, closes f, or calls Unlock on it.
    39  //
    40  // If f's descriptor is already read- or write-locked, the behavior of Lock is
    41  // unspecified.
    42  //
    43  // Closing the file may or may not release the lock promptly. Callers should
    44  // ensure that Unlock is always called when Lock succeeds.
    45  func Lock(f File) error {
    46  	return lock(f, writeLock, false)
    47  }
    48  
    49  // TryLock tries to lock rw for writing and reports whether it succeeded.
    50  //
    51  // Note that while correct uses of TryLock do exist, they are rare,
    52  // and use of TryLock is often a sign of a deeper problem
    53  // in a particular use of mutexes.
    54  func TryLock(f File) (bool, error) {
    55  	err := lock(f, writeLock, true)
    56  	if err != nil {
    57  		if os.IsTimeout(err) {
    58  			return false, nil
    59  		}
    60  		return false, err
    61  	}
    62  	return true, nil
    63  }
    64  
    65  // RLock places an advisory read lock on the file, blocking until it can be locked.
    66  //
    67  // If RLock returns nil, no other process will be able to place a write lock on
    68  // the file until this process exits, closes f, or calls Unlock on it.
    69  //
    70  // If f is already read- or write-locked, the behavior of RLock is unspecified.
    71  //
    72  // Closing the file may or may not release the lock promptly. Callers should
    73  // ensure that Unlock is always called if RLock succeeds.
    74  func RLock(f File) error {
    75  	return lock(f, readLock, false)
    76  }
    77  
    78  // TryRLock tries to lock rw for reading and reports whether it succeeded.
    79  //
    80  // Note that while correct uses of TryRLock do exist, they are rare,
    81  // and use of TryRLock is often a sign of a deeper problem
    82  // in a particular use of mutexes.
    83  func TryRLock(f File) (bool, error) {
    84  	err := lock(f, readLock, true)
    85  	if err != nil {
    86  		if os.IsTimeout(err) {
    87  			return false, nil
    88  		}
    89  		return false, err
    90  	}
    91  	return true, nil
    92  }
    93  
    94  // Unlock removes an advisory lock placed on f by this process.
    95  //
    96  // The caller must not attempt to unlock a file that is not locked.
    97  func Unlock(f File) error {
    98  	return unlock(f)
    99  }
   100  
   101  // String returns the name of the function corresponding to lt
   102  // (Lock, RLock, or Unlock).
   103  func (lt lockType) String() string {
   104  	switch lt {
   105  	case readLock:
   106  		return "RLock"
   107  	case writeLock:
   108  		return "Lock"
   109  	default:
   110  		return "Unlock"
   111  	}
   112  }
   113  
   114  // IsNotSupported returns a boolean indicating whether the error is known to
   115  // report that a function is not supported (possibly for a specific input).
   116  // It is satisfied by errors.ErrUnsupported as well as some syscall errors.
   117  func IsNotSupported(err error) bool {
   118  	return errors.Is(err, errors.ErrUnsupported)
   119  }