package svalue import ( "errors" "log" "reflect" "runtime" "sync" "time" ) // IValue 必须实现的值接口 type IValue interface { // TakeValue 获取 value的方法覆盖 TakeValue() interface{} // 每次 TakeValue 休眠的时间 UpdateInterval() time.Duration // Lock value的锁 Lock() // Unlock value的解锁 Unlock() // SetValue 设置动态的值 TakeValue 调用. SetValue(v interface{}) // CloseSync 关闭同步 CloseSync() // IsCloseSync 判断是否要关闭同步. 非使用者调用 IsCloseSync() bool // SetSync 设置是否已经同步的信息. 非使用者调用 SetSync(is bool) // IsSync 设置是否已经同步的信息. 非使用者调用 IsSync() bool } // Value 必须设置的动态类型 type Value struct { IValue value interface{} mutex sync.Mutex isClose bool isSync bool } // SetValue 设置动态的值 TakeValue 调用 func (value *Value) SetValue(v interface{}) { value.value = v } // Lock value的锁 func (value *Value) Lock() { value.mutex.Lock() } // Unlock value的解锁 func (value *Value) Unlock() { value.mutex.Unlock() } // IsSync 设置是否已经同步的信息. 非使用者调用 func (value *Value) IsSync() bool { return value.isSync } // SetSync 设置是否已经同步的信息. 非使用者调用 func (value *Value) SetSync(is bool) { value.isSync = is } // GetValue 获取value. 带并发锁 func (value *Value) GetValue() interface{} { value.mutex.Lock() defer value.mutex.Unlock() return value.value } // CloseSync 关闭同步 func (value *Value) CloseSync() { value.mutex.Lock() defer value.mutex.Unlock() value.isClose = true } // IsCloseSync 判断是否要关闭同步. 非使用者调用 func (value *Value) IsCloseSync() bool { return value.isClose } // UpdateInterval 每次 TakeValue 休眠的时间. 可覆盖 func (value *Value) UpdateInterval() time.Duration { return time.Second * 5 } // StartSynchronize 开始同步的方法 func StartSynchronize(value IValue) bool { // 判断必要方法是否已经覆盖 if !reflect.ValueOf(value.TakeValue).CanInterface() { panic(errors.New("TakeValue method is need OverWrite")) } // 防止忘记Close内存泄漏 runtime.SetFinalizer(value, func(obj IValue) { obj.CloseSync() }) if value.IsSync() { return false } value.SetValue(value.TakeValue()) go func() { for { time.Sleep(value.UpdateInterval()) tvalue := value.TakeValue() value.Lock() defer value.Unlock() isClose := value.IsCloseSync() // 减少在休眠期间再操作一次, TakeValue if isClose { log.Println(value, "is Closed") break } else { value.SetValue(tvalue) } } }() value.SetSync(true) return true }