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