@@ -398,10 +398,11 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen, equiv: E
398398
399399 def isNullInode (ct : TrieMap [K , V ]) = GCAS_READ (ct) eq null
400400
401- def cachedSize (ct : TrieMap [K , V ]): Int = {
402- val m = GCAS_READ (ct)
403- m.cachedSize(ct)
404- }
401+ def cachedSize (ct : TrieMap [K , V ]): Int =
402+ GCAS_READ (ct).cachedSize(ct)
403+
404+ def knownSize (ct : TrieMap [K , V ]): Int =
405+ GCAS_READ (ct).knownSize()
405406
406407 /* this is a quiescent method! */
407408 def string (lev : Int ) = " %sINode -> %s" .format(" " * lev, mainnode match {
@@ -438,6 +439,8 @@ private[concurrent] final class FailedNode[K, V](p: MainNode[K, V]) extends Main
438439
439440 def cachedSize (ct : AnyRef ): Int = throw new UnsupportedOperationException
440441
442+ def knownSize : Int = throw new UnsupportedOperationException
443+
441444 override def toString = " FailedNode(%s)" .format(p)
442445}
443446
@@ -456,18 +459,19 @@ private[collection] final class SNode[K, V](final val k: K, final val v: V, fina
456459 def string (lev : Int ) = (" " * lev) + " SNode(%s, %s, %x)" .format(k, v, hc)
457460}
458461
459-
462+ // Tomb Node, used to ensure proper ordering during removals
460463private [collection] final class TNode [K , V ](final val k : K , final val v : V , final val hc : Int )
461464 extends MainNode [K , V ] with KVNode [K , V ] {
462465 def copy = new TNode (k, v, hc)
463466 def copyTombed = new TNode (k, v, hc)
464467 def copyUntombed = new SNode (k, v, hc)
465468 def kvPair = (k, v)
466469 def cachedSize (ct : AnyRef ): Int = 1
470+ def knownSize : Int = 1
467471 def string (lev : Int ) = (" " * lev) + " TNode(%s, %s, %x, !)" .format(k, v, hc)
468472}
469473
470-
474+ // List Node, leaf node that handles hash collisions
471475private [collection] final class LNode [K , V ](val entries : List [(K , V )], equiv : Equiv [K ])
472476 extends MainNode [K , V ] {
473477
@@ -492,7 +496,7 @@ private[collection] final class LNode[K, V](val entries: List[(K, V)], equiv: Eq
492496
493497 def removed (k : K , ct : TrieMap [K , V ]): MainNode [K , V ] = {
494498 val updmap = entries.filterNot(entry => equiv.equiv(entry._1, k))
495- if (updmap.size > 1 ) new LNode (updmap, equiv)
499+ if (updmap.sizeIs > 1 ) new LNode (updmap, equiv)
496500 else {
497501 val (k, v) = updmap.iterator.next()
498502 new TNode (k, v, ct.computeHash(k)) // create it tombed so that it gets compressed on subsequent accesses
@@ -503,14 +507,16 @@ private[collection] final class LNode[K, V](val entries: List[(K, V)], equiv: Eq
503507
504508 def cachedSize (ct : AnyRef ): Int = entries.size
505509
510+ def knownSize : Int = - 1 // shouldn't ever be empty, and the size of a list is not known
511+
506512 def string (lev : Int ) = (" " * lev) + " LNode(%s)" .format(entries.mkString(" , " ))
507513
508514}
509515
510-
516+ // Ctrie Node, contains bitmap and array of references to branch nodes
511517private [collection] final class CNode [K , V ](val bitmap : Int , val array : Array [BasicNode ], val gen : Gen ) extends CNodeBase [K , V ] {
512518 // this should only be called from within read-only snapshots
513- def cachedSize (ct : AnyRef ) = {
519+ def cachedSize (ct : AnyRef ): Int = {
514520 val currsz = READ_SIZE ()
515521 if (currsz != - 1 ) currsz
516522 else {
@@ -520,6 +526,8 @@ private[collection] final class CNode[K, V](val bitmap: Int, val array: Array[Ba
520526 }
521527 }
522528
529+ def knownSize : Int = READ_SIZE () // this should only ever return -1 if unknown
530+
523531 // lends itself towards being parallelizable by choosing
524532 // a random starting offset in the array
525533 // => if there are concurrent size computations, they start
@@ -676,6 +684,7 @@ private[concurrent] case class RDCSS_Descriptor[K, V](old: INode[K, V], expected
676684 *
677685 * For details, see: [[http://lampwww.epfl.ch/~prokopec/ctries-snapshot.pdf ]]
678686 */
687+ @ SerialVersionUID (- 5212455458703321708L )
679688final class TrieMap [K , V ] private (r : AnyRef , rtupd : AtomicReferenceFieldUpdater [TrieMap [K , V ], AnyRef ], hashf : Hashing [K ], ef : Equiv [K ])
680689 extends scala.collection.mutable.AbstractMap [K , V ]
681690 with scala.collection.concurrent.Map [K , V ]
@@ -1002,16 +1011,14 @@ final class TrieMap[K, V] private (r: AnyRef, rtupd: AtomicReferenceFieldUpdater
10021011 // END extra overrides
10031012 // /////////////////////////////////////////////////////////////////
10041013
1005-
1006- private def cachedSize () = {
1007- val r = RDCSS_READ_ROOT ()
1008- r.cachedSize(this )
1009- }
1010-
10111014 override def size : Int =
10121015 if (nonReadOnly) readOnlySnapshot().size
1013- else cachedSize()
1014- override def isEmpty : Boolean = size == 0
1016+ else RDCSS_READ_ROOT ().cachedSize(this )
1017+ override def knownSize : Int =
1018+ if (nonReadOnly) - 1
1019+ else RDCSS_READ_ROOT ().knownSize(this )
1020+ override def isEmpty : Boolean =
1021+ (if (nonReadOnly) readOnlySnapshot() else this ).sizeIs == 0 // sizeIs checks knownSize
10151022 override protected [this ] def className = " TrieMap"
10161023
10171024}
0 commit comments