From baad7da10d78738f7f13b4f3e234d314da8ee49b Mon Sep 17 00:00:00 2001 From: "Alexander \"Arav\" Andreev" Date: Wed, 22 May 2024 04:05:15 +0400 Subject: [PATCH] After a research on how mutexes work, a mutex bcame embedded. And locks should be invoke from outside. --- cmd/dwelling-radio/main.go | 4 ++++ internal/http/dj_handlers.go | 8 ++++++++ internal/radio/listener_counter.go | 18 +----------------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/cmd/dwelling-radio/main.go b/cmd/dwelling-radio/main.go index 95c2cb8..639b101 100644 --- a/cmd/dwelling-radio/main.go +++ b/cmd/dwelling-radio/main.go @@ -62,6 +62,8 @@ func main() { log.Printf("Failed to fetch last N songs: %s\n", err) } + lstnrs.RLock() + defer lstnrs.Unlock() web.Index(¤tSong, lst, *songListLen, lstnrs, r).Render(context.Background(), w) }) @@ -112,6 +114,8 @@ func main() { switch <-sysSignal { case os.Interrupt, syscall.SIGINT, syscall.SIGTERM, syscall.SIGABRT, syscall.SIGSEGV: if currentSong.Artist != "" { + lstnrs.Lock() + defer lstnrs.Unlock() currentSong.Listeners, currentSong.PeakListeners = lstnrs.Reset() if err := stats.Add(¤tSong); err != nil { log.Println("failed to save a current song during a shutdown:", err) diff --git a/internal/http/dj_handlers.go b/internal/http/dj_handlers.go index 90c0791..575af65 100644 --- a/internal/http/dj_handlers.go +++ b/internal/http/dj_handlers.go @@ -42,8 +42,12 @@ func (dj *DJHandlers) ListenersUpdateIcecast(w http.ResponseWriter, r *http.Requ switch r.FormValue("action") { case "listener_add": + dj.listeners.Lock() _ = dj.listeners.Inc() + dj.listeners.Unlock() case "listener_remove": + dj.listeners.Lock() + defer dj.listeners.Unlock() if _, err := dj.listeners.Dec(); err != nil { log.Println("DJHandlers.ListenersUpdateIcecast:", err) w.WriteHeader(http.StatusBadRequest) @@ -107,7 +111,9 @@ func (dj *DJHandlers) PlaylistNext(w http.ResponseWriter, _ *http.Request) { newSong.Artist = "Nothing to play. Playing a fallback: " + newSong.Artist } + dj.listeners.Lock() dj.curSong.Listeners, dj.curSong.PeakListeners = dj.listeners.Reset() + dj.listeners.Unlock() if dj.curSong.Artist != "" && !strings.Contains(dj.curSong.Artist, "no artist tag") && !strings.Contains(dj.curSong.Artist, "No title tag") { @@ -131,6 +137,8 @@ func (dj *DJHandlers) Status(w http.ResponseWriter, r *http.Request) { log.Println("failed to fetch last n songs:", err) } + dj.listeners.RLock() + defer dj.listeners.Unlock() err = json.NewEncoder(w).Encode(&struct { Current *radio.Song `json:"current_song,omitempty"` Listeners int64 `json:"listeners"` diff --git a/internal/radio/listener_counter.go b/internal/radio/listener_counter.go index 298c007..e30e620 100644 --- a/internal/radio/listener_counter.go +++ b/internal/radio/listener_counter.go @@ -9,7 +9,7 @@ import ( // ListenerCounter stores the current, overall and peak numbers of listeners. type ListenerCounter struct { - mutex sync.RWMutex + sync.RWMutex current, peak int64 overall, cur_peak int64 } @@ -21,36 +21,26 @@ func NewListenerCounter() *ListenerCounter { // Current returns a number of current listeners. func (l *ListenerCounter) Current() int64 { - l.mutex.RLock() - defer l.mutex.RUnlock() return l.current } // Peak returns a peak number of listeners. func (l *ListenerCounter) Peak() int64 { - l.mutex.RLock() - defer l.mutex.RUnlock() return l.peak } // CurrentPeak returns a peak number of listeners for a currently playing song. func (l *ListenerCounter) CurrentPeak() int64 { - l.mutex.RLock() - defer l.mutex.RUnlock() return l.cur_peak } // Overall returns an overall number of listeners for a currently playing song. func (l *ListenerCounter) Overall() int64 { - l.mutex.RLock() - defer l.mutex.RUnlock() return l.overall } // Inc increments by 1 a current number of listeners and updates a peak number. func (l *ListenerCounter) Inc() int64 { - l.mutex.Lock() - defer l.mutex.Unlock() if l.current == math.MaxInt64 { // We panic here because if this will ever happen, then something's going certainly wrong. panic("a current number of listeners exceeded MaxInt64") @@ -72,8 +62,6 @@ func (l *ListenerCounter) Inc() int64 { // Dec decrements by 1 a current number of listeners. An error will occur if // a resulting number is less than 0. func (l *ListenerCounter) Dec() (int64, error) { - l.mutex.Lock() - defer l.mutex.Unlock() if l.current == 0 { return l.current, errors.New("an attempt to decrement a number of current listeners down to less than 0") } @@ -84,8 +72,6 @@ func (l *ListenerCounter) Dec() (int64, error) { // Reset current peak and overall listeners for a song that is playing. // And return its values. func (l *ListenerCounter) Reset() (overall, peak int64) { - l.mutex.Lock() - defer l.mutex.Unlock() peak = l.cur_peak l.cur_peak = l.current overall = l.overall @@ -94,8 +80,6 @@ func (l *ListenerCounter) Reset() (overall, peak int64) { } func (l *ListenerCounter) MarshalJSON() ([]byte, error) { - l.mutex.RLock() - defer l.mutex.RUnlock() return json.Marshal(&struct { Current int64 `json:"current"` Peak int64 `json:"peak"`