You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

btree.go 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938
  1. // Copyright 2020 Joshua J Baker. All rights reserved.
  2. // Use of this source code is governed by an MIT-style
  3. // license that can be found in the LICENSE file.
  4. package btree
  5. import (
  6. "sync"
  7. )
  8. const maxItems = 255 // max items per node. max children is +1
  9. const minItems = maxItems * 40 / 100
  10. type cow struct {
  11. _ int // it cannot be an empty struct
  12. }
  13. type node struct {
  14. cow *cow
  15. leaf bool
  16. numItems int16
  17. count int
  18. items [maxItems]interface{}
  19. children *[maxItems + 1]*node
  20. }
  21. // BTree is an ordered set items
  22. type BTree struct {
  23. mu *sync.RWMutex
  24. cow *cow
  25. root *node
  26. count int
  27. less func(a, b interface{}) bool
  28. locks bool
  29. }
  30. func (tr *BTree) newNode(leaf bool) *node {
  31. n := &node{leaf: leaf}
  32. if !leaf {
  33. n.children = new([maxItems + 1]*node)
  34. }
  35. n.cow = tr.cow
  36. return n
  37. }
  38. // PathHint is a utility type used with the *Hint() functions. Hints provide
  39. // faster operations for clustered keys.
  40. type PathHint struct {
  41. used [8]bool
  42. path [8]uint8
  43. }
  44. // New returns a new BTree
  45. func New(less func(a, b interface{}) bool) *BTree {
  46. return newBTree(less, true)
  47. }
  48. // NewNonConcurrent returns a new BTree which is not safe for concurrent
  49. // write operations by multiple goroutines.
  50. //
  51. // This is useful for when you do not need the BTree to manage the locking,
  52. // but would rather do it yourself.
  53. func NewNonConcurrent(less func(a, b interface{}) bool) *BTree {
  54. return newBTree(less, false)
  55. }
  56. func newBTree(less func(a, b interface{}) bool, locks bool) *BTree {
  57. if less == nil {
  58. panic("nil less")
  59. }
  60. tr := new(BTree)
  61. tr.mu = new(sync.RWMutex)
  62. tr.less = less
  63. tr.locks = locks
  64. return tr
  65. }
  66. // Less is a convenience function that performs a comparison of two items
  67. // using the same "less" function provided to New.
  68. func (tr *BTree) Less(a, b interface{}) bool {
  69. return tr.less(a, b)
  70. }
  71. func (n *node) find(key interface{}, less func(a, b interface{}) bool,
  72. hint *PathHint, depth int,
  73. ) (index int16, found bool) {
  74. low := int16(0)
  75. high := n.numItems - 1
  76. if hint != nil && depth < 8 && hint.used[depth] {
  77. index = int16(hint.path[depth])
  78. if index >= n.numItems {
  79. // tail item
  80. if less(n.items[n.numItems-1], key) {
  81. if less(key, n.items[n.numItems-1]) {
  82. index = n.numItems - 1
  83. found = true
  84. goto path_match
  85. } else {
  86. index = n.numItems
  87. goto path_match
  88. }
  89. }
  90. index = n.numItems - 1
  91. }
  92. if less(key, n.items[index]) {
  93. if index == 0 || less(n.items[index-1], key) {
  94. goto path_match
  95. }
  96. high = index - 1
  97. } else if less(n.items[index], key) {
  98. low = index + 1
  99. } else {
  100. found = true
  101. goto path_match
  102. }
  103. }
  104. for low <= high {
  105. mid := low + ((high+1)-low)/2
  106. if !less(key, n.items[mid]) {
  107. low = mid + 1
  108. } else {
  109. high = mid - 1
  110. }
  111. }
  112. if low > 0 && !less(n.items[low-1], key) {
  113. index = low - 1
  114. found = true
  115. } else {
  116. index = low
  117. found = false
  118. }
  119. if hint == nil || depth >= 8 {
  120. return index, found
  121. }
  122. path_match:
  123. hint.used[depth] = true
  124. if n.leaf && found {
  125. hint.path[depth] = byte(index + 1)
  126. } else {
  127. hint.path[depth] = byte(index)
  128. }
  129. return index, found
  130. }
  131. // SetHint sets or replace a value for a key using a path hint
  132. func (tr *BTree) SetHint(item interface{}, hint *PathHint) (prev interface{}) {
  133. if item == nil {
  134. panic("nil item")
  135. }
  136. if tr.lock() {
  137. defer tr.unlock()
  138. }
  139. return tr.setHint(item, hint)
  140. }
  141. func (tr *BTree) setHint(item interface{}, hint *PathHint) (prev interface{}) {
  142. if tr.root == nil {
  143. tr.root = tr.newNode(true)
  144. tr.root.items[0] = item
  145. tr.root.numItems = 1
  146. tr.root.count = 1
  147. tr.count = 1
  148. return
  149. }
  150. prev = tr.nodeSet(&tr.root, item, tr.less, hint, 0)
  151. if prev != nil {
  152. return prev
  153. }
  154. if tr.root.numItems == maxItems {
  155. n := tr.cowLoad(&tr.root)
  156. right, median := tr.nodeSplit(n)
  157. tr.root = tr.newNode(false)
  158. tr.root.children[0] = n
  159. tr.root.items[0] = median
  160. tr.root.children[1] = right
  161. tr.root.numItems = 1
  162. tr.root.count = n.count + 1 + right.count
  163. }
  164. tr.count++
  165. return prev
  166. }
  167. // Set or replace a value for a key
  168. func (tr *BTree) Set(item interface{}) (prev interface{}) {
  169. return tr.SetHint(item, nil)
  170. }
  171. func (tr *BTree) nodeSplit(n *node) (right *node, median interface{}) {
  172. right = tr.newNode(n.leaf)
  173. median = n.items[maxItems/2]
  174. copy(right.items[:maxItems/2], n.items[maxItems/2+1:])
  175. if !n.leaf {
  176. copy(right.children[:maxItems/2+1], n.children[maxItems/2+1:])
  177. }
  178. right.numItems = maxItems / 2
  179. if !n.leaf {
  180. for i := maxItems/2 + 1; i < maxItems+1; i++ {
  181. n.children[i] = nil
  182. }
  183. }
  184. for i := maxItems / 2; i < maxItems; i++ {
  185. n.items[i] = nil
  186. }
  187. n.numItems = maxItems / 2
  188. // update counts
  189. n.updateCount()
  190. right.updateCount()
  191. return right, median
  192. }
  193. func (n *node) updateCount() {
  194. n.count = int(n.numItems)
  195. if !n.leaf {
  196. for i := 0; i <= int(n.numItems); i++ {
  197. n.count += n.children[i].count
  198. }
  199. }
  200. }
  201. // This operation should not be inlined because it's expensive and rarely
  202. // called outside of heavy copy-on-write situations. Marking it "noinline"
  203. // allows for the parent cowLoad to be inlined.
  204. // go:noinline
  205. func (tr *BTree) copy(n *node) *node {
  206. n2 := *n
  207. n2.cow = tr.cow
  208. copy(n2.items[:], n.items[:])
  209. if n.children != nil {
  210. n2.children = new([maxItems + 1]*node)
  211. copy(n2.children[:], n.children[:])
  212. }
  213. return &n2
  214. }
  215. // cowLoad loads the provide node and, if needed, performs a copy-on-write.
  216. func (tr *BTree) cowLoad(cn **node) *node {
  217. if (*cn).cow != tr.cow {
  218. *cn = tr.copy(*cn)
  219. }
  220. return *cn
  221. }
  222. func (tr *BTree) nodeSet(cn **node, item interface{},
  223. less func(a, b interface{}) bool, hint *PathHint, depth int,
  224. ) (prev interface{}) {
  225. n := tr.cowLoad(cn)
  226. i, found := n.find(item, less, hint, depth)
  227. if found {
  228. prev = n.items[i]
  229. n.items[i] = item
  230. return prev
  231. }
  232. if n.leaf {
  233. copy(n.items[i+1:n.numItems+1], n.items[i:n.numItems])
  234. n.items[i] = item
  235. n.numItems++
  236. n.count++
  237. return nil
  238. }
  239. prev = tr.nodeSet(&n.children[i], item, less, hint, depth+1)
  240. if prev != nil {
  241. return prev
  242. }
  243. if n.children[i].numItems == maxItems {
  244. right, median := tr.nodeSplit(n.children[i])
  245. copy(n.children[i+1:], n.children[i:])
  246. copy(n.items[i+1:], n.items[i:])
  247. n.items[i] = median
  248. n.children[i+1] = right
  249. n.numItems++
  250. }
  251. n.count++
  252. return nil
  253. }
  254. func (n *node) scan(iter func(item interface{}) bool) bool {
  255. if n.leaf {
  256. for i := int16(0); i < n.numItems; i++ {
  257. if !iter(n.items[i]) {
  258. return false
  259. }
  260. }
  261. return true
  262. }
  263. for i := int16(0); i < n.numItems; i++ {
  264. if !n.children[i].scan(iter) {
  265. return false
  266. }
  267. if !iter(n.items[i]) {
  268. return false
  269. }
  270. }
  271. return n.children[n.numItems].scan(iter)
  272. }
  273. // Get a value for key
  274. func (tr *BTree) Get(key interface{}) interface{} {
  275. // This operation is basically the same as calling:
  276. // return tr.GetHint(key, nil)
  277. // But here we inline the bsearch to avoid the hint logic and extra
  278. // function call.
  279. if tr.rlock() {
  280. defer tr.runlock()
  281. }
  282. if tr.root == nil || key == nil {
  283. return nil
  284. }
  285. depth := 0
  286. n := tr.root
  287. for {
  288. low := int16(0)
  289. high := n.numItems - 1
  290. for low <= high {
  291. mid := low + ((high+1)-low)/2
  292. if !tr.less(key, n.items[mid]) {
  293. low = mid + 1
  294. } else {
  295. high = mid - 1
  296. }
  297. }
  298. if low > 0 && !tr.less(n.items[low-1], key) {
  299. return n.items[low-1]
  300. }
  301. if n.leaf {
  302. return nil
  303. }
  304. n = n.children[low]
  305. depth++
  306. }
  307. }
  308. // GetHint gets a value for key using a path hint
  309. func (tr *BTree) GetHint(key interface{}, hint *PathHint) interface{} {
  310. if tr.rlock() {
  311. defer tr.runlock()
  312. }
  313. if tr.root == nil || key == nil {
  314. return nil
  315. }
  316. depth := 0
  317. n := tr.root
  318. for {
  319. index, found := n.find(key, tr.less, hint, depth)
  320. if found {
  321. return n.items[index]
  322. }
  323. if n.leaf {
  324. return nil
  325. }
  326. n = n.children[index]
  327. depth++
  328. }
  329. }
  330. // Len returns the number of items in the tree
  331. func (tr *BTree) Len() int {
  332. return tr.count
  333. }
  334. // Delete a value for a key
  335. func (tr *BTree) Delete(key interface{}) interface{} {
  336. return tr.DeleteHint(key, nil)
  337. }
  338. // DeleteHint deletes a value for a key using a path hint
  339. func (tr *BTree) DeleteHint(key interface{}, hint *PathHint) interface{} {
  340. if tr.lock() {
  341. defer tr.unlock()
  342. }
  343. return tr.deleteHint(key, hint)
  344. }
  345. func (tr *BTree) deleteHint(key interface{}, hint *PathHint) interface{} {
  346. if tr.root == nil || key == nil {
  347. return nil
  348. }
  349. prev := tr.delete(&tr.root, false, key, tr.less, hint, 0)
  350. if prev == nil {
  351. return nil
  352. }
  353. if tr.root.numItems == 0 && !tr.root.leaf {
  354. tr.root = tr.root.children[0]
  355. }
  356. tr.count--
  357. if tr.count == 0 {
  358. tr.root = nil
  359. }
  360. return prev
  361. }
  362. func (tr *BTree) delete(cn **node, max bool, key interface{},
  363. less func(a, b interface{}) bool, hint *PathHint, depth int,
  364. ) interface{} {
  365. n := tr.cowLoad(cn)
  366. var i int16
  367. var found bool
  368. if max {
  369. i, found = n.numItems-1, true
  370. } else {
  371. i, found = n.find(key, less, hint, depth)
  372. }
  373. if n.leaf {
  374. if found {
  375. prev := n.items[i]
  376. // found the items at the leaf, remove it and return.
  377. copy(n.items[i:], n.items[i+1:n.numItems])
  378. n.items[n.numItems-1] = nil
  379. n.numItems--
  380. n.count--
  381. return prev
  382. }
  383. return nil
  384. }
  385. var prev interface{}
  386. if found {
  387. if max {
  388. i++
  389. prev = tr.delete(&n.children[i], true, "", less, nil, 0)
  390. } else {
  391. prev = n.items[i]
  392. maxItem := tr.delete(&n.children[i], true, "", less, nil, 0)
  393. n.items[i] = maxItem
  394. }
  395. } else {
  396. prev = tr.delete(&n.children[i], max, key, less, hint, depth+1)
  397. }
  398. if prev == nil {
  399. return nil
  400. }
  401. n.count--
  402. if n.children[i].numItems >= minItems {
  403. return prev
  404. }
  405. // merge / rebalance nodes
  406. if i == n.numItems {
  407. i--
  408. }
  409. n.children[i] = tr.cowLoad(&n.children[i])
  410. n.children[i+1] = tr.cowLoad(&n.children[i+1])
  411. if n.children[i].numItems+n.children[i+1].numItems+1 < maxItems {
  412. // merge left + item + right
  413. n.children[i].items[n.children[i].numItems] = n.items[i]
  414. copy(n.children[i].items[n.children[i].numItems+1:],
  415. n.children[i+1].items[:n.children[i+1].numItems])
  416. if !n.children[0].leaf {
  417. copy(n.children[i].children[n.children[i].numItems+1:],
  418. n.children[i+1].children[:n.children[i+1].numItems+1])
  419. }
  420. n.children[i].numItems += n.children[i+1].numItems + 1
  421. n.children[i].count += n.children[i+1].count + 1
  422. copy(n.items[i:], n.items[i+1:n.numItems])
  423. copy(n.children[i+1:], n.children[i+2:n.numItems+1])
  424. n.items[n.numItems-1] = nil
  425. n.children[n.numItems] = nil
  426. n.numItems--
  427. } else if n.children[i].numItems > n.children[i+1].numItems {
  428. // move left -> right
  429. copy(n.children[i+1].items[1:],
  430. n.children[i+1].items[:n.children[i+1].numItems])
  431. if !n.children[0].leaf {
  432. copy(n.children[i+1].children[1:],
  433. n.children[i+1].children[:n.children[i+1].numItems+1])
  434. }
  435. n.children[i+1].items[0] = n.items[i]
  436. if !n.children[0].leaf {
  437. n.children[i+1].children[0] =
  438. n.children[i].children[n.children[i].numItems]
  439. n.children[i+1].count += n.children[i+1].children[0].count
  440. }
  441. n.children[i+1].numItems++
  442. n.children[i+1].count++
  443. n.items[i] = n.children[i].items[n.children[i].numItems-1]
  444. n.children[i].items[n.children[i].numItems-1] = nil
  445. if !n.children[0].leaf {
  446. n.children[i].children[n.children[i].numItems] = nil
  447. n.children[i].count -= n.children[i+1].children[0].count
  448. }
  449. n.children[i].numItems--
  450. n.children[i].count--
  451. } else {
  452. // move left <- right
  453. n.children[i].items[n.children[i].numItems] = n.items[i]
  454. if !n.children[0].leaf {
  455. n.children[i].children[n.children[i].numItems+1] =
  456. n.children[i+1].children[0]
  457. n.children[i].count +=
  458. n.children[i].children[n.children[i].numItems+1].count
  459. }
  460. n.children[i].numItems++
  461. n.children[i].count++
  462. n.items[i] = n.children[i+1].items[0]
  463. copy(n.children[i+1].items[:],
  464. n.children[i+1].items[1:n.children[i+1].numItems])
  465. n.children[i+1].items[n.children[i+1].numItems-1] = nil
  466. if !n.children[0].leaf {
  467. copy(n.children[i+1].children[:],
  468. n.children[i+1].children[1:n.children[i+1].numItems+1])
  469. n.children[i+1].children[n.children[i+1].numItems] = nil
  470. n.children[i+1].count -=
  471. n.children[i].children[n.children[i].numItems].count
  472. }
  473. n.children[i+1].numItems--
  474. n.children[i+1].count--
  475. }
  476. return prev
  477. }
  478. // Ascend the tree within the range [pivot, last]
  479. // Pass nil for pivot to scan all item in ascending order
  480. // Return false to stop iterating
  481. func (tr *BTree) Ascend(pivot interface{}, iter func(item interface{}) bool) {
  482. if tr.rlock() {
  483. defer tr.runlock()
  484. }
  485. if tr.root == nil {
  486. return
  487. }
  488. if pivot == nil {
  489. tr.root.scan(iter)
  490. } else if tr.root != nil {
  491. tr.root.ascend(pivot, tr.less, nil, 0, iter)
  492. }
  493. }
  494. func (n *node) ascend(pivot interface{}, less func(a, b interface{}) bool,
  495. hint *PathHint, depth int, iter func(item interface{}) bool,
  496. ) bool {
  497. i, found := n.find(pivot, less, hint, depth)
  498. if !found {
  499. if !n.leaf {
  500. if !n.children[i].ascend(pivot, less, hint, depth+1, iter) {
  501. return false
  502. }
  503. }
  504. }
  505. for ; i < n.numItems; i++ {
  506. if !iter(n.items[i]) {
  507. return false
  508. }
  509. if !n.leaf {
  510. if !n.children[i+1].scan(iter) {
  511. return false
  512. }
  513. }
  514. }
  515. return true
  516. }
  517. func (n *node) reverse(iter func(item interface{}) bool) bool {
  518. if n.leaf {
  519. for i := n.numItems - 1; i >= 0; i-- {
  520. if !iter(n.items[i]) {
  521. return false
  522. }
  523. }
  524. return true
  525. }
  526. if !n.children[n.numItems].reverse(iter) {
  527. return false
  528. }
  529. for i := n.numItems - 1; i >= 0; i-- {
  530. if !iter(n.items[i]) {
  531. return false
  532. }
  533. if !n.children[i].reverse(iter) {
  534. return false
  535. }
  536. }
  537. return true
  538. }
  539. // Descend the tree within the range [pivot, first]
  540. // Pass nil for pivot to scan all item in descending order
  541. // Return false to stop iterating
  542. func (tr *BTree) Descend(pivot interface{}, iter func(item interface{}) bool) {
  543. if tr.rlock() {
  544. defer tr.runlock()
  545. }
  546. if tr.root == nil {
  547. return
  548. }
  549. if pivot == nil {
  550. tr.root.reverse(iter)
  551. } else if tr.root != nil {
  552. tr.root.descend(pivot, tr.less, nil, 0, iter)
  553. }
  554. }
  555. func (n *node) descend(pivot interface{}, less func(a, b interface{}) bool,
  556. hint *PathHint, depth int, iter func(item interface{}) bool,
  557. ) bool {
  558. i, found := n.find(pivot, less, hint, depth)
  559. if !found {
  560. if !n.leaf {
  561. if !n.children[i].descend(pivot, less, hint, depth+1, iter) {
  562. return false
  563. }
  564. }
  565. i--
  566. }
  567. for ; i >= 0; i-- {
  568. if !iter(n.items[i]) {
  569. return false
  570. }
  571. if !n.leaf {
  572. if !n.children[i].reverse(iter) {
  573. return false
  574. }
  575. }
  576. }
  577. return true
  578. }
  579. // Load is for bulk loading pre-sorted items
  580. func (tr *BTree) Load(item interface{}) interface{} {
  581. if item == nil {
  582. panic("nil item")
  583. }
  584. if tr.lock() {
  585. defer tr.unlock()
  586. }
  587. if tr.root == nil {
  588. return tr.setHint(item, nil)
  589. }
  590. n := tr.cowLoad(&tr.root)
  591. for {
  592. n.count++ // optimistically update counts
  593. if n.leaf {
  594. if n.numItems < maxItems-2 {
  595. if tr.less(n.items[n.numItems-1], item) {
  596. n.items[n.numItems] = item
  597. n.numItems++
  598. tr.count++
  599. return nil
  600. }
  601. }
  602. break
  603. }
  604. n = tr.cowLoad(&n.children[n.numItems])
  605. }
  606. // revert the counts
  607. n = tr.root
  608. for {
  609. n.count--
  610. if n.leaf {
  611. break
  612. }
  613. n = n.children[n.numItems]
  614. }
  615. return tr.setHint(item, nil)
  616. }
  617. // Min returns the minimum item in tree.
  618. // Returns nil if the tree has no items.
  619. func (tr *BTree) Min() interface{} {
  620. if tr.rlock() {
  621. defer tr.runlock()
  622. }
  623. if tr.root == nil {
  624. return nil
  625. }
  626. n := tr.root
  627. for {
  628. if n.leaf {
  629. return n.items[0]
  630. }
  631. n = n.children[0]
  632. }
  633. }
  634. // Max returns the maximum item in tree.
  635. // Returns nil if the tree has no items.
  636. func (tr *BTree) Max() interface{} {
  637. if tr.rlock() {
  638. defer tr.runlock()
  639. }
  640. if tr.root == nil {
  641. return nil
  642. }
  643. n := tr.root
  644. for {
  645. if n.leaf {
  646. return n.items[n.numItems-1]
  647. }
  648. n = n.children[n.numItems]
  649. }
  650. }
  651. // PopMin removes the minimum item in tree and returns it.
  652. // Returns nil if the tree has no items.
  653. func (tr *BTree) PopMin() interface{} {
  654. if tr.lock() {
  655. defer tr.unlock()
  656. }
  657. if tr.root == nil {
  658. return nil
  659. }
  660. n := tr.cowLoad(&tr.root)
  661. var item interface{}
  662. for {
  663. n.count-- // optimistically update counts
  664. if n.leaf {
  665. item = n.items[0]
  666. if n.numItems == minItems {
  667. break
  668. }
  669. copy(n.items[:], n.items[1:])
  670. n.items[n.numItems-1] = nil
  671. n.numItems--
  672. tr.count--
  673. if tr.count == 0 {
  674. tr.root = nil
  675. }
  676. return item
  677. }
  678. n = tr.cowLoad(&n.children[0])
  679. }
  680. // revert the counts
  681. n = tr.root
  682. for {
  683. n.count++
  684. if n.leaf {
  685. break
  686. }
  687. n = n.children[0]
  688. }
  689. return tr.deleteHint(item, nil)
  690. }
  691. // PopMax removes the minimum item in tree and returns it.
  692. // Returns nil if the tree has no items.
  693. func (tr *BTree) PopMax() interface{} {
  694. if tr.lock() {
  695. defer tr.unlock()
  696. }
  697. if tr.root == nil {
  698. return nil
  699. }
  700. n := tr.cowLoad(&tr.root)
  701. var item interface{}
  702. for {
  703. n.count-- // optimistically update counts
  704. if n.leaf {
  705. item = n.items[n.numItems-1]
  706. if n.numItems == minItems {
  707. break
  708. }
  709. n.items[n.numItems-1] = nil
  710. n.numItems--
  711. tr.count--
  712. if tr.count == 0 {
  713. tr.root = nil
  714. }
  715. return item
  716. }
  717. n = tr.cowLoad(&n.children[n.numItems])
  718. }
  719. // revert the counts
  720. n = tr.root
  721. for {
  722. n.count++
  723. if n.leaf {
  724. break
  725. }
  726. n = n.children[n.numItems]
  727. }
  728. return tr.deleteHint(item, nil)
  729. }
  730. // GetAt returns the value at index.
  731. // Return nil if the tree is empty or the index is out of bounds.
  732. func (tr *BTree) GetAt(index int) interface{} {
  733. if tr.rlock() {
  734. defer tr.runlock()
  735. }
  736. if tr.root == nil || index < 0 || index >= tr.count {
  737. return nil
  738. }
  739. n := tr.root
  740. for {
  741. if n.leaf {
  742. return n.items[index]
  743. }
  744. i := 0
  745. for ; i < int(n.numItems); i++ {
  746. if index < n.children[i].count {
  747. break
  748. } else if index == n.children[i].count {
  749. return n.items[i]
  750. }
  751. index -= n.children[i].count + 1
  752. }
  753. n = n.children[i]
  754. }
  755. }
  756. // DeleteAt deletes the item at index.
  757. // Return nil if the tree is empty or the index is out of bounds.
  758. func (tr *BTree) DeleteAt(index int) interface{} {
  759. if tr.lock() {
  760. defer tr.unlock()
  761. }
  762. if tr.root == nil || index < 0 || index >= tr.count {
  763. return nil
  764. }
  765. var pathbuf [8]uint8 // track the path
  766. path := pathbuf[:0]
  767. var item interface{}
  768. n := tr.cowLoad(&tr.root)
  769. outer:
  770. for {
  771. n.count-- // optimistically update counts
  772. if n.leaf {
  773. // the index is the item position
  774. item = n.items[index]
  775. if n.numItems == minItems {
  776. path = append(path, uint8(index))
  777. break outer
  778. }
  779. copy(n.items[index:], n.items[index+1:n.numItems])
  780. n.items[n.numItems-1] = nil
  781. n.numItems--
  782. tr.count--
  783. if tr.count == 0 {
  784. tr.root = nil
  785. }
  786. return item
  787. }
  788. i := 0
  789. for ; i < int(n.numItems); i++ {
  790. if index < n.children[i].count {
  791. break
  792. } else if index == n.children[i].count {
  793. item = n.items[i]
  794. path = append(path, uint8(i))
  795. break outer
  796. }
  797. index -= n.children[i].count + 1
  798. }
  799. path = append(path, uint8(i))
  800. n = tr.cowLoad(&n.children[i])
  801. }
  802. // revert the counts
  803. var hint PathHint
  804. n = tr.root
  805. for i := 0; i < len(path); i++ {
  806. if i < len(hint.path) {
  807. hint.path[i] = path[i]
  808. hint.used[i] = true
  809. }
  810. n.count++
  811. if !n.leaf {
  812. n = n.children[uint8(path[i])]
  813. }
  814. }
  815. return tr.deleteHint(item, &hint)
  816. }
  817. // Height returns the height of the tree.
  818. // Returns zero if tree has no items.
  819. func (tr *BTree) Height() int {
  820. if tr.rlock() {
  821. defer tr.runlock()
  822. }
  823. var height int
  824. if tr.root != nil {
  825. n := tr.root
  826. for {
  827. height++
  828. if n.leaf {
  829. break
  830. }
  831. n = n.children[n.numItems]
  832. }
  833. }
  834. return height
  835. }
  836. // Walk iterates over all items in tree, in order.
  837. // The items param will contain one or more items.
  838. func (tr *BTree) Walk(iter func(item []interface{})) {
  839. if tr.rlock() {
  840. defer tr.runlock()
  841. }
  842. if tr.root != nil {
  843. tr.root.walk(iter)
  844. }
  845. }
  846. func (n *node) walk(iter func(item []interface{})) {
  847. if n.leaf {
  848. iter(n.items[:n.numItems])
  849. } else {
  850. for i := int16(0); i < n.numItems; i++ {
  851. n.children[i].walk(iter)
  852. iter(n.items[i : i+1])
  853. }
  854. n.children[n.numItems].walk(iter)
  855. }
  856. }
  857. // Copy the tree. This operation is very fast because it only performs a
  858. // shadowed copy.
  859. func (tr *BTree) Copy() *BTree {
  860. if tr.lock() {
  861. defer tr.unlock()
  862. }
  863. tr.cow = new(cow)
  864. tr2 := *tr
  865. tr2.mu = new(sync.RWMutex)
  866. tr2.cow = new(cow)
  867. return &tr2
  868. }
  869. func (tr *BTree) lock() bool {
  870. if tr.locks {
  871. tr.mu.Lock()
  872. }
  873. return tr.locks
  874. }
  875. func (tr *BTree) unlock() {
  876. tr.mu.Unlock()
  877. }
  878. func (tr *BTree) rlock() bool {
  879. if tr.locks {
  880. tr.mu.RLock()
  881. }
  882. return tr.locks
  883. }
  884. func (tr *BTree) runlock() {
  885. tr.mu.RUnlock()
  886. }