aboutsummaryrefslogtreecommitdiff
path: root/internal/imap/mailboxes.go
blob: 25bf0875b1a8f1a874e22f98ea9ec2947be8f65e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package imap

import (
	"sync"

	"github.com/emersion/go-imap"
)

type mailboxes struct {
	mb          map[string]*imap.MailboxInfo
	mu          sync.RWMutex
	changeLocks map[string]chan struct{}
}

func (mbs *mailboxes) unlocking(elem Folder) {
	mbs.mu.Lock()
	defer mbs.mu.Unlock()

	ch, ok := mbs.changeLocks[elem.str]
	if !ok {
		panic("Unlocking where nothing is locked")
	}
	close(ch)
	delete(mbs.changeLocks, elem.str)
}

func (mbs *mailboxes) locking(elem Folder) bool {
	mbs.mu.Lock()

	// check again, if the folder has been created in the meantime
	_, ok := mbs.mb[elem.str]
	if ok {
		mbs.mu.Unlock()
		return true
	}

	ch, ok := mbs.changeLocks[elem.str]
	if !ok {
		ch = make(chan struct{})
		mbs.changeLocks[elem.str] = ch
		mbs.mu.Unlock()
		// we created the lock, we are in charge and done here
		return false
	} else {
		// someone else is working, we wait till he's done
		mbs.mu.Unlock() // we are not doing anything...
		<-ch
		return true
	}
}

func (mbs *mailboxes) contains(elem Folder) bool {
	mbs.mu.RLock()
	defer mbs.mu.RUnlock()

	_, ok := mbs.mb[elem.str]
	return ok
}

func (mbs *mailboxes) add(elem *imap.MailboxInfo) {
	mbs.mu.Lock()
	defer mbs.mu.Unlock()

	mbs.mb[elem.Name] = elem
}

func NewMailboxes() *mailboxes {
	return &mailboxes{
		mb:          map[string]*imap.MailboxInfo{},
		changeLocks: map[string]chan struct{}{},
		mu:          sync.RWMutex{},
	}
}