1
- /** Taken from the original implementation of WeakHashSet in scala-reflect
1
+ /** Adapted from the original implementation of WeakHashSet in scala-reflect
2
2
*/
3
3
package dotty .tools .dotc .util
4
4
5
5
import java .lang .ref .{ReferenceQueue , WeakReference }
6
6
7
- import scala .annotation .tailrec
7
+ import scala .annotation .{ constructorOnly , tailrec }
8
8
import scala .collection .mutable
9
9
10
10
/**
@@ -17,7 +17,7 @@ import scala.collection.mutable
17
17
* This set implementation is not in general thread safe without external concurrency control. However it behaves
18
18
* properly when GC concurrently collects elements in this set.
19
19
*/
20
- final class WeakHashSet [A <: AnyRef ](initialCapacity : Int , loadFactor : Double ) extends mutable. Set [A ] {
20
+ final class WeakHashSet [A <: AnyRef ](initialCapacity : Int , loadFactor : Double ) extends MutableSet [A ] {
21
21
22
22
import WeakHashSet ._
23
23
@@ -61,8 +61,6 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
61
61
62
62
private def computeThreshold : Int = (table.size * loadFactor).ceil.toInt
63
63
64
- def get (elem : A ): Option [A ] = Option (findEntry(elem))
65
-
66
64
/**
67
65
* find the bucket associated with an element's hash code
68
66
*/
@@ -86,6 +84,7 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
86
84
* remove a single entry from a linked list in a given bucket
87
85
*/
88
86
private def remove (bucket : Int , prevEntry : Entry [A ], entry : Entry [A ]): Unit = {
87
+ Stats .record(statsItem(" remove" ))
89
88
prevEntry match {
90
89
case null => table(bucket) = entry.tail
91
90
case _ => prevEntry.tail = entry.tail
@@ -122,6 +121,7 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
122
121
* Double the size of the internal table
123
122
*/
124
123
private def resize (): Unit = {
124
+ Stats .record(statsItem(" resize" ))
125
125
val oldTable = table
126
126
table = new Array [Entry [A ]](oldTable.size * 2 )
127
127
threshold = computeThreshold
@@ -145,12 +145,10 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
145
145
tableLoop(0 )
146
146
}
147
147
148
- def contains (elem : A ): Boolean = findEntry(elem) ne null
149
-
150
- // from scala.reflect.internal.Set, find an element or null if it isn't contained
151
- def findEntry (elem : A ): A = elem match {
148
+ def lookup (elem : A ): A | Null = elem match {
152
149
case null => throw new NullPointerException (" WeakHashSet cannot hold nulls" )
153
150
case _ =>
151
+ Stats .record(statsItem(" lookup" ))
154
152
removeStaleEntries()
155
153
val hash = elem.hashCode
156
154
val bucket = bucketFor(hash)
@@ -166,10 +164,11 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
166
164
167
165
linkedListLoop(table(bucket))
168
166
}
169
- // add an element to this set unless it's already in there and return the element
170
- def findEntryOrUpdate (elem : A ): A = elem match {
167
+
168
+ def put (elem : A ): A = elem match {
171
169
case null => throw new NullPointerException (" WeakHashSet cannot hold nulls" )
172
170
case _ =>
171
+ Stats .record(statsItem(" put" ))
173
172
removeStaleEntries()
174
173
val hash = elem.hashCode
175
174
val bucket = bucketFor(hash)
@@ -194,36 +193,12 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
194
193
linkedListLoop(oldHead)
195
194
}
196
195
197
- // add an element to this set unless it's already in there and return this set
198
- override def addOne (elem : A ): this .type = elem match {
199
- case null => throw new NullPointerException (" WeakHashSet cannot hold nulls" )
200
- case _ =>
201
- removeStaleEntries()
202
- val hash = elem.hashCode
203
- val bucket = bucketFor(hash)
204
- val oldHead = table(bucket)
205
-
206
- def add (): Unit = {
207
- table(bucket) = new Entry (elem, hash, oldHead, queue)
208
- count += 1
209
- if (count > threshold) resize()
210
- }
211
-
212
- @ tailrec
213
- def linkedListLoop (entry : Entry [A ]): Unit = entry match {
214
- case null => add()
215
- case _ if elem.equals(entry.get) => ()
216
- case _ => linkedListLoop(entry.tail)
217
- }
196
+ def += (elem : A ): Unit = put(elem)
218
197
219
- linkedListLoop(oldHead)
220
- this
221
- }
222
-
223
- // remove an element from this set and return this set
224
- override def subtractOne (elem : A ): this .type = elem match {
225
- case null => this
198
+ def -= (elem : A ): Unit = elem match {
199
+ case null =>
226
200
case _ =>
201
+ Stats .record(statsItem(" -=" ))
227
202
removeStaleEntries()
228
203
val bucket = bucketFor(elem.hashCode)
229
204
@@ -237,11 +212,9 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
237
212
}
238
213
239
214
linkedListLoop(null , table(bucket))
240
- this
241
215
}
242
216
243
- // empty this set
244
- override def clear (): Unit = {
217
+ def clear (): Unit = {
245
218
table = new Array [Entry [A ]](table.size)
246
219
threshold = computeThreshold
247
220
count = 0
@@ -251,21 +224,11 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
251
224
queueLoop()
252
225
}
253
226
254
- // true if this set is empty
255
- override def empty : This = new WeakHashSet [A ](initialCapacity, loadFactor)
256
-
257
- // the number of elements in this set
258
- override def size : Int = {
227
+ def size : Int = {
259
228
removeStaleEntries()
260
229
count
261
230
}
262
231
263
- override def isEmpty : Boolean = size == 0
264
- override def foreach [U ](f : A => U ): Unit = iterator foreach f
265
-
266
- // It has the `()` because iterator runs `removeStaleEntries()`
267
- override def toList (): List [A ] = iterator.toList
268
-
269
232
// Iterator over all the elements in this set in no particular order
270
233
override def iterator : Iterator [A ] = {
271
234
removeStaleEntries()
@@ -318,6 +281,12 @@ final class WeakHashSet[A <: AnyRef](initialCapacity: Int, loadFactor: Double) e
318
281
}
319
282
}
320
283
284
+ protected def statsItem (op : String ): String = {
285
+ val prefix = " WeakHashSet."
286
+ val suffix = getClass.getSimpleName
287
+ s " $prefix$op $suffix"
288
+ }
289
+
321
290
/**
322
291
* Diagnostic information about the internals of this set. Not normally
323
292
* needed by ordinary code, but may be useful for diagnosing performance problems
@@ -386,7 +355,7 @@ object WeakHashSet {
386
355
* A single entry in a WeakHashSet. It's a WeakReference plus a cached hash code and
387
356
* a link to the next Entry in the same bucket
388
357
*/
389
- private class Entry [A ](element : A , val hash : Int , var tail : Entry [A ], queue : ReferenceQueue [A ]) extends WeakReference [A ](element, queue)
358
+ private class Entry [A ](@ constructorOnly element : A , val hash : Int , var tail : Entry [A ], @ constructorOnly queue : ReferenceQueue [A ]) extends WeakReference [A ](element, queue)
390
359
391
360
private final val defaultInitialCapacity = 16
392
361
private final val defaultLoadFactor = .75
0 commit comments