diff options
Diffstat (limited to 'pkg/tasks/async_handler.go')
-rw-r--r-- | pkg/tasks/async_handler.go | 56 |
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() +} |