-
Notifications
You must be signed in to change notification settings - Fork 24
/
atom.go
114 lines (97 loc) · 2.16 KB
/
atom.go
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
package x
import (
"sync"
)
type AtomCache struct {
atoms map[string]Atom
atomNames map[Atom]string
mu sync.RWMutex
}
func (ac *AtomCache) getVal(name string) (val Atom, ok bool) {
ac.mu.RLock()
val, ok = ac.atoms[name]
ac.mu.RUnlock()
return
}
func (ac *AtomCache) getName(val Atom) (name string, ok bool) {
ac.mu.RLock()
name, ok = ac.atomNames[val]
ac.mu.RUnlock()
return
}
func (ac *AtomCache) store(name string, val Atom) {
ac.mu.Lock()
ac.atoms[name] = val
ac.atomNames[val] = name
ac.mu.Unlock()
}
func NewAtomCache() *AtomCache {
ac := &AtomCache{
atoms: make(map[string]Atom),
atomNames: make(map[Atom]string),
}
return ac
}
var defaultAtomCache *AtomCache
var defaultAtomCacheMu sync.Mutex
func (c *Conn) getAtomCache() *AtomCache {
c.atomCacheMu.Lock()
if c.atomCache == nil {
// try default atom cache
defaultAtomCacheMu.Lock()
if defaultAtomCache == nil {
defaultAtomCache = NewAtomCache()
}
c.atomCache = defaultAtomCache
defaultAtomCacheMu.Unlock()
}
v := c.atomCache
c.atomCacheMu.Unlock()
return v
}
func (c *Conn) SetAtomCache(ac *AtomCache) {
c.atomCacheMu.Lock()
c.atomCache = ac
c.atomCacheMu.Unlock()
}
func (c *Conn) GetAtomCache() (ac *AtomCache) {
c.atomCacheMu.Lock()
ac = c.atomCache
c.atomCacheMu.Unlock()
return
}
func (c *Conn) GetAtom(name string) (Atom, error) {
return c.getAtom(false, name)
}
func (c *Conn) GetAtomExisting(name string) (Atom, error) {
return c.getAtom(true, name)
}
func (c *Conn) getAtom(onlyIfExists bool, name string) (Atom, error) {
ac := c.getAtomCache()
val, ok := ac.getVal(name)
if ok {
return val, nil
}
reply, err := InternAtom(c, onlyIfExists, name).Reply(c)
if err != nil {
return AtomNone, err
}
ac.store(name, reply.Atom)
return reply.Atom, nil
}
func (c *Conn) GetAtomName(atom Atom) (string, error) {
ac := c.getAtomCache()
name, ok := ac.getName(atom)
if ok {
return name, nil
}
reply, err := GetAtomName(c, atom).Reply(c)
if err != nil {
return "", err
}
ac.store(reply.Name, atom)
return reply.Name, nil
}