Skip to content

Commit

Permalink
chore: apply semantic line breaks
Browse files Browse the repository at this point in the history
  • Loading branch information
ldez committed Jun 30, 2024
1 parent 016605a commit c9b0b98
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 127 deletions.
14 changes: 8 additions & 6 deletions flock.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,18 @@ func (f *Flock) String() string {
return f.path
}

// TryLockContext repeatedly tries to take an exclusive lock until one of the
// conditions is met: TryLock succeeds, TryLock fails with error, or Context
// Done channel is closed.
// TryLockContext repeatedly tries to take an exclusive lock until one of the conditions is met:
// - TryLock succeeds
// - TryLock fails with error
// - Context Done channel is closed.
func (f *Flock) TryLockContext(ctx context.Context, retryDelay time.Duration) (bool, error) {
return tryCtx(ctx, f.TryLock, retryDelay)
}

// TryRLockContext repeatedly tries to take a shared lock until one of the
// conditions is met: TryRLock succeeds, TryRLock fails with error, or Context
// Done channel is closed.
// TryRLockContext repeatedly tries to take a shared lock until one of the conditions is met:
// - TryRLock succeeds
// - TryRLock fails with error
// - Context Done channel is closed.
func (f *Flock) TryRLockContext(ctx context.Context, retryDelay time.Duration) (bool, error) {
return tryCtx(ctx, f.TryRLock, retryDelay)
}
Expand Down
91 changes: 47 additions & 44 deletions flock_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,29 @@ import (
"syscall"
)

// Lock is a blocking call to try and take an exclusive file lock. It will wait
// until it is able to obtain the exclusive file lock. It's recommended that
// TryLock() be used over this function. This function may block the ability to
// query the current Locked() or RLocked() status due to a RW-mutex lock.
// Lock is a blocking call to try and take an exclusive file lock.
// It will wait until it is able to obtain the exclusive file lock.
// It's recommended that TryLock() be used over this function.
// This function may block the ability to query the current Locked() or RLocked() status due to a RW-mutex lock.
//
// If we are already exclusive-locked, this function short-circuits and returns
// immediately assuming it can take the mutex lock.
// If we are already exclusive-locked,
// this function short-circuits and returns immediately assuming it can take the mutex lock.
//
// If the *Flock has a shared lock (RLock), this may transparently replace the
// shared lock with an exclusive lock on some UNIX-like operating systems. Be
// careful when using exclusive locks in conjunction with shared locks
// (RLock()), because calling Unlock() may accidentally release the exclusive
// lock that was once a shared lock.
// If the *Flock has a shared lock (RLock),
// this may transparently replace the shared lock with an exclusive lock on some UNIX-like operating systems.
// Be careful when using exclusive locks in conjunction with shared locks (RLock()),
// because calling Unlock() may accidentally release the exclusive lock that was once a shared lock.
func (f *Flock) Lock() error {
return f.lock(&f.l, syscall.LOCK_EX)
}

// RLock is a blocking call to try and take a shared file lock. It will wait
// until it is able to obtain the shared file lock. It's recommended that
// TryRLock() be used over this function. This function may block the ability to
// query the current Locked() or RLocked() status due to a RW-mutex lock.
// RLock is a blocking call to try and take a shared file lock.
// It will wait until it is able to obtain the shared file lock.
// It's recommended that TryRLock() be used over this function.
// This function may block the ability to query the current Locked() or RLocked() status due to a RW-mutex lock.
//
// If we are already shared-locked, this function short-circuits and returns
// immediately assuming it can take the mutex lock.
// If we are already shared-locked,
// this function short-circuits and returns immediately assuming it can take the mutex lock.
func (f *Flock) RLock() error {
return f.lock(&f.r, syscall.LOCK_SH)
}
Expand Down Expand Up @@ -77,27 +76,29 @@ func (f *Flock) lock(locked *bool, flag int) error {
return nil
}

