[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

copy on write



Guenter Kniesel <Guenter.Kniesel@Informatik.Uni-Bonn.DE> wrote:
> [ lot's of good stuff, deleted to save space ]
> In the current SELF version one can allow different degrees of encapsulation 
> by hiding slots or allowing execute and/or write access (using the _, ^_, ^, 
> and _^ annotations). 

Actually, this no longer works in version 3.0. The syntax is still
accepted and this even changes how a slot is displayed by the user
interface, but the VM ignores these declarations entirely.

> Full (xw) delegation access would change the mammal prototype where only 
> a change to a child is intended [....]

I just had a hard time convincing a Smalltalker that what he called a
"prototype" we call "traits" in Self. I think this might be causing
some confusion in this discussion too. In normal Self style, there is
*no* relation ( from the user's point of view ) between a prototype
and one of its clones.

> Yes, this could be a powerful feature and I would love to have a multi-user 
> SELF system, incorporating it.
> 
> Nevertheless, again I might misunderstand your ideas, how can multi-user 
> features solve the CPP? They would avoid that it spreads in a multi-user 
> environment, but  if I am working alone, how can they ensure that I do not 
> change one of my _own_ prototypes just because I forgot a "copy" in the right 
> place? 

You are right: it doesn't help at all, here. The problem I was trying to
solve was CPP ( corrupt politician problem .. er... I mean prototype ;-)
at the user interface level. Imagine you have a system where there are
lots of neat objects ( like texts, drawings, spreadsheets ) lying
around. The only way to create a new object is to copy an existing
one and then change it until it suits you. I think that the Lisa was
like that, but the prototypes were special in that they created a
new object when you tried to open it - you would "tear off" a LisaDraw
sheet from the LisaDraw pad to start a new drawing. Of course, on the 
Lisa this was just smoke-and-mirrors on top of a conventional application/
data model, but in Self that is how the it really works.

I think that *any* drawing might make a nice prototype, rather than
just the empty one. That argues against this "pad" idea. But if the
"main" prototype is just a normal object, it would be nasty if some
user changed it or even deleted it. I don't want the empty spreadsheet
to be different from its clones, but I do want it to be protected
from accidents or tampering. So I decided to create a new user and
make the empty spreadsheet belong to it. Other users can now clone
it. If there really is a need to change it, someone with permission
may do so.

None of this avoids the need for a good privacy scheme, and your
suggestion is a very good one.

Ooops! I just noticed that what I wrote above is valid for my very
simple multiuser scheme, but a Unix-like system could easily help
with the CPP. Just say "chmod -w prototype". Now "edit prototype"
will cause an error, while "cp prototype clone; edit clone" will
work fine. If you really need to change the prototype, then
"chmod +w prototype; edit prototype; chmod -w prototype" will
allow it. You don't need any extra user IDs or stuff like that.
Maybe I went too far in simplifying my design ...

> The best one can do is to try to avoid making errors by restructuring the 
> system in such a way that the "safer" syntax is the default, as Dave and 
> Jecel suggested:

  [ suggestions ]

Like I said, this is better than nothing, but I really would prefer that
the problem was solved without making prototypes too special.

I.R.Woollard@bnr.co.uk wrote:
> perhaps easier to read is:
> 
> "new point"

The problem with this is that we are back where we started: you are
more likely to accidently omit a word rather than add one. Omitting
"new" in your suggestion is as bad as forgetting "copy" now.



Copy-on-write slots would come in handy in several places, so I have
already thought a little about them. Here is one idea of how to get
something like it with Dynamic Inheritance. Actually, I doubt anyone
can do worse than this ;-)

traits _AddSlotsIfAbsent: ( | demo = () | )

traits demo _Define: ( | sharedA <- 100. 
                         print = ( _Print )
                     | )

prototypes _AddSlotsIfAbsent: ( | demo = (). demoCOW = () | )

demo _Define: ( | cowParent* <- demoCOW. 
                  localB <- 50 
              | )

demoCOW _Define: ( | realParent* = traits demo.
                     sharedA: v = ( cowParent: ( | realParent* = traits demo.
                                                   sharedA.
                                               | ) _Clone.
                                    sharedA: v
                                  )
                 | )

When you create a clone of "demo", it seems to have a sharedA slot and
a localB slot. If you try to change the value of the sharedA slot, you
get a new parent with its own sharedA slot, which acts as if the slot
had been added to demo's clone itself. The shared "sharedA" slot can
be changed, if needed, by "cowParent realParent sharedA: 99".

I would much rather an implementation using _AddSlots. The main problem
with my idea is that copying the slot is fast; using it is slow. This
is just the opposite of what we need, as a tipical use would have
slot copying initiated from a user action ( where we can wait a few
milliseconds ) while slot use would happen all the time. _AddSlots has
this characteristic, but it would lead to many objects that are alike
having different Maps. This would cause needless compilation wasting
both time and space. One solution would be to do "Map Merging" - when
_AddSlots or _DeleteSlots would create a new map, it would first check
all of the existing ones for an exact match, and simply use it instead
if there was. I did not check, but I think all maps are already linked
together ( for the garbage collector ) and that the whole memory is
scanned to change pointers if the object changed size. So this would
just make an already slow operation a little slower. This way, if you
add a "w" slot to an object and there already are other objects where
you have done this, it will share the old map and all compiled code.

David.Ungar@Eng.Sun.COM (David Ungar) writes:
> Personally, the next language I work on ;-) is going to have a much simpler
> model; I suspect both are too complicated.
> 
> -- Dave (responsible for many of the overcomplexities in Self and
> have learned the hard way) Ungar

Actually, Self's model is quite simple and elegant but some of us
are trying our best to complicate it :-)

All you have to do is to ignore us when we try to lead you astray :-) :-)

Regards,
- Jecel