[Oberon] Oberon for a C++ user.

Chris Burrows chris at cfbsoftware.com
Mon Oct 3 22:40:53 CEST 2016


Hi Andreas,

If you are planning on implementing such a scheme then make sure that the
user still has the ability to force modules to be unloaded if he understands
what he was doing. E.g. in the problematic scenarios described here where
two modules are mutually dependent it is not a problem to unload them as
long as both of them are unloaded. Otherwise in the process of developing /
testing new modules he would be forced to reboot every time he made a change
to one of the modules. I suspect you had already thought of that as you are
proposing a new (for Project Oberon) command Modules.Free, I assume that the
less restrictive System.Free could still be used as it is currently?

Regards,
Chris
 

> ________________________________________
> From: Andreas Pirklbauer [andreas_pirklbauer at yahoo.com]
> Sent: Monday, October 3, 2016 4:01 AM
> To: Skulski, Wojciech; Oberon List
> Subject: Re: [Oberon]  Oberon for a C++ user.
> 
> There is an alternative solution without reference counting: When
> unloading a module M using Modules.Free(M), one *could* traverse the
> heap object for object - just like the garbage collector does - and
> check whether the encountered objects contain procedure variables,
> and if so see whether the (addresses of) such procedure variables
> belong to M's code section (i.e. whether M.code <= address <
> M.imports). If there is at least one such procedure variable, simply
> don't unload M. It's practically the same code as the garbage
> collector (so it could in fact be be combined with it), except that
> is it merely used to *check* whether the addresses of procedure
> variables in heap records belong to (the code section of) module M.
> That too I have implemented on Ceres (in NS32032 assembly code) a
> long time ago, and now that the garbage collector is itself
> implemented in Oberon (see procedures Kernel.Mark and Kernel.Scan),
> it would be straightforward to bring the code forward to Oberon 2013
> - one really just needs to create a modified version of Kernel.Mark
> and call it from within procedure Modules.Free. But again, this would
> create a non-negligible overhead during unloading of a module - every
> time a module M needs to be unloaded, the *entire* heap would need to
> be traversed, and this just to find out whether one or more of its
> elements contain a procedure variable whose memory addresses belong
> to module M's code (this inefficiency can be remedied though in
> various ways, e.g. by setting a flag in module M when an assignment
> of M.proc to a procedure variable is made, but still, this would make
> both assignments and unloading rather cumbersome operations). But it
> is definitely doable. Note that performance is not really an issue,
> because unloading of modules should be rare - and could be preceded
> by a garbage collection run as a matter of course (in which case one
> just needs to slightly adapt *its* code).
> 
> 
> Thus, it is doable and has in fact been implemented. But I have yet
> to see a truly satisfactory and elegant solution to this problem -
> and this is why I haven’t brought the code forward to Oberon 2013
> (and Experimental Oberon 2013).
> 
> 
> Andreas
> 
> ________________________________
> From: "Skulski, Wojciech"
> <skulski at pas.rochester.edu<mailto:skulski at pas.rochester.edu>>
> To: Andreas Pirklbauer
> <andreas_pirklbauer at yahoo.com<mailto:andreas_pirklbauer at yahoo.com>>;
> ETH Oberon and related systems
> <oberon at lists.inf.ethz.ch<mailto:oberon at lists.inf.ethz.ch>>
> Sent: Monday, October 3, 2016 9:07 AM
> Subject: RE: [Oberon] Oberon for a C++ user.
> 
> Andreas:
> 
> the problem IMHO is in the operator :=, which is overloaded. The
> procedure variables are not a variables in the usual sense. The
> operator := should not apply to them.
> 
> A regular variable has a value. The value is passive. It gets acted
> upon by a client. The variable is not doing anything on its own.
> Somebody is doing something with the variable (somebody is using its
> value for some goal).
> 
> IF var1 = var2 THEN... (*passive role of the variables*)
> 
> The procedure variable has a value (the address to jump to), and also
> a behavior. The value is passive, but the behavior is active. The
> value is retained after unloading the implementation, but the
> behavior is damaged. This is the problem.
> 
> The value (the address) is not that important. Yes, you can use it in
> comparisons:
> 
> IF proc1 = proc2 THEN... (*passive role of the procedure variables*)
> 
> Note that after unloading the implementations of the proc1 and proc2,
> you can still make the comparison. Both proc1 and proc2 are perfectly
> valid in the passive sense. Their code is gone, but their passive
> values (addresses) are perfectly OK.
> 
> But this is not why procedure variables are important. We want their
> behaviors. And this gets damaged upon unloading.
> 
> In order to cure the problem, the operator :=should not be permitted
> with procedure variables. There needs to be another, separate
> operator which will assign procedure variables and also take care of
> the reference counting.
> 
> ASSIGN (procvar, Mod.Proc)
> 
> I think that separating both operators := and ASSIGN will make sense,
> because regular variables are not posing the problem which procedure
> variables are posing.
> 
> The counterpart of ASSIGN would be RETRACT (or some better name).
> Since you re not allowed to use := with procedure variables, you
> could not write
> 
> procvar := NIL; (*not allowed*)
> 
> You would have to say
> 
> RETRACT (procvar); (*takes care of the references*)
> 
> I hope this proposition makes sense.
> 
> W.
> 
> ----------------------------
> 
> Chris, Joerg:
> 
> that is exactly the problem: assigning a procedure of a *client*
> module to a procedure variable of an *imported* module, and then
> unloading the client module - leaving the procedure variable in the
> imported module dangling.
> 
> Assigning a procedure of a client module to a variable of an imported
> "base" module is in fact the standard way the Oberon system itself
> employs procedure variables to implement the viewer system in an
> object-oriented style.
> 
> For example, module TextFrames (the client) installs a handler
> (procedure TextFrames.Handle) in the field F.handle of text frame F
> (see TextFrames.NewText and TextFrames.Open for the details), where
> the record field F.handle is declared as a procedure variable in the
> "base" module Viewers (see Viewers.ViewerDesc), which also manages
> the viewer data structure (see procedure Viewers.Open).
> 
> Except that of course in the case of the Oberon system, the "client"
> module TextFrames *never* gets unloaded, so this is not a problem
> there. Thus, the burden is on the user to make sure that such modules
> never get unloaded.
> 
> It is of course possible to implement a "procedure variable" counter
> - in analogy to the "module counter" employed in Oberon: each time an
> assignment to a procedure variable is made, the counter gets
> increased. But that would require changing the code generator
> compiler for assignments, and the module loader (Modules.Load) and
> unloader (Modules.Free). But I would refrain from introducing such
> complexity to the compiler and runtime system.
> 
> Andreas
> 
> Chris Burrows chris at
> cfbsoftware.com<https://urldefense.proofpoint.com/v2/url?u=http-
> 3A__cfbsoftware.com&d=CwMFaQ&c=kbmfwr1Yojg42sGEpaQh5ofMHBeTl9EI2eaqQZ
> hHbOU&r=uUiA_zLpwaGJIlq-_BM9w1wVOuyqPwHi3XzJRa-
> ybV0&m=uCo5T7FsqFpABSbe4qNj_9wO71q0cOpBhZcNZ79F_28&s=QDMllTxM_47yu_wV
> GCaG1gvwnYwA6fnPwzkt16mBJsc&e=>
> <mailto:oberon%40lists.inf.ethz.ch<https://urldefense.proofpoint.com/
> v2/url?u=http-
> 3A__40lists.inf.ethz.ch&d=CwMFaQ&c=kbmfwr1Yojg42sGEpaQh5ofMHBeTl9EI2e
> aqQZhHbOU&r=uUiA_zLpwaGJIlq-_BM9w1wVOuyqPwHi3XzJRa-
> ybV0&m=uCo5T7FsqFpABSbe4qNj_9wO71q0cOpBhZcNZ79F_28&s=JjFlvNvGq14Jc57Y
> njqQ1ua9Yx-
> tBWQ69_Y7UalxAa0&e=>?Subject=Re:%20Re%3A%20%5BOberon%5D%20Oberon%20fo
> r%20a%20C%2B%2B%20user.&In-Reply-
> To=%3C000a01d21ba8%24b97dc9d0%242c795d70%24%40cfbsoftware.com<https:/
> /urldefense.proofpoint.com/v2/url?u=http-
> 3A__40cfbsoftware.com&d=CwMFaQ&c=kbmfwr1Yojg42sGEpaQh5ofMHBeTl9EI2eaq
> QZhHbOU&r=uUiA_zLpwaGJIlq-_BM9w1wVOuyqPwHi3XzJRa-
> ybV0&m=uCo5T7FsqFpABSbe4qNj_9wO71q0cOpBhZcNZ79F_28&s=UF_1Pj7G3IOmGznn
> b4-LwXOfO9BuhZiedJF_e_vdyQw&e=>%3E>
> 
> ________________________________
> 
> > Joerg,
> >
> > OK - you may well be onto something here but it is incomplete as it
> > is. Something has to
> 
> > import Square so that the module body is executed, or you need an
> > exported procedure in
> 
> > Square that is called from the OS.
> 
> >
> > Note: there are a couple of semicolons missing and Init must be
> exported.
> 
> >
> > Chris.
> 
> > -----Original Message-----
> > From: Jörg Straube [mailto:joerg.straube at
> > iaeth.ch<https://urldefense.proofpoint.com/v2/url?u=http-
> 3A__iaeth.ch&
> >
> d=CwMFaQ&c=kbmfwr1Yojg42sGEpaQh5ofMHBeTl9EI2eaqQZhHbOU&r=uUiA_zLpwaGJ
> I
> > lq-_BM9w1wVOuyqPwHi3XzJRa-
> ybV0&m=uCo5T7FsqFpABSbe4qNj_9wO71q0cOpBhZcNZ
> > 79F_28&s=FN1J5KaD-V4B2ndfhuj-
> 8OpXXPH4thm38kn7TNpwkBw&e=><https://urlde
> > fense.proofpoint.com/v2/url?u=https-
> 3A__lists.inf.ethz.ch_mailman_list
> >
> info_oberon&d=CwMFaQ&c=kbmfwr1Yojg42sGEpaQh5ofMHBeTl9EI2eaqQZhHbOU&r=
> u
> > UiA_zLpwaGJIlq-_BM9w1wVOuyqPwHi3XzJRa-
> ybV0&m=UHr5AP3cXC2ZAXacD2dYANUhp
> >
> xDnR6gWosSpUd2oaRw&s=TWgxIZxS5z7mpZJDUj92ydjRoic3rLYdp0iN4Zb0ngQ&e=>]
> > Sent: Saturday, 1 October 2016 2:22 PM
> > To: chris at
> > cfbsoftware.com<https://urldefense.proofpoint.com/v2/url?u=http-
> 3A__cf
> >
> bsoftware.com&d=CwMFaQ&c=kbmfwr1Yojg42sGEpaQh5ofMHBeTl9EI2eaqQZhHbOU&
> r
> > =uUiA_zLpwaGJIlq-_BM9w1wVOuyqPwHi3XzJRa-
> ybV0&m=uCo5T7FsqFpABSbe4qNj_9w
> >
> O71q0cOpBhZcNZ79F_28&s=QDMllTxM_47yu_wVGCaG1gvwnYwA6fnPwzkt16mBJsc&e=
> >
> > <https://urldefense.proofpoint.com/v2/url?u=https-
> 3A__lists.inf.ethz.c
> >
> h_mailman_listinfo_oberon&d=CwMFaQ&c=kbmfwr1Yojg42sGEpaQh5ofMHBeTl9EI
> 2
> > eaqQZhHbOU&r=uUiA_zLpwaGJIlq-_BM9w1wVOuyqPwHi3XzJRa-
> ybV0&m=UHr5AP3cXC2
> >
> ZAXacD2dYANUhpxDnR6gWosSpUd2oaRw&s=TWgxIZxS5z7mpZJDUj92ydjRoic3rLYdp0
> i
> > N4Zb0ngQ&e=>; ETH Oberon and related systems
> 
> > Subject: Re: [Oberon] Oberon for a C++ user.
> >
> > Chris
> >
> > Here a possble example that might cause issues:
> >
> > MODULE Figure;
> > TYPE
> >  DrawProc = PROCEDURE;
> >  Figure = POINTER TO FigureDesc;
> >  FigureDesc = RECORD
> >    next: Figure;
> >    draw: DrawProc
> >  END;
> > VAR list: Figure;
> > PROCEDURE Init(d: DrawProc)
> >  VAR f: Figure;
> >  BEGIN
> >    NEW(f); f.next := list; list := f;
> >    f.draw := d
> >  END Init;
> > BEGIN list:= NIL END Figure.
> >
> > MODULE Square;
> > IMPORT Figure;
> > PROCEDURE DrawSquare;
> >  BEGIN (* do what ever you
> >    need to do to draw a square *)
> >  END DrawSquare
> > BEGIN
> >  Figure.Init(DrawSquare)
> > END Square.
> >
> > Now you could run Square and unload Square. The list in Figure has
> a
> > reference to unloaded code.
> >
> > J rg
> >
> 
> 
> --
> Oberon at lists.inf.ethz.ch mailing list for ETH Oberon and related
> systems https://lists.inf.ethz.ch/mailman/listinfo/oberon



More information about the Oberon mailing list