@@ -37,27 +37,38 @@ import (
3737)
3838
3939const (
40- w = 5
40+ // w controls the number of branches at a node (2^w branches).
41+ w = 5
42+
43+ // exp2 is 2^w, which is the hashcode space.
4144 exp2 = 32
4245)
4346
47+ // Ctrie is a concurrent, lock-free hash trie. By default, keys are hashed
48+ // using FNV-1a, but the hashing function used can be set with SetHash.
4449type Ctrie struct {
4550 root * iNode
4651 h hash.Hash32
4752 hMu sync.Mutex
4853}
4954
55+ // iNode is an indirection node. I-nodes remain present in the Ctrie even as
56+ // nodes above and below change. Thread-safety is achieved in part by
57+ // performing CAS operations on the I-node instead of the internal node array.
5058type iNode struct {
5159 main * mainNode
5260}
5361
54- // mainNode is either a cNode, tNode, or lNode.
62+ // mainNode is either a cNode, tNode, or lNode which makes up an I-node .
5563type mainNode struct {
5664 cNode * cNode
5765 tNode * tNode
5866 lNode * lNode
5967}
6068
69+ // cNode is an internal main node containing a bitmap and the array with
70+ // references to branch nodes. A branch node is either another I-node or a
71+ // singleton S-node.
6172type cNode struct {
6273 bmp uint32
6374 array []branch
@@ -135,23 +146,31 @@ func (c *cNode) removed(pos, flag uint32) *cNode {
135146 return ncn
136147}
137148
149+ // tNode is tomb node which is a special node used to ensure proper ordering
150+ // during removals.
138151type tNode struct {
139152 * sNode
140153}
141154
155+ // untombed returns the S-node contained by the T-node.
142156func (t * tNode ) untombed () * sNode {
143157 return & sNode {& entry {key : t .key , hash : t .hash , value : t .value }}
144158}
145159
160+ // lNode is a list node which is a leaf node used to handle hashcode
161+ // collisions by keeping such keys in a persistent list.
146162type lNode struct {
147163 list.PersistentList
148164}
149165
166+ // entry returns the first S-node contained in the L-node.
150167func (l * lNode ) entry () * sNode {
151168 head , _ := l .Head ()
152169 return head .(* sNode )
153170}
154171
172+ // lookup returns the value at the given entry in the L-node or returns false
173+ // if it's not contained.
155174func (l * lNode ) lookup (e * entry ) (interface {}, bool ) {
156175 found , ok := l .Find (func (sn interface {}) bool {
157176 return bytes .Equal (e .key , sn .(* sNode ).key )
@@ -162,10 +181,12 @@ func (l *lNode) lookup(e *entry) (interface{}, bool) {
162181 return found .(* sNode ).value , true
163182}
164183
184+ // inserted creates a new L-node with the added entry.
165185func (l * lNode ) inserted (entry * entry ) * lNode {
166186 return & lNode {l .Add (& sNode {entry })}
167187}
168188
189+ // removed creates a new L-node with the entry removed.
169190func (l * lNode ) removed (e * entry ) * lNode {
170191 idx := l .FindIndex (func (sn interface {}) bool {
171192 return bytes .Equal (e .key , sn .(* sNode ).key )
@@ -177,34 +198,45 @@ func (l *lNode) removed(e *entry) *lNode {
177198 return & lNode {nl }
178199}
179200
201+ // length returns the L-node list length.
180202func (l * lNode ) length () uint {
181203 return l .Length ()
182204}
183205
184206// branch is either an iNode or sNode.
185207type branch interface {}
186208
209+ // entry contains a Ctrie entry, which is also a technique used to cache the
210+ // hashcode of the key.
187211type entry struct {
188212 key []byte
189213 hash uint32
190214 value interface {}
191215}
192216
217+ // sNode is a singleton node which contains a single key and value.
193218type sNode struct {
194219 * entry
195220}
196221
222+ // New creates an empty Ctrie, defaulting to FNV-1a for key hashing. Use
223+ // SetHash to change the hash function.
197224func New () * Ctrie {
198225 root := & iNode {main : & mainNode {cNode : & cNode {}}}
199226 return & Ctrie {root : root , h : fnv .New32a ()}
200227}
201228
229+ // SetHash sets the hash function used by the Ctrie. Existing entries are not
230+ // rehashed when this is set, so this should be called on a newly created
231+ // Ctrie.
202232func (c * Ctrie ) SetHash (hash hash.Hash32 ) {
203233 c .hMu .Lock ()
204234 c .h = hash
205235 c .hMu .Unlock ()
206236}
207237
238+ // Insert adds the key-value pair to the Ctrie, replacing the existing value if
239+ // the key already exists.
208240func (c * Ctrie ) Insert (key []byte , value interface {}) {
209241 c .insert (& entry {
210242 key : key ,
@@ -213,10 +245,14 @@ func (c *Ctrie) Insert(key []byte, value interface{}) {
213245 })
214246}
215247
248+ // Lookup returns the value for the associated key or returns false if the key
249+ // doesn't exist.
216250func (c * Ctrie ) Lookup (key []byte ) (interface {}, bool ) {
217251 return c .lookup (& entry {key : key , hash : c .hash (key )})
218252}
219253
254+ // Remove deletes the value for the associated key, returning true if it was
255+ // removed or false if the entry doesn't exist.
220256func (c * Ctrie ) Remove (key []byte ) (interface {}, bool ) {
221257 return c .remove (& entry {key : key , hash : c .hash (key )})
222258}
0 commit comments