recator: use timer signals instead of shared.Message.TimeLeft

- remove shared.Message.TimeLeft
- modify Timer struct
  - add TimeLeft signal
  - add End and Abort signals
- add syncronised ticker
- update RunPomodoro to use goroutines for timer starts
  - add waitForTimer function
This commit is contained in:
Sebastian Mark 2024-10-25 23:13:06 +02:00
parent aa5c24f06d
commit 3eae584d6d
2 changed files with 44 additions and 22 deletions

View file

@ -9,6 +9,19 @@ import (
var mu sync.Mutex // to synchronize access to shared state
var timer Timer
func waitForTimer(t Timer) bool {
for {
select {
case <-t.End:
return true
case <-t.Abort:
return false
case shared.Message.TimeLeft = <-t.TimeLeft:
// do nothing, just let the timer update the message
}
}
}
// RunPomodoro iterates the Pomodoro work/break sessions.
func RunPomodoro() {
mu.Lock()
@ -24,18 +37,21 @@ func RunPomodoro() {
shared.Message.Session = session
shared.Message.Mode = "Work"
if !timer.Start(pomodoroConfig.Work) {
go timer.Start(pomodoroConfig.Work)
if !waitForTimer(timer) {
break
}
if session > pomodoroConfig.Sessions {
if session < pomodoroConfig.Sessions {
shared.Message.Mode = "ShortBreak"
if !timer.Start(pomodoroConfig.ShortBreak) {
go timer.Start(pomodoroConfig.ShortBreak)
if !waitForTimer(timer) {
break
}
} else { // last phase, prepare for finish
shared.Message.Mode = "LongBreak"
if !timer.Start(pomodoroConfig.LongBreak) {
go timer.Start(pomodoroConfig.LongBreak)
if !waitForTimer(timer) {
break
}
shared.Message.Mode = "End"

View file

@ -1,47 +1,53 @@
package pomodoro
import (
"git.smsvc.net/pomodoro/GoTomato/internal/shared"
"time"
)
type Timer struct {
abort chan bool
wait chan bool
resume chan bool
TimeLeft chan int // time left
End chan bool // signal on successful end
Abort chan bool // signal on premature end
stop chan bool
wait chan bool
resume chan bool
}
func (t Timer) Init() Timer {
return Timer{
abort: make(chan bool, 1),
wait: make(chan bool, 1),
resume: make(chan bool, 1),
TimeLeft: make(chan int),
End: make(chan bool, 1),
Abort: make(chan bool, 1),
stop: make(chan bool, 1),
wait: make(chan bool, 1),
resume: make(chan bool, 1),
}
}
func (t *Timer) Start(duration int) bool {
func (t *Timer) Start(duration int) {
tick := time.NewTicker(time.Second)
for timeLeft := duration; timeLeft > 0; {
select {
case <-t.abort:
return false
case <-t.stop:
t.Abort <- true
return
case <-t.wait:
<-t.resume
default:
shared.Message.TimeLeft = timeLeft
time.Sleep(time.Second)
continue
case <-tick.C:
timeLeft--
default:
t.TimeLeft <- timeLeft
}
}
t.TimeLeft <- 0
// Final shared.Message when time reaches zero
shared.Message.TimeLeft = 0
return true
t.End <- true
}
func (t *Timer) Stop() {
t.resume <- true
t.abort <- true
t.stop <- true
}
func (t *Timer) Pause() {