[tor-commits] [snowflake/main] Port V2Ray periodic task standard library to snowflake

meskio at torproject.org meskio at torproject.org
Tue Nov 16 19:37:40 UTC 2021


commit 4c8a16617873bcf637d14674f0c0f985303f4d1f
Author: Shelikhoo <xiaokangwang at outlook.com>
Date:   Thu Nov 4 20:21:59 2021 +0000

    Port V2Ray periodic task standard library to snowflake
    
    This is a mature implementation of periodic task that run a function at given interval. It allows task to be stopped, and deals with edge case like interval too short gracefully.
    
    V2Ray/V2Fly is MIT licensed.
---
 common/task/periodic.go | 85 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 85 insertions(+)

diff --git a/common/task/periodic.go b/common/task/periodic.go
new file mode 100644
index 0000000..6abe41a
--- /dev/null
+++ b/common/task/periodic.go
@@ -0,0 +1,85 @@
+package task
+
+import (
+	"sync"
+	"time"
+)
+
+// Periodic is a task that runs periodically.
+type Periodic struct {
+	// Interval of the task being run
+	Interval time.Duration
+	// Execute is the task function
+	Execute func() error
+
+	access  sync.Mutex
+	timer   *time.Timer
+	running bool
+}
+
+func (t *Periodic) hasClosed() bool {
+	t.access.Lock()
+	defer t.access.Unlock()
+
+	return !t.running
+}
+
+func (t *Periodic) checkedExecute() error {
+	if t.hasClosed() {
+		return nil
+	}
+
+	if err := t.Execute(); err != nil {
+		t.access.Lock()
+		t.running = false
+		t.access.Unlock()
+		return err
+	}
+
+	t.access.Lock()
+	defer t.access.Unlock()
+
+	if !t.running {
+		return nil
+	}
+
+	t.timer = time.AfterFunc(t.Interval, func() {
+		t.checkedExecute()
+	})
+
+	return nil
+}
+
+// Start implements common.Runnable.
+func (t *Periodic) Start() error {
+	t.access.Lock()
+	if t.running {
+		t.access.Unlock()
+		return nil
+	}
+	t.running = true
+	t.access.Unlock()
+
+	if err := t.checkedExecute(); err != nil {
+		t.access.Lock()
+		t.running = false
+		t.access.Unlock()
+		return err
+	}
+
+	return nil
+}
+
+// Close implements common.Closable.
+func (t *Periodic) Close() error {
+	t.access.Lock()
+	defer t.access.Unlock()
+
+	t.running = false
+	if t.timer != nil {
+		t.timer.Stop()
+		t.timer = nil
+	}
+
+	return nil
+}





More information about the tor-commits mailing list