filemutex_flock.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. // Copyright 2013 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. // +build darwin dragonfly freebsd linux netbsd openbsd solaris
  5. package filemutex
  6. import "golang.org/x/sys/unix"
  7. const (
  8. mkdirPerm = 0750
  9. )
  10. // FileMutex is similar to sync.RWMutex, but also synchronizes across processes.
  11. // This implementation is based on flock syscall.
  12. type FileMutex struct {
  13. fd int
  14. }
  15. func New(filename string) (*FileMutex, error) {
  16. fd, err := unix.Open(filename, unix.O_CREAT|unix.O_RDONLY, mkdirPerm)
  17. if err != nil {
  18. return nil, err
  19. }
  20. return &FileMutex{fd: fd}, nil
  21. }
  22. func (m *FileMutex) Lock() error {
  23. return unix.Flock(m.fd, unix.LOCK_EX)
  24. }
  25. func (m *FileMutex) TryLock() error {
  26. if err := unix.Flock(m.fd, unix.LOCK_EX|unix.LOCK_NB); err != nil {
  27. if errno, ok := err.(unix.Errno); ok {
  28. if errno == unix.EWOULDBLOCK {
  29. return AlreadyLocked
  30. }
  31. }
  32. return err
  33. }
  34. return nil
  35. }
  36. func (m *FileMutex) Unlock() error {
  37. return unix.Flock(m.fd, unix.LOCK_UN)
  38. }
  39. func (m *FileMutex) RLock() error {
  40. return unix.Flock(m.fd, unix.LOCK_SH)
  41. }
  42. func (m *FileMutex) RUnlock() error {
  43. return unix.Flock(m.fd, unix.LOCK_UN)
  44. }
  45. // Close unlocks the lock and closes the underlying file descriptor.
  46. func (m *FileMutex) Close() error {
  47. if err := unix.Flock(m.fd, unix.LOCK_UN); err != nil {
  48. return err
  49. }
  50. return unix.Close(m.fd)
  51. }