[Oberon] Oberon for a C++ user.

Peter Froehlich phf at acm.org
Mon Oct 3 09:30:57 CEST 2016


Hi there,

Sorry, I have not done any Oberon work in 13+ years but when I see a
suggestion such as ASSIGN and RETRACT to "reference count" procedures,
I just shiver. (Let's not mess with the language if we don't have to
would be my motto.)

I believe what you really want to avoid the "dangling procedure
variable" problem is a garbage collector that deals with modules. It
would basically be an RCU scheme. When you unload a module, it's
removed from the mapping that associates some module name with the
actual data/code used behind the scenes. However, that data/code is
NOT actually thrown out of memory at that time, instead it sticks
around until the last *reference* to it is gone, meaning here until
the last procedure variable referring to this module's code has been
reassigned. The usual := way.

I'd be interested to hear why that wouldn't solve your issues.

Regards,
Peter

On Mon, Oct 3, 2016 at 3:07 AM, Skulski, Wojciech
<skulski at pas.rochester.edu> wrote:
> 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 <mailto:oberon%40lists.inf.ethz.ch?Subject=Re:%20Re%3A%20%5BOberon%5D%20Oberon%20for%20a%20C%2B%2B%20user.&In-Reply-To=%3C000a01d21ba8%24b97dc9d0%242c795d70%24%40cfbsoftware.com%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=https-3A__lists.inf.ethz.ch_mailman_listinfo_oberon&d=CwMFaQ&c=kbmfwr1Yojg42sGEpaQh5ofMHBeTl9EI2eaqQZhHbOU&r=uUiA_zLpwaGJIlq-_BM9w1wVOuyqPwHi3XzJRa-ybV0&m=UHr5AP3cXC2ZAXacD2dYANUhpxDnR6gWosSpUd2oaRw&s=TWgxIZxS5z7mpZJDUj92ydjRoic3rLYdp0iN4Zb0ngQ&e=>]
>> Sent: Saturday, 1 October 2016 2:22 PM
>> To: chris at cfbsoftware.com<https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.inf.ethz.ch_mailman_listinfo_oberon&d=CwMFaQ&c=kbmfwr1Yojg42sGEpaQh5ofMHBeTl9EI2eaqQZhHbOU&r=uUiA_zLpwaGJIlq-_BM9w1wVOuyqPwHi3XzJRa-ybV0&m=UHr5AP3cXC2ZAXacD2dYANUhpxDnR6gWosSpUd2oaRw&s=TWgxIZxS5z7mpZJDUj92ydjRoic3rLYdp0iN4Zb0ngQ&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



-- 
Peter H. Froehlich <http://www.cs.jhu.edu/~phf/>
Senior Lecturer | Director, Johns Hopkins Gaming Lab

The views stated in this communication are my own and do not express
the position or views of The Johns Hopkins University or the
Association for Computing Machinery.


More information about the Oberon mailing list