100 lines
3.6 KiB
Go
100 lines
3.6 KiB
Go
package incrementor
|
||
|
||
import (
|
||
"math"
|
||
"sync"
|
||
)
|
||
|
||
type (
|
||
// Incrementor является инкрементным числом с настройками поведения, вроде максимально допустимого значения.
|
||
Incrementor struct {
|
||
// NOTE(toby3d): защита чтения/записи числа в горутинах
|
||
mutex *sync.RWMutex
|
||
|
||
// NOTE(toby3d): непосредственно само инкрементное число
|
||
number int64
|
||
|
||
// NOTE(toby3d): максимально допустимое значение инкрементного числа, по достижении которого оно будет
|
||
// сброшено в 0
|
||
maxValue int64
|
||
}
|
||
|
||
// Reader описывает действия для чтения текущего значения числа.
|
||
Reader interface {
|
||
GetNumber() int64
|
||
}
|
||
|
||
// Writer описывает действия для изменения значения числа и управления его максимально допустимым значением.
|
||
Writer interface {
|
||
IncrementNumber()
|
||
SetMaximumValue(maximumValue int)
|
||
}
|
||
|
||
// Incrementer описывает поведение менеджера инкрементного числа.
|
||
Incrementer interface {
|
||
Reader
|
||
Writer
|
||
}
|
||
)
|
||
|
||
// DefaultMaximumValue содержит максимально возможное значение числа по-умолчанию в битах.
|
||
const DefaultMaximumValue = math.MaxInt64
|
||
|
||
// New создаёт новую структуру для хранения и управления инкрементным числом.
|
||
//
|
||
// NOTE(toby3d): в тестовом задании нет сведений по тому возможно ли изменение параметров на этапе инициализации, как
|
||
// например отсчёт не с 0 или перезапись максимального порога без отдельного вызова SetMaximumValue. 🤷♂
|
||
func New() *Incrementor {
|
||
i := new(Incrementor)
|
||
i.number = 0
|
||
i.mutex = new(sync.RWMutex)
|
||
i.maxValue = DefaultMaximumValue
|
||
|
||
return i
|
||
}
|
||
|
||
// GetNumber возвращает текущее число.
|
||
func (i *Incrementor) GetNumber() int64 {
|
||
i.mutex.RLock()
|
||
defer i.mutex.RUnlock()
|
||
|
||
return i.number
|
||
}
|
||
|
||
// IncrementNumber увеличивает текущее число на 1.
|
||
//
|
||
// Если в процессе выполнения метода число будет >= максимально допустимого порога, то оно будет сброшено в 0.
|
||
func (i *Incrementor) IncrementNumber() {
|
||
i.mutex.Lock()
|
||
|
||
i.number++
|
||
|
||
if i.number >= i.maxValue {
|
||
i.number = 0
|
||
}
|
||
|
||
i.mutex.Unlock()
|
||
}
|
||
|
||
// SetMaximumValue устанавливает максимально возможное значение для числа. По достижении или превышении указанного
|
||
// порога число будет сброшено в 0.
|
||
//
|
||
// Вводимое значение не может быть меньше 0 и больше DefaultMaximumValue.
|
||
func (i *Incrementor) SetMaximumValue(maximumValue int64) {
|
||
// NOTE(toby3d): предварительно проверяем ввод, косячный сбрасываем в значение по-умолчанию.
|
||
if maximumValue <= 0 || maximumValue > DefaultMaximumValue {
|
||
maximumValue = DefaultMaximumValue
|
||
}
|
||
|
||
i.mutex.Lock()
|
||
|
||
i.maxValue = maximumValue
|
||
|
||
// NOTE(toby3d): если максимум оказывается меньше текущего значения, то сбрасываем число в 0.
|
||
if i.number >= i.maxValue {
|
||
i.number = 0
|
||
}
|
||
|
||
i.mutex.Unlock()
|
||
}
|