// Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build darwin dragonfly freebsd linux netbsd openbsd package main import ( "sync" "syscall" ) // FileMutex is similar to sync.RWMutex, but also synchronizes across processes. // This implementation is based on flock syscall. type FileMutex struct { mu sync.RWMutex fd int } func MakeFileMutex(filename string) *FileMutex { if filename == "" { return &FileMutex{fd: -1} } fd, err := syscall.Open(filename, syscall.O_CREAT|syscall.O_RDONLY, mkdirPerm) if err != nil { panic(err) } return &FileMutex{fd: fd} } func (m *FileMutex) Lock() { m.mu.Lock() if m.fd != -1 { if err := syscall.Flock(m.fd, syscall.LOCK_EX); err != nil { panic(err) } } } func (m *FileMutex) Unlock() { if m.fd != -1 { if err := syscall.Flock(m.fd, syscall.LOCK_UN); err != nil { panic(err) } } m.mu.Unlock() } func (m *FileMutex) RLock() { m.mu.RLock() if m.fd != -1 { if err := syscall.Flock(m.fd, syscall.LOCK_SH); err != nil { panic(err) } } } func (m *FileMutex) RUnlock() { if m.fd != -1 { if err := syscall.Flock(m.fd, syscall.LOCK_UN); err != nil { panic(err) } } m.mu.RUnlock() }