From 1bd85d8bafbd11ddc3d4eacfad8bc7576eac0df8 Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Sun, 3 May 2015 14:18:32 +0200 Subject: [PATCH] Use a channel instead of locks --- internal/model/rofolder.go | 35 ++++++++++++++++------------------- internal/model/rwfolder.go | 23 ++++++----------------- 2 files changed, 22 insertions(+), 36 deletions(-) diff --git a/internal/model/rofolder.go b/internal/model/rofolder.go index 76c928dd8..ae97d3a5a 100644 --- a/internal/model/rofolder.go +++ b/internal/model/rofolder.go @@ -17,12 +17,12 @@ import ( type roFolder struct { stateTracker - folder string - intv time.Duration - timer *time.Timer - tmut sync.Mutex // protects timer - model *Model - stop chan struct{} + folder string + intv time.Duration + timer *time.Timer + model *Model + stop chan struct{} + delayScan chan time.Duration } func newROFolder(model *Model, folder string, interval time.Duration) *roFolder { @@ -31,12 +31,12 @@ func newROFolder(model *Model, folder string, interval time.Duration) *roFolder folder: folder, mut: sync.NewMutex(), }, - folder: folder, - intv: interval, - timer: time.NewTimer(time.Millisecond), - tmut: sync.NewMutex(), - model: model, - stop: make(chan struct{}), + folder: folder, + intv: interval, + timer: time.NewTimer(time.Millisecond), + model: model, + stop: make(chan struct{}), + delayScan: make(chan time.Duration), } } @@ -47,17 +47,13 @@ func (s *roFolder) Serve() { } defer func() { - s.tmut.Lock() s.timer.Stop() - s.tmut.Unlock() }() reschedule := func() { // Sleep a random time between 3/4 and 5/4 of the configured interval. sleepNanos := (s.intv.Nanoseconds()*3 + rand.Int63n(2*s.intv.Nanoseconds())) / 4 - s.tmut.Lock() s.timer.Reset(time.Duration(sleepNanos) * time.Nanosecond) - s.tmut.Unlock() } initialScanCompleted := false @@ -97,6 +93,9 @@ func (s *roFolder) Serve() { } reschedule() + + case next := <-s.delayScan: + s.timer.Reset(next) } } } @@ -116,7 +115,5 @@ func (s *roFolder) Jobs() ([]string, []string) { } func (s *roFolder) DelayScan(next time.Duration) { - s.tmut.Lock() - s.timer.Reset(next) - s.tmut.Unlock() + s.delayScan <- next } diff --git a/internal/model/rwfolder.go b/internal/model/rwfolder.go index 07849483d..6fc103399 100644 --- a/internal/model/rwfolder.go +++ b/internal/model/rwfolder.go @@ -76,7 +76,7 @@ type rwFolder struct { dbUpdates chan protocol.FileInfo scanTimer *time.Timer pullTimer *time.Timer - tmut sync.Mutex // protects scanTimer and pullTimer + delayScan chan time.Duration } func newRWFolder(m *Model, shortID uint64, cfg config.FolderConfiguration) *rwFolder { @@ -103,7 +103,7 @@ func newRWFolder(m *Model, shortID uint64, cfg config.FolderConfiguration) *rwFo queue: newJobQueue(), pullTimer: time.NewTimer(checkPullIntv), scanTimer: time.NewTimer(time.Millisecond), // The first scan should be done immediately. - tmut: sync.NewMutex(), + delayScan: make(chan time.Duration), } } @@ -116,10 +116,8 @@ func (p *rwFolder) Serve() { } defer func() { - p.tmut.Lock() p.pullTimer.Stop() p.scanTimer.Stop() - p.tmut.Unlock() // TODO: Should there be an actual FolderStopped state? p.setState(FolderIdle) }() @@ -140,9 +138,7 @@ func (p *rwFolder) Serve() { if debug { l.Debugln(p, "next rescan in", intv) } - p.tmut.Lock() p.scanTimer.Reset(intv) - p.tmut.Unlock() } // We don't start pulling files until a scan has been completed. @@ -163,9 +159,7 @@ func (p *rwFolder) Serve() { if debug { l.Debugln(p, "skip (initial)") } - p.tmut.Lock() p.pullTimer.Reset(nextPullIntv) - p.tmut.Unlock() continue } @@ -189,9 +183,7 @@ func (p *rwFolder) Serve() { if debug { l.Debugln(p, "skip (curVer == prevVer)", prevVer) } - p.tmut.Lock() p.pullTimer.Reset(checkPullIntv) - p.tmut.Unlock() continue } @@ -229,9 +221,7 @@ func (p *rwFolder) Serve() { if debug { l.Debugln(p, "next pull in", nextPullIntv) } - p.tmut.Lock() p.pullTimer.Reset(nextPullIntv) - p.tmut.Unlock() break } @@ -244,9 +234,7 @@ func (p *rwFolder) Serve() { if debug { l.Debugln(p, "next pull in", pauseIntv) } - p.tmut.Lock() p.pullTimer.Reset(pauseIntv) - p.tmut.Unlock() break } } @@ -283,6 +271,9 @@ func (p *rwFolder) Serve() { l.Infoln("Completed initial scan (rw) of folder", p.folder) initialScanCompleted = true } + + case next := <-p.delayScan: + p.scanTimer.Reset(next) } } } @@ -1181,9 +1172,7 @@ func (p *rwFolder) Jobs() ([]string, []string) { } func (p *rwFolder) DelayScan(next time.Duration) { - p.tmut.Lock() - p.scanTimer.Reset(next) - p.tmut.Unlock() + p.delayScan <- next } // dbUpdaterRoutine aggregates db updates and commits them in batches no