// Unlock is a function to unlock the file. This file takes a RW-mutex lock, so
// while it is running the Locked() and RLocked() functions will be blocked.
// Unlock is a function to unlock the file.
// This file takes a RW-mutex lock,
// so while it is running the Locked() and RLocked() functions will be blocked.
//
// This function short-circuits if we are unlocked already. If not, it calls
// syscall.LOCK_UN on the file and closes the file descriptor. It does not
// remove the file from disk. It's up to your application to do.
// This function short-circuits if we are unlocked already.
// If not, it calls syscall.LOCK_UN on the file and closes the file descriptor.
// It does not remove the file from disk. It's up to your application to do.
//
// Please note, if your shared lock became an exclusive lock this may
// unintentionally drop the exclusive lock if called by the consumer that
// believes they have a shared lock. Please see Lock() for more details.
// Please note,
// if your shared lock became an exclusive lock,
// this may unintentionally drop the exclusive lock if called by the consumer that believes they have a shared lock.
// Please see Lock() for more details.
func (f *Flock) Unlock() error {
f.m.Lock()
defer f.m.Unlock()

// if we aren't locked or if the lockfile instance is nil
// just return a nil error because we are unlocked
// If we aren't locked or if the lockfile instance is nil
// just return a nil error because we are unlocked.
if (!f.l && !f.r) || f.fh == nil {
return nil
}

// mark the file as unlocked
// Mark the file as unlocked.
if err := syscall.Flock(int(f.fh.Fd()), syscall.LOCK_UN); err != nil {
return err
}
Expand All @@ -111,26 +112,28 @@ func (f *Flock) Unlock() error {
return nil
}

// TryLock is the preferred function for taking an exclusive file lock. This
// function takes an RW-mutex lock before it tries to lock the file, so there is
// the possibility that this function may block for a short time if another
// goroutine is trying to take any action.
// TryLock is the preferred function for taking an exclusive file lock.
// This function takes an RW-mutex lock before it tries to lock the file,
// so there is the possibility that this function may block for a short time
// if another goroutine is trying to take any action.
//
// The actual file lock is non-blocking. If we are unable to get the exclusive
// file lock, the function will return false instead of waiting for the lock. If
// we get the lock, we also set the *Flock instance as being exclusive-locked.
// The actual file lock is non-blocking.
// If we are unable to get the exclusive file lock,
// the function will return false instead of waiting for the lock.
// If we get the lock, we also set the *Flock instance as being exclusive-locked.
func (f *Flock) TryLock() (bool, error) {
return f.try(&f.l, syscall.LOCK_EX)
}

// TryRLock is the preferred function for taking a shared file lock. This
// function takes an RW-mutex lock before it tries to lock the file, so there is
// the possibility that this function may block for a short time if another
// goroutine is trying to take any action.
// TryRLock is the preferred function for taking a shared file lock.
// This function takes an RW-mutex lock before it tries to lock the file,
// so there is the possibility that this function may block for a short time
// if another goroutine is trying to take any action.
//
// The actual file lock is non-blocking. If we are unable to get the shared file
// lock, the function will return false instead of waiting for the lock. If we
// get the lock, we also set the *Flock instance as being share-locked.
// The actual file lock is non-blocking.
// If we are unable to get the shared file lock,
// the function will return false instead of waiting for the lock.
// If we get the lock, we also set the *Flock instance as being share-locked.
func (f *Flock) TryRLock() (bool, error) {
return f.try(&f.r, syscall.LOCK_SH)
}
Expand Down Expand Up @@ -175,8 +178,8 @@ retry:
return false, err
}

// reopenFDOnError determines whether we should reopen the file handle
// in readwrite mode and try again. This comes from util-linux/sys-utils/flock.c:
// reopenFDOnError determines whether we should reopen the file handle in readwrite mode and try again.
// This comes from `util-linux/sys-utils/flock.c`:
//
// Since Linux 3.4 (commit 55725513)
// Probably NFSv4 where flock() is emulated by fcntl().
Expand Down
81 changes: 41 additions & 40 deletions flock_unix_variants.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This code implements the filelock API using POSIX 'fcntl' locks, which attach
// to an (inode, process) pair rather than a file descriptor. To avoid unlocking
// files prematurely when the same file is opened through different descriptors,
// This code implements the filelock API using POSIX 'fcntl' locks,
// which attach to an (inode, process) pair rather than a file descriptor.
// To avoid unlocking files prematurely when the same file is opened through different descriptors,
// we allow only one read-lock at a time.
//
// This code is adapted from the Go package:
Expand Down Expand Up @@ -56,30 +56,29 @@ var (
locks = map[inode]inodeLock{}
)

// Lock is a blocking call to try and take an exclusive file lock. It will wait
// until it is able to obtain the exclusive file lock. It's recommended that
// TryLock() be used over this function. This function may block the ability to
// query the current Locked() or RLocked() status due to a RW-mutex lock.
// Lock is a blocking call to try and take an exclusive file lock.
// It will wait until it is able to obtain the exclusive file lock.
// It's recommended that TryLock() be used over this function.
// This function may block the ability to query the current Locked() or RLocked() status due to a RW-mutex lock.
//
// If we are already exclusive-locked, this function short-circuits and returns
// immediately assuming it can take the mutex lock.
// If we are already exclusive-locked, this function short-circuits and
// returns immediately assuming it can take the mutex lock.
//
// If the *Flock has a shared lock (RLock), this may transparently replace the
// shared lock with an exclusive lock on some UNIX-like operating systems. Be
// careful when using exclusive locks in conjunction with shared locks
// (RLock()), because calling Unlock() may accidentally release the exclusive
// lock that was once a shared lock.
// If the *Flock has a shared lock (RLock),
// this may transparently replace the shared lock with an exclusive lock on some UNIX-like operating systems.
// Be careful when using exclusive locks in conjunction with shared locks (RLock()),
// because calling Unlock() may accidentally release the exclusive lock that was once a shared lock.
func (f *Flock) Lock() error {
return f.lock(&f.l, writeLock)
}

