// package safe_mutex -- безопасный мьютекс package safe_mutex import ( "log" "sync" "gitp78su.ipnodns.ru/svi/kern/v4/d0/defs/def_spec_base" ) const ( // Lock -- блокировка мьютекса Lock = def_spec_base.Num(1) // Free -- разблокировка мьютекса Free = def_spec_base.Num(0) // RLock -- блокировка мьютекса с чтением RLock = def_spec_base.Num(-1) ) // MSafeMutex -- безопасный мьютекс. type MSafeMutex struct { block sync.Mutex // Блокирует операции мьютекса val sync.RWMutex // Фактическое значение мьютекса stateLock def_spec_base.Num // Значение блокировки } // MutSafeMutex -- возвращает новый безопасный мьютекс func MutSafeMutex() *MSafeMutex { sf := &MSafeMutex{} return sf } // Lock -- попытка захватить мьютекс func (sf *MSafeMutex) Lock() { sf.block.Lock() defer sf.block.Unlock() sf.val.Lock() sf.stateLock = Lock } // Unlock -- освободить мьютекс func (sf *MSafeMutex) Unlock() { sf.block.Lock() defer sf.block.Unlock() if sf.stateLock == 0 { log.Println("ERROR MSafeMutex.Unlock(): mutex already free") return } sf.val.Unlock() sf.stateLock = Free } // RLock -- попытка захватить мьютекс func (sf *MSafeMutex) RLock() { sf.block.Lock() defer sf.block.Unlock() sf.val.RLock() sf.stateLock = RLock } // RUnlock -- освободить мьютекс func (sf *MSafeMutex) RUnlock() { sf.block.Lock() defer sf.block.Unlock() if sf.stateLock == Free { log.Println("ERROR MSafeMutex.Unlock(): mutex already free") return } sf.val.RUnlock() sf.stateLock = Free } // State -- возвращает признак захвата мьютекса func (sf *MSafeMutex) State() def_spec_base.Num { sf.block.Lock() defer sf.block.Unlock() return sf.stateLock } // IsFree -- возвращает признак свободного мьютекса func (sf *MSafeMutex) IsFree() def_spec_base.Bool { sf.block.Lock() defer sf.block.Unlock() return sf.stateLock == Free }