mutex.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. // Copyright 2021 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. // Package syncx contains exotic synchronization primitives.
  17. package syncx
  18. // ClosableMutex is a mutex that can also be closed.
  19. // Once closed, it can never be taken again.
  20. type ClosableMutex struct {
  21. ch chan struct{}
  22. }
  23. func NewClosableMutex() *ClosableMutex {
  24. ch := make(chan struct{}, 1)
  25. ch <- struct{}{}
  26. return &ClosableMutex{ch}
  27. }
  28. // TryLock attempts to lock cm.
  29. // If the mutex is closed, TryLock returns false.
  30. func (cm *ClosableMutex) TryLock() bool {
  31. _, ok := <-cm.ch
  32. return ok
  33. }
  34. // MustLock locks cm.
  35. // If the mutex is closed, MustLock panics.
  36. func (cm *ClosableMutex) MustLock() {
  37. _, ok := <-cm.ch
  38. if !ok {
  39. panic("mutex closed")
  40. }
  41. }
  42. // Unlock unlocks cm.
  43. func (cm *ClosableMutex) Unlock() {
  44. select {
  45. case cm.ch <- struct{}{}:
  46. default:
  47. panic("Unlock of already-unlocked ClosableMutex")
  48. }
  49. }
  50. // Close locks the mutex, then closes it.
  51. func (cm *ClosableMutex) Close() {
  52. _, ok := <-cm.ch
  53. if !ok {
  54. panic("Close of already-closed ClosableMutex")
  55. }
  56. close(cm.ch)
  57. }