gitea源码

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. // Copyright 2024 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package globallock
  4. import (
  5. "context"
  6. "sync"
  7. "time"
  8. )
  9. type memoryLocker struct {
  10. locks sync.Map
  11. }
  12. var _ Locker = &memoryLocker{}
  13. func NewMemoryLocker() Locker {
  14. return &memoryLocker{}
  15. }
  16. func (l *memoryLocker) Lock(ctx context.Context, key string) (ReleaseFunc, error) {
  17. if l.tryLock(key) {
  18. releaseOnce := sync.Once{}
  19. return func() {
  20. releaseOnce.Do(func() {
  21. l.locks.Delete(key)
  22. })
  23. }, nil
  24. }
  25. ticker := time.NewTicker(time.Millisecond * 100)
  26. defer ticker.Stop()
  27. for {
  28. select {
  29. case <-ctx.Done():
  30. return func() {}, ctx.Err()
  31. case <-ticker.C:
  32. if l.tryLock(key) {
  33. releaseOnce := sync.Once{}
  34. return func() {
  35. releaseOnce.Do(func() {
  36. l.locks.Delete(key)
  37. })
  38. }, nil
  39. }
  40. }
  41. }
  42. }
  43. func (l *memoryLocker) TryLock(_ context.Context, key string) (bool, ReleaseFunc, error) {
  44. if l.tryLock(key) {
  45. releaseOnce := sync.Once{}
  46. return true, func() {
  47. releaseOnce.Do(func() {
  48. l.locks.Delete(key)
  49. })
  50. }, nil
  51. }
  52. return false, func() {}, nil
  53. }
  54. func (l *memoryLocker) tryLock(key string) bool {
  55. _, loaded := l.locks.LoadOrStore(key, struct{}{})
  56. return !loaded
  57. }