Persisting IdentityDictionary

Chris Muller ma.chris.m at gmail.com
Tue Apr 26 15:12:20 UTC 2011


Thanks for the explanation.

> Aida/Web uses a huge IdentityDictionary to keep a stable obj -> url
> relationship and a huge Dictionary to keep a stable url -> obj
> relationship.  This is how it accomplishes one of it's nicest features
> - simple obj to obj refs in code translate to urls in the webpage.
>
> so when I say:
>
> e addLinkTo: address text: address lastName.
>
> it checks the IdentityDictionary to see what URL was used for
> 'address' last time, and it uses it again.  If this is the first time,
> then it creates the entries in the dictionaries.  There are also some
> checks to make sure duplicate URLs aren't used, etc... but that's the
> jest of it.

Ok.  I still don't understand why an IdentityDictionary would be used
in this case; maybe Janko knows.  1) What if the user supplied a new,
equivalent-but-not-identical address?  Objects that don't override #=
will be found by identity anyway in a standard Dictionary, and objects
that do override #= WANT to be found by equivalence, not identity.

So, I'm still confused as to the "why" Aida uses an IdentityDictionary
in this case but nevertheless, I see no reason Magma can't or
shouldn't support it.

> If I were to subclass MagmaPreallocatedDictionary and change:
>
> MagmaPreallocatedDictionary>>keyHash: key
>     ^ (key hash \\ maxBuckets) + 1
>
> to this:
>
> MagmaPreallocatedDictionary>>keyHash: key
>     ^ (key aSelectorThatAnswersMagmaOID \\ maxBuckets) + 1

aSelectorThatAnswersMagmaOID is already implemented, it's called
#magmaOid, implemented on Object.

But that won't work, because when you have new, uncommitted objects
that you attach to the persistent model (before commit), they will not
have a magmaOid yet (it would be nil).

The way to do it would be to do the same thing that the standard
IdentityDictionary overrides Dictionary:  Override
MagmaPreallocatedDictionary>>#at: key ifAbsent: aBlock with:

1	| bucket |
2	bucket := self bucketAt: (self keyHash: key).
3	[bucket notNil] whileTrue: [ bucket key == key ifTrue: [^ bucket
value]. bucket := bucket next ].
4	^ aBlock value

Note the change on line 3, to an identity compare.

You would also want to check all the other methods to make similar
change:  A quick run-through, I see #at:ifAbsentPut:, #at:put:,
#removeKey:, would all need similar change.  But I believe that should
be all that's needed to have a MagmaPreallocatedIdentityDictionary.

Please let us know if you get it working..

 - Chris


More information about the Magma mailing list