[Pharo-project] Class initialisation after loading
frank.shearar at gmail.com
Fri Jan 18 17:38:07 EST 2013
On 18 January 2013 21:49, Eliot Miranda <eliot.miranda at gmail.com> wrote:
> phhh, let me try again :)
> On Fri, Jan 18, 2013 at 8:47 AM, Frank Shearar <frank.shearar at gmail.com>
>> On 17 January 2013 17:45, Eliot Miranda <eliot.miranda at gmail.com> wrote:
>> > On Thu, Jan 17, 2013 at 3:25 AM, Igor Stasenko <siguctua at gmail.com>
>> > wrote:
>> >> After some thought i decided to contribute my 2cents.
>> >> First, i think it is impossible to introduce a (re)initialization
>> >> logic which would suit all different scenarios.
>> >> Because it is really depends on what is stored in class variables
>> >> and/or
>> >> pools
>> >> and if you add subclasses and then instances into the soup, you might
>> >> end up with something
>> >> which is really hard to safely reinitialize, because it may have some
>> >> inconsistent state at different stages
>> >> of initialization. It also, sometimes an order of initialization is
>> >> important.
>> > Yes, but on *can* write idempotent class initialization code. So that
>> > if
>> > the system does reinitialize on every load old code may break until its
>> > fixed, but new code will have the advantage of always being correctly
>> > initialized. Note that in the VMMaker class reinitializations of the
>> > core
>> > VM classes (the interpreter, garbage collector, jit, etc) are done *on
>> > each
>> > launch of the simulator*, and *each vm generation*, let alone on each
>> > package load :). [ I'm not recommending this :) ].
>> > One thing I do is when creating singletons for sentinels etc I check
>> > whether
>> > they've been initialized. e.g.
>> > initialize
>> > Sentinel ifNil: [Sentinel := Object new]
>> Knowing full well that I know next to nothing about concurrency in the
>> image, and so realising that this might be a complete non-issue: lazy
>> initialization and concurrency do not mix well.
> Agreed, but the two can be decoupled. For example one can build the state
> and then assign it. Assignment is currently atomic so there are no
> multicore issues here (yet :) ). Further, assignments are not suspension
> points so a sequence of (just) assignments are guaranteed to occur without
> interruption. And (I'm sure you realize, for give the pedantry) the above
> example isn't lazy, it is eager. It simply refuses to create another
> Sentinel if one exists already.
So because of the assignment guarantees we won't have two processes
entering the ifNil: block? (I'll try extract one foot from my mouth
and maybe replace it with another...)
In this particular case things seem pretty innocuous: let's say two
processes enter the #initialize. They both manage to enter the ifNil:
(I'm aware this is compiled away to jumps, but the impact of this I
don't know) through a time-of-check-time-of-use race, and you end up
generating two objects. But one's simply lost. As long as references
to Sentinel don't escape the class, no one need know anything at all.
>> But I do agree with your sentiment: idempotency is highly desirable,
>> and somehow forcing non-idempotent class initialisation to fail
>> quickly and noisily sounds like a good plan.
More information about the Pharo-dev