diff options
| -rw-r--r-- | lib/msgstore.go | 25 | ||||
| -rw-r--r-- | widgets/msglist.go | 18 | 
2 files changed, 40 insertions, 3 deletions
| diff --git a/lib/msgstore.go b/lib/msgstore.go index 9d537fc..b39d0bb 100644 --- a/lib/msgstore.go +++ b/lib/msgstore.go @@ -2,6 +2,7 @@ package lib  import (  	"io" +	"sync"  	"time"  	"github.com/emersion/go-imap" @@ -9,7 +10,10 @@ import (  	"git.sr.ht/~sircmpwn/aerc2/worker/types"  ) +// Accesses to fields must be guarded by MessageStore.Lock/Unlock  type MessageStore struct { +	sync.Mutex +  	Deleted  map[uint32]interface{}  	DirInfo  types.DirectoryInfo  	Messages map[uint32]*types.MessageInfo @@ -45,6 +49,9 @@ func NewMessageStore(worker *types.Worker,  func (store *MessageStore) FetchHeaders(uids []uint32,  	cb func(*types.MessageInfo)) { +	store.Lock() +	defer store.Unlock() +  	// TODO: this could be optimized by pre-allocating toFetch and trimming it  	// at the end. In practice we expect to get most messages back in one frame.  	var toFetch imap.SeqSet @@ -67,6 +74,9 @@ func (store *MessageStore) FetchHeaders(uids []uint32,  }  func (store *MessageStore) FetchFull(uids []uint32, cb func(io.Reader)) { +	store.Lock() +	defer store.Unlock() +  	// TODO: this could be optimized by pre-allocating toFetch and trimming it  	// at the end. In practice we expect to get most messages back in one frame.  	var toFetch imap.SeqSet @@ -103,8 +113,7 @@ func (store *MessageStore) FetchBodyPart(  	})  } -func (store *MessageStore) merge( -	to *types.MessageInfo, from *types.MessageInfo) { +func merge(to *types.MessageInfo, from *types.MessageInfo) {  	if from.BodyStructure != nil {  		to.BodyStructure = from.BodyStructure @@ -125,6 +134,8 @@ func (store *MessageStore) merge(  }  func (store *MessageStore) Update(msg types.WorkerMessage) { +	store.Lock() +  	update := false  	switch msg := msg.(type) {  	case *types.DirectoryInfo: @@ -144,7 +155,7 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {  		update = true  	case *types.MessageInfo:  		if existing, ok := store.Messages[msg.Uid]; ok && existing != nil { -			store.merge(existing, msg) +			merge(existing, msg)  		} else {  			store.Messages[msg.Uid] = msg  		} @@ -186,6 +197,9 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {  		store.Uids = uids  		update = true  	} + +	store.Unlock() +  	if update {  		store.update()  	} @@ -202,11 +216,16 @@ func (store *MessageStore) update() {  }  func (store *MessageStore) Delete(uids []uint32) { +	store.Lock() +  	var set imap.SeqSet  	for _, uid := range uids {  		set.AddNum(uid)  		store.Deleted[uid] = nil  	} + +	store.Unlock() +  	store.worker.PostAction(&types.DeleteMessages{Uids: set}, nil)  	store.update()  } diff --git a/widgets/msglist.go b/widgets/msglist.go index 4f853f3..eeadec7 100644 --- a/widgets/msglist.go +++ b/widgets/msglist.go @@ -53,6 +53,8 @@ func (ml *MessageList) Draw(ctx *ui.Context) {  		return  	} +	store.Lock() +  	var (  		needsHeaders []uint32  		row          int = 0 @@ -92,6 +94,8 @@ func (ml *MessageList) Draw(ctx *ui.Context) {  			tcell.StyleDefault, "%s", msg)  	} +	store.Unlock() +  	if len(needsHeaders) != 0 {  		store.FetchHeaders(needsHeaders, nil)  		ml.spinner.Start() @@ -109,11 +113,13 @@ func (ml *MessageList) storeUpdate(store *lib.MessageStore) {  		return  	} +	store.Lock()  	if len(store.Uids) > 0 {  		for ml.selected >= len(store.Uids) {  			ml.Prev()  		}  	} +	store.Unlock()  	ml.Invalidate()  } @@ -139,16 +145,25 @@ func (ml *MessageList) Store() *lib.MessageStore {  func (ml *MessageList) Empty() bool {  	store := ml.Store() +	store.Lock() +	defer store.Unlock() +  	return store == nil || len(store.Uids) == 0  }  func (ml *MessageList) Selected() *types.MessageInfo {  	store := ml.Store() +	store.Lock() +	defer store.Unlock() +  	return store.Messages[store.Uids[len(store.Uids)-ml.selected-1]]  }  func (ml *MessageList) Select(index int) {  	store := ml.Store() +	store.Lock() +	defer store.Unlock() +  	ml.selected = index  	for ; ml.selected < 0; ml.selected = len(store.Uids) + ml.selected {  	} @@ -166,6 +181,9 @@ func (ml *MessageList) Select(index int) {  func (ml *MessageList) nextPrev(delta int) {  	store := ml.Store() +	store.Lock() +	defer store.Unlock() +  	if store == nil || len(store.Uids) == 0 {  		return  	} | 
