mirror of
https://github.com/hanzoai/forge.git
synced 2026-10-30 15:00:39 +00:00
Source files keep their SPDX-License-Identifier and Hanzo copyright line; the Gitea, Gogs and LFS Test Server copyrights they used to repeat now live once in NOTICE, alongside LICENSE. The header lint accepts any copyright line above the SPDX line, so it no longer demands an upstream one. Co-authored-by: Hanzo Dev <[email protected]>
83 lines
2.1 KiB
Go
83 lines
2.1 KiB
Go
// Copyright 2026 Hanzo AI, Inc. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package globallock
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"sync/atomic"
|
|
|
|
"github.com/hanzoai/git/modules/setting"
|
|
)
|
|
|
|
var (
|
|
defaultLocker atomic.Pointer[Locker]
|
|
defaultMutex sync.Mutex
|
|
)
|
|
|
|
func initDefaultLocker() Locker {
|
|
switch setting.GlobalLock.ServiceType {
|
|
case "kv":
|
|
return NewKVLocker(setting.GlobalLock.ServiceConnStr)
|
|
default: // "memory"
|
|
return NewMemoryLocker()
|
|
}
|
|
}
|
|
|
|
// DefaultLocker returns the default locker.
|
|
func DefaultLocker() Locker {
|
|
ptr := defaultLocker.Load()
|
|
if ptr == nil {
|
|
defaultMutex.Lock()
|
|
ptr = defaultLocker.Load()
|
|
if ptr == nil {
|
|
ptr = new(initDefaultLocker())
|
|
defaultLocker.Store(ptr)
|
|
}
|
|
defaultMutex.Unlock()
|
|
ptr = defaultLocker.Load()
|
|
}
|
|
return *ptr
|
|
}
|
|
|
|
// Lock tries to acquire a lock for the given key, it uses the default locker.
|
|
// Read the documentation of Locker.Lock for more information about the behavior.
|
|
func Lock(ctx context.Context, key string) (ReleaseFunc, error) {
|
|
return DefaultLocker().Lock(ctx, key)
|
|
}
|
|
|
|
// TryLock tries to acquire a lock for the given key, it uses the default locker.
|
|
// Read the documentation of Locker.TryLock for more information about the behavior.
|
|
func TryLock(ctx context.Context, key string) (bool, ReleaseFunc, error) {
|
|
return DefaultLocker().TryLock(ctx, key)
|
|
}
|
|
|
|
// LockAndDo tries to acquire a lock for the given key and then calls the given function.
|
|
// It uses the default locker, and it will return an error if failed to acquire the lock.
|
|
func LockAndDo(ctx context.Context, key string, f func(context.Context) error) error {
|
|
release, err := Lock(ctx, key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer release()
|
|
|
|
return f(ctx)
|
|
}
|
|
|
|
// TryLockAndDo tries to acquire a lock for the given key and then calls the given function.
|
|
// It uses the default locker, and it will return false if failed to acquire the lock.
|
|
func TryLockAndDo(ctx context.Context, key string, f func(context.Context) error) (bool, error) {
|
|
ok, release, err := TryLock(ctx, key)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
defer release()
|
|
|
|
if !ok {
|
|
return false, nil
|
|
}
|
|
|
|
return true, f(ctx)
|
|
}
|