[squeak-dev] enabling read-only literals...

Chris Muller ma.chris.m at gmail.com
Thu Mar 12 02:53:10 UTC 2020

Hi Eliot,

Thanks for the great explanation!  Quick question:  Will a become: cause
the handler to be called on all referencing objects?

Can ModificationForbidden be resumed?  I certainly hope so.
> Indeed its can.  Use in database write barriers is one major use case.
> However, the framework for convenient use has yet to be designed and
> implemented.  We have lots of experience with this barrier in VisualWorks
> and some experience in Pharo, so designing the right support should not be
> hard at all.

>> Magma's own WriteBarrier has one place where it dynamically compiles a
>> literal in a method for the sole purpose of providing one extra reference
>> slot needed for the framework.  This is a useful feature in a general
>> sense, something I'd hate to see lost.  Yes, I understand it's "bad code"
>> to modify a literal, just like using "become:" (which it also uses), but
>> for frameworks that need to work slightly under the hood, these hacks can
>> be very useful when one knows what they're doing.
> If you *do* have to modify a literal, then all you have to do is send
> beWritableObject to the literal in question and you'll be able to modify it
> (there is no recursive protection against setting read-only objects to
> writable).

Oh, good.  :)

> Unfortunately, I don't think the VM-based WriteBarrier can work for Magma
>> due to its "global" nature.
> I'm willing to bet you that it can.  For example,e, it works in Gemstone
> on VisualWorks. The solution is to provide a policy registry hat on a
> per-object basis specifies how modifications to objects are to be handled.
> This registry typically/best exists in the exception class
> (ModificationForbidden), and maps an object to a MessageSend or block. This
> registry tags specific instances with a retry policy, so e.g. Magma can put
> all objects it fetches from the database that it wants to be write-through
> into the registry
and sets them to be read-only.  Then on an attempted modification the
> ModificationForbidden exception looks up the object in the registry, and if
> its there runs whatever code the registry specifies.  This would be some
> method in Magma that would
> - set the object as writable
> - ask the exception to retry the modification
> - write the changed object through to the database
> - set the object back to read-only
> - resume the exception with a suitable value

For this step, above:

      - write the changed object through to the database

I need a reference to the particular MagmaSession which the object belongs,
so I can tell it,

       mySession modified: forbiddenException object

and why I use the compiled literal to hold that reference.  How would this
be accomplished under this model?  IIRC, GemBuilder had the luxury /
restriction of assuming there was only one backend Stone, so was able to go
through a global...

> Specific classes might implement a message the exception could send rather
> than require the registry is used.  But that's a space-saving optimization.

Good, since the registration/unregistration cost would make merely reading
objects from the database considerably more expensive than simply changing
their class via primChangeClassTo:.

But I still need that reference to the Session anyway...

> Such a framework allows several orthogonal clients to share the framework,
> potentially on the same objects because the registry can be engineered to
> have more than one action per object.
> (BTW, this is how VisualWorks does things, IIRC)
> Does that instill more confidence?

More, yes.  All the way there?  I'm not sure. I do also have need of #abort
-- *restore all changed objects to their state as read from the database*.
This means all WriteBarrier handlers for objects read from that Session
need to be temporarily suspended, since restoring the variables of an
object require it to once again undergo modification back to its original
state.  With Avi's / Magma's WriteBarrier, this is just flipping a boolean
switch on the Session, but for this, would I have to

  - unregister all dirty objects,
  - then do the #abort function (restore all the dirty objects to their
former state)
  - re-register those above objects, no longer dirty, but ready to track
further updates


It's okay.  With all on my plate, I doubt I'll ever have time to switch out
Magma's WriteBarrier.  The ability to keep running Avi's working will be
important for Magma in 6.0+, but thankfully sounds like a non-issue with a
minor update.

> When we added read-only object support to VisualWorks some of the
>>> engineering staff were of the opinion that insulating customers from the
>>> change was a necessary thing, and so we implemented a preference to allow
>>> automatic mutating of read-only literals so that customers whose code did
>>> modify literals could set the preference rather than fix their code.  I
>>> *really* don't ant to do this.  It is a lot of complication for little
>>> gain; the right fix is just to rewrite the code not to write to literals.
>>> Note that that's as easy as:
>> I don't think we need a global preference as much as just let it be
>> #isResumable.  Can we do that?
> Yes, it is, but doing so loses the modification:
> | l |
> [(l := #(1 2 3)) at: 2 put: 'nevermore']
> on: ModificationForbidden
> do: [:ex| ex resume].
> l => #(1 2 3)
> whereas one often wants to do something more like this:
> | lit result |
> result := [(lit := #(1 2 3)) at: 2 put: 'nevermore']
> on: ModificationForbidden
> do: [:ex| ex object beWritableObject. ex retryModification].
> lit -> result #(1 'nevermore' 3)->'nevermore'

I think I will prefer to take care of it as early as possible, on
compilation, as in:

        compileSilently: 'writeBarrier
    ^ #(size) first first'
        classified: 'access'.
    ((class methodDictionary at: #writeBarrier) literalAt: 2)
        *beWritableObject ;*           *"<----- can I simply add in this
        at: 1
        put: (WeakArray with: mySession)

and then not worry about ModifiedForbidden at all.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20200311/61c964ad/attachment.html>

More information about the Squeak-dev mailing list