summaryrefslogtreecommitdiffstats
path: root/pkg/tasks/async_handler.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/tasks/async_handler.go')
-rw-r--r--pkg/tasks/async_handler.go56
1 files changed, 56 insertions, 0 deletions
diff --git a/pkg/tasks/async_handler.go b/pkg/tasks/async_handler.go
new file mode 100644
index 000000000..897efb0e2
--- /dev/null
+++ b/pkg/tasks/async_handler.go
@@ -0,0 +1,56 @@
+package tasks
+
+import (
+ "sync"
+
+ "github.com/jesseduffield/lazygit/pkg/utils"
+)
+
+// the purpose of an AsyncHandler is to ensure that if we have multiple long-running
+// requests, we only handle the result of the latest one. For example, if I am
+// searching for 'abc' and I have to type 'a' then 'b' then 'c' and each keypress
+// dispatches a request to search for things with the string so-far, we'll be searching
+// for 'a', 'ab', and 'abc', and it may be that 'abc' comes back first, then 'ab',
+// then 'a' and we don't want to display the result for 'a' just because it came
+// back last. AsyncHandler keeps track of the order in which things were dispatched
+// so that we can ignore anything that comes back late.
+type AsyncHandler struct {
+ currentId int
+ lastId int
+ mutex sync.Mutex
+ onReject func()
+}
+
+func NewAsyncHandler() *AsyncHandler {
+ return &AsyncHandler{
+ mutex: sync.Mutex{},
+ }
+}
+
+func (self *AsyncHandler) Do(f func() func()) {
+ self.mutex.Lock()
+ self.currentId++
+ id := self.currentId
+ self.mutex.Unlock()
+
+ go utils.Safe(func() {
+ after := f()
+ self.handle(after, id)
+ })
+}
+
+// f here is expected to be a function that doesn't take long to run
+func (self *AsyncHandler) handle(f func(), id int) {
+ self.mutex.Lock()
+ defer self.mutex.Unlock()
+
+ if id < self.lastId {
+ if self.onReject != nil {
+ self.onReject()
+ }
+ return
+ }
+
+ self.lastId = id
+ f()
+}