// RLock is a blocking call to try and take a shared file lock. It will wait
// until it is able to obtain the shared file lock. It's recommended that
// TryRLock() be used over this function. This function may block the ability to
// query the current Locked() or RLocked() status due to a RW-mutex lock.
// RLock is a blocking call to try and take a shared file lock.
// It will wait until it is able to obtain the shared file lock.
// It's recommended that TryRLock() be used over this function.
// This function may block the ability to query the current Locked() or RLocked() status due to a RW-mutex lock.
//
// If we are already shared-locked, this function short-circuits and returns
// immediately assuming it can take the mutex lock.
// If we are already shared-locked, this function short-circuits and
// returns immediately assuming it can take the mutex lock.
func (f *Flock) RLock() error {
return f.lock(&f.r, readLock)
}
Expand Down Expand Up @@ -110,10 +109,10 @@ func (f *Flock) lock(locked *bool, flag lockType) error {
}

func (f *Flock) doLock(cmd cmdType, lt lockType, blocking bool) (bool, error) {
// POSIX locks apply per inode and process, and the lock for an inode is
// released when *any* descriptor for that inode is closed. So we need to
// synchronize access to each inode internally, and must serialize lock and
// unlock calls that refer to the same inode through different descriptors.
// POSIX locks apply per inode and process,
// and the lock for an inode is released when *any* descriptor for that inode is closed.
// So we need to synchronize access to each inode internally,
// and must serialize lock and unlock calls that refer to the same inode through different descriptors.
fi, err := f.fh.Stat()
if err != nil {
return false, err
Expand Down Expand Up @@ -179,8 +178,8 @@ func (f *Flock) Unlock() error {
f.m.Lock()
defer f.m.Unlock()

// if we aren't locked or if the lockfile instance is nil
// just return a nil error because we are unlocked
// If we aren't locked or if the lockfile instance is nil
// just return a nil error because we are unlocked.
if (!f.l && !f.r) || f.fh == nil {
return nil
}
Expand Down Expand Up @@ -236,26 +235,28 @@ func (f *Flock) doUnlock() (err error) {
return err
}

// TryLock is the preferred function for taking an exclusive file lock. This
// function takes an RW-mutex lock before it tries to lock the file, so there is
// the possibility that this function may block for a short time if another
// goroutine is trying to take any action.
// TryLock is the preferred function for taking an exclusive file lock.
// This function takes an RW-mutex lock before it tries to lock the file,
// so there is the possibility that this function may block for a short time
// if another goroutine is trying to take any action.
//
// The actual file lock is non-blocking. If we are unable to get the exclusive
// file lock, the function will return false instead of waiting for the lock. If
// we get the lock, we also set the *Flock instance as being exclusive-locked.
// The actual file lock is non-blocking.
// If we are unable to get the exclusive file lock,
// the function will return false instead of waiting for the lock.
// If we get the lock, we also set the *Flock instance as being exclusive-locked.
func (f *Flock) TryLock() (bool, error) {
return f.try(&f.l, writeLock)
}

// TryRLock is the preferred function for taking a shared file lock. This
// function takes an RW-mutex lock before it tries to lock the file, so there is
// the possibility that this function may block for a short time if another
// goroutine is trying to take any action.
// TryRLock is the preferred function for taking a shared file lock.
// This function takes an RW-mutex lock before it tries to lock the file,
// so there is the possibility that this function may block for a short time
// if another goroutine is trying to take any action.
//
// The actual file lock is non-blocking. If we are unable to get the shared file
// lock, the function will return false instead of waiting for the lock. If we
// get the lock, we also set the *Flock instance as being share-locked.
// The actual file lock is non-blocking.
// If we are unable to get the shared file lock,
// the function will return false instead of waiting for the lock.
// If we get the lock, we also set the *Flock instance as being share-locked.
func (f *Flock) TryRLock() (bool, error) {
return f.try(&f.r, readLock)
}
Expand Down
7 changes: 3 additions & 4 deletions flock_winapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@ const (
winLockfileSharedLock = 0x00000000
)

// Use of 0x00000000 for the shared lock is a guess based on some the MS Windows
// `LockFileEX` docs, which document the `LOCKFILE_EXCLUSIVE_LOCK` flag as:
// Use of 0x00000000 for the shared lock is a guess based on some the MS Windows `LockFileEX` docs,
// which document the `LOCKFILE_EXCLUSIVE_LOCK` flag as:
//
// > The function requests an exclusive lock. Otherwise, it requests a shared
// > lock.
// > The function requests an exclusive lock. Otherwise, it requests a shared lock.
//
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx

Expand Down
Loading

0 comments on commit c9b0b98

Please sign in to comment.