!=========================================================================
! Copyright (C) VMware, Inc. 1986-2011.  All Rights Reserved.
!
! $Id: identkeysoftvaluedict.gs,v 1.5 2008-01-09 22:50:11 stever Exp $
!
! Superclass Hierarchy:
!   KeySoftValueDictionary, KeyValueDictionary, AbstractDictionary, Collection, Object.
!
!=========================================================================

expectvalue %String
run
| res cls oldCls clsName |
clsName := #IdentityKeySoftValueDictionary .
oldCls := Globals at:clsName otherwise: nil .
oldCls == nil ifTrue:[
  res := KeySoftValueDictionary _newKernelSubclass: clsName"IdentityKeySoftValueDictionary"
    instVarNames: #( )
    classVars: #()
    classInstVars: #()
    poolDictionaries: #[]
    inDictionary: Globals
    constraints: #[ ]
    instancesInvariant: false
    isModifiable: true
    reservedOop: 943 .
  cls := Globals at: clsName .
  cls makeInstancesNonPersistent .
  cls _disallowGciCreateStore . 
  cls immediateInvariant .
] ifFalse: [
  res := clsName asString + 'already exists'.
  oldCls instancesNonPersistent ifFalse:[ nil error:'should be NP' ].
].
^ res
%

removeallmethods IdentityKeySoftValueDictionary
removeallclassmethods 

category: 'For Documentation Installation only'
classmethod
installDocumentation

| doc txt |
doc := GsClassDocumentation newForClass: self.

txt := (GsDocText new) details:
'IdentityKeySoftValueDictionary is a subclass of KeySoftValueDictionary
 which uses identity comparision on keys.' .
doc documentClassWith: txt.

self description: doc.
%

category: 'Hashing'
method
hashFunction: aKey

"The hash function should perform some operation on the value of the key aKey
 which returns a value in the range 1..tableSize."

^(aKey identityHash \\ tableSize) + 1
%

category: 'Private'
method
collisionBucketClass

"Returns the class of object to create when keys collide."

^ IdentitySoftCollisionBucket
%

category: 'Private'
method
compareKey: key1 with: key2

"Returns true if key1 is identical to key2; returns false otherwise."

^ key1 == key2
%
category: 'Initializing'
method
initialize: itsSize

"Initializes the instance variables of the receiver to be an empty
 IdentityKeyValueDictionary of the specified size."

| theSize |
theSize := itsSize .
(theSize <= 0)
  ifTrue: [theSize _error: #rtErrArgNotPositive .  theSize := 1 ].
numElements := 0.
numCollisions := 0.
collisionLimit := theSize  * 500 .
  "This is where it differs from KeySoftValueDictionary. By setting the default
   collision limit to be high in comparison to the size of the dictionary,
   the dictionary will only be rebuilt when the collision buckets have
   become big."
self _basicSize: 0.  "Reset size to 0 to nil any entries"
self _basicSize: theSize * 2.
tableSize := theSize.
^self
%

category: 'Hashing'
method
rebuildTable: newSize

super rebuildTable: newSize .
self collisionLimit: newSize * 500 . "differs from KeySoftValueDictionary"
%


category: 'Comparing'
method
hash

"Returns a numeric hash key for the receiver."

| hashValue |

hashValue := 97633 bitXor: (self size).
"For large dictionaries, the hash value is just a function of its size"
(self size > 64) ifTrue: [ ^ hashValue abs ].
self keysDo: [ :aKey |
   "Skip if the key is a dictionary."
   (aKey isKindOf: AbstractDictionary)
     ifFalse: [
       hashValue := hashValue bitXor: aKey identityHash
       ]
     ].
^ hashValue abs
%

! fix 32863, keysAndValuesDo: is inherited 
