浏览代码

non-blocking timer. Fixes #848

Darien Raymond 7 年之前
父节点
当前提交
ede2c39967
共有 2 个文件被更改,包括 22 次插入2 次删除
  1. 10 2
      common/signal/timer.go
  2. 12 0
      common/signal/timer_test.go

+ 10 - 2
common/signal/timer.go

@@ -12,6 +12,7 @@ type ActivityUpdater interface {
 type ActivityTimer struct {
 	updated chan bool
 	timeout chan time.Duration
+	closing chan bool
 }
 
 func (t *ActivityTimer) Update() {
@@ -22,11 +23,17 @@ func (t *ActivityTimer) Update() {
 }
 
 func (t *ActivityTimer) SetTimeout(timeout time.Duration) {
-	t.timeout <- timeout
+	select {
+	case <-t.closing:
+	case t.timeout <- timeout:
+	}
 }
 
 func (t *ActivityTimer) run(ctx context.Context, cancel context.CancelFunc) {
-	defer cancel()
+	defer func() {
+		cancel()
+		close(t.closing)
+	}()
 
 	timeout := <-t.timeout
 	if timeout == 0 {
@@ -66,6 +73,7 @@ func CancelAfterInactivity(ctx context.Context, cancel context.CancelFunc, timeo
 	timer := &ActivityTimer{
 		timeout: make(chan time.Duration, 1),
 		updated: make(chan bool, 1),
+		closing: make(chan bool),
 	}
 	timer.timeout <- timeout
 	go timer.run(ctx, cancel)

+ 12 - 0
common/signal/timer_test.go

@@ -32,3 +32,15 @@ func TestActivityTimerUpdate(t *testing.T) {
 	assert(ctx.Err(), IsNotNil)
 	runtime.KeepAlive(timer)
 }
+
+func TestActivityTimerNonBlocking(t *testing.T) {
+	assert := With(t)
+
+	ctx, cancel := context.WithCancel(context.Background())
+	timer := CancelAfterInactivity(ctx, cancel, 0)
+	time.Sleep(time.Second * 1)
+	assert(ctx, HasDone)
+	timer.SetTimeout(0)
+	timer.SetTimeout(1)
+	timer.SetTimeout(2)
+}