[Oberon] Oberon for a C++ user.

Andreas Pirklbauer andreas_pirklbauer at yahoo.com
Mon Nov 21 12:44:31 CET 2016


Felix,

I think we are completely on the same page.

Andreas


Sent from my iPhone

[Oberon] Oberon for a C++ user.

Felix Friedrich 
Andreas, Understood. Good point that indeed new types in the new module are in a way uncomparable to the old types of the old module. So, yes, you are right and the type test should not be changed. And also, I agree very much that the (academically interesting) discussion about the corner cases of module unloading is additionally merely relevant for the development phase and does not really apply to production systems. Regards Felix > Felix, > > Not sure I missed the point. I believe this *should* be the expected > behavior. In my code, the type test "emitted" by the "new" module are > only to be applied to "new" instances. So for all practical purposes > these *are* different types, yes. And the modules *are* different > (except that they happened to have shared the same name). > > > If it is your intention to make the type test in the "new" module > return also TRUE when applied to instances created by the "old" module > (and vice versa), then indeed this would require a different > implementation. Agree with that of course. > > > I have actually implemented THAT as well in a variant of Experimental > Oberon. It is not difficult (the compiler needs to emit different code > for type tests - code that simply runs through all module "versions", > old and new, and then performs the type test which is a simple address > comparison, and it's easy to know from the module list which modules > "belong together" version-wise). > > > But I have refrained from including that in the published version of > Experimental Oberon, for several reasons: > > > 1. It makes type tests more expensive > 2. Keeping "old" and "new" separate appears to be the cleaner > approach. As you said, it's no drama, really, and programmer can  > always handle it as well (eg by just adding another "id" field or > something). > 3. It would only be a real solution if one formally introduces the > notion of a "version" of a module - but that would in turn lead to > complex rules on when are two modules considered to be same, what if I > *want* multiple versions coexisting - and I didn't see the need for > that kind of complexity in the Oberon core - although it's perfectly > doable. > > > If you give me a good use case, I may reconsider and publish a variant > of EO that handles multiple module versions the way you see them. > > > Multiple versions in memory are mostly occurring during development > (so that's not a good use case), but not in production. The only > "good" use case I have seen so far is on a server environment in a > data center where one might indeed want to have multiple versions of, > say, an Oracle database, hosted on the *same* server. But with the > advent of virtual machines, even that use case has by and large gone > away long time ago. > > > But happy to be proven wrong. With a good use case, I'll publish... > > > Best, > Andreas -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.inf.ethz.ch/pipermail/oberon/attachments/20161121/e68047b4/attachment.html>
Previous message: [Oberon] Oberon for a C++ user.
Next message: [Oberon] Non Oberon code in Oberon
Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Oberon mailing list

> On 21 Nov 2016, at 10:08, Andreas Pirklbauer <andreas_pirklbauer at yahoo.com> wrote:
> 
> Felix,
> 
> Not sure I missed the point. I believe this *should* be the expected behavior. In my code, the type test "emitted" by the "new" module are only to be applied to "new" instances. So for all practical purposes these *are* different types, yes. And the modules *are* different (except that they happened to have shared the same name).
> 
> 
> If it is your intention to make the type test in the "new" module return also TRUE when applied to instances created by the "old" module (and vice  versa), then indeed this would require a different implementation. Agree with that of course.
> 
> 
> I have actually implemented THAT as well in a variant of Experimental Oberon. It is not difficult (the compiler needs to emit different code for type tests - code that simply runs through all module "versions", old and new, and then performs the type test which is a simple address comparison, and it's easy to know from the module list which modules "belong together" version-wise).
> 
> 
> But I have refrained from including that in the published version of Experimental Oberon, for several reasons:
> 
> 
> 1. It makes type tests more expensive
> 2. Keeping "old" and "new" separate appears to be the cleaner approach. As you said, it's no drama, really, and  programmer can always handle it as well (eg by just adding another "id" field or something).
> 3. It would only be a real solution if one formally introduces the notion of a "version" of a module - but that would in turn lead to complex rules on when are two modules considered to be same, what if I *want* multiple versions coexisting - and I didn't see the need for that kind of complexity in the Oberon core - although it's perfectly doable.
> 
> 
> If you give me a good use case, I may reconsider and publish a variant of EO that handles multiple module versions the way you see them.
> 
> 
> Multiple versions in memory are mostly occurring during development (so that's not a good use case), but not in production. The only "good" use case I have seen so far is on a server environment in a data center where one might indeed want to have multiple versions of, say, an Oracle database, hosted on the *same* server. But with the advent of virtual machines, even that use case has by and large gone away long time ago.
> 
> 
> But happy to be proven wrong. With a good use case, I'll publish... 
> 
> 
> Best,
> Andreas
> 
> 
> Felix Friedrich felix.friedrich at inf.ethz.ch 
> Mon Nov 21 08:40:45 CET 2016
> Previous message: [Oberon] Oberon for a C++ user.
> Next message: [Oberon] Non Oberon code in Oberon
> Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
> Andreas Although it is nice that it works like this, your code example misses the point of the previous code: there are two different variants  coexisting of a singleton object (a module) with the consequence that a  type test or type guard on instances of the "old" module emitted from a "new" module does not work any more. Eventually it is not a drama because no practically important examples seem to exist. Moreover with some indirection on the type descriptors it would be easy to solve. But for the sake of purity.... Kind regards Felix > Felix, > > below is the output (under Experimental Oberon) of a modified set of > your modules A, B, and C (source code appended below). > > > It nicely shows that C.Delete selects the "right" module B, i.e. > either the "old B" (here called B*), or the "new B" (here called B). > The type descriptors and the code of module B* (removed from module > list) is still available in memory. > > > All type tests automatically select the "right" type descriptor and > the "old B" is only removed from memory when no more references from > the remaining modules exist. > > > Andreas > > > COMMAND SEQUENCE (see below for source code of A, B, and C): > > B.Insert 1 ... insert elemt from old B > System.ShowModules ... B is the old B > System.Free B/f ... remove old B from module list, don't > release memorz > System.ShowModules ... B* is the old B > B.Insert 2 ... new B > System.ShowModules ... B* is the old B, B is the new B > C.Delete 1 ... deletes the element created by the old B > C.Delete 2 ... deletes the element created by the old B > C.Init ... clears the data structure rooted in A.root > Modules.Collect ... collects B* (no longer referenced) > System.ShowModules ... module B* no longer in memory > > GENERATED OUTPUT: > > 1) B.Insert 1 > insert element from module B module descriptor at 000212C0 > > 2) System.ShowModules > B 000212C0 000213D0 0 > A 00020F60 00020FDC 1 > System 0001CB80 0001D320 0 > ... > > 3) System.Free B/f > B unloading: removing from module list (references exist) > > 4) System.ShowModules > *B 000212C0 000213D0 0 (removed from module list) > A 00020F60 00020FDC 1 > System 0001CB80 0001D320 0 > ... > > 5) B.Insert 2 > insert element from module B module descriptor at 00021800 > > 6) System.ShowModules > B 00021800 00021910 0 > *B 000212C0 000213D0 0 (removed from module list) > A 00020F60 00020FDC 2 > System 0001CB80 0001D320 0 > ... > > 7) C.Delete 1 > type of t is T from module B* module descriptor at 000212C0 > > 8) C.Delete 2 > type of t is T from module B module descriptor at 00021800 > > 9) C.Init + Modules.Collect + System.ShowModules > B 00021800 00021910 0 > A 00020F60 00020FDC 2 > System 0001CB80 0001D320 0 > ... > > ---------------------------------------------------------------------------------------------------- > > MODULE A; (*base module managing data structure of base type T*) > TYPE T* = POINTER TO R; > P* = PROCEDURE (t: T); > R* = RECORD i*: INTEGER; > close*: P; > next: T > END ; > > VAR root*: T; > > PROCEDURE Find*(i: INTEGER): T; > VAR t: T; > BEGIN t := root; > WHILE (t # NIL) & (t.i # i) DO t := t.next END ; > RETURN t > END Find; > > PROCEDURE Insert*(t: T); > VAR s: T; > BEGIN s := Find(t.i); > IF s = NIL THEN t.next := root; root := t END > END Insert; > > PROCEDURE Delete*(i: INTEGER); > VAR s, t: T; > BEGIN t := root; s := t; > WHILE (t # NIL) & (t.i # i) DO s := t; t := t.next END ; > IF t # NIL THEN t.close(t); > IF t = root THEN root := NIL ELSE s.next := t.next END > END > END Delete; > > PROCEDURE Init*; > BEGIN root := NIL > END Init; > > BEGIN Init > END A. > > -------------------------------------- > > MODULE B; (*client of A, defining extensions of A.T*) > IMPORT A, Modules, Texts, Oberon; > TYPE T* = POINTER TO R; > R* = RECORD (A.R) j: INTEGER END; > > VAR M: Modules.Module; > W: Texts.Writer; > > PROCEDURE Close*(t: A.T); > VAR S: Texts.Scanner; > BEGIN > IF (t IS T) & (M # NIL) THEN > Texts.WriteString(W, "type of t is T from module "); > Texts.WriteString(W, M.name); > Texts.WriteString(W, " module descriptor at "); Texts.WriteHex(W, ORD(M)); > Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf) > END > END Close; > > PROCEDURE Insert*; > VAR S: Texts.Scanner; t: T; > BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); > Texts.Scan(S); > IF S.class = Texts.Int THEN NEW(t); t.i := S.i; t.close := Close; > A.Insert(t); > Texts.WriteString(W, "insert element from module "); > Texts.WriteString(W, M.name); > Texts.WriteString(W, " module descriptor at "); Texts.WriteHex(W, ORD(M)); > Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf) > END > END Insert; > > PROCEDURE Init*; > BEGIN > END Init; > > BEGIN Texts.OpenWriter(W); M := Modules.root; > WHILE (M # NIL) & (M.name # "B") DO M := M.next END > END B. > > -------------------------------------- > > ODULE C; (*tool module*) > IMPORT A, Texts, Oberon; > > VAR W: Texts.Writer; > > PROCEDURE Delete*; > VAR S: Texts.Scanner; > BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); > Texts.Scan(S); > IF S.class = Texts.Int THEN A.Delete(S.i) END > END Delete; > > PROCEDURE Init*; > BEGIN > END Init; > > BEGIN Texts.OpenWriter(W) > END C. > > ---------------- > > > > > -- > Oberon at lists.inf.ethz.ch mailing list for ETH Oberon and related systems > https://lists.inf.ethz.ch/mailman/listinfo/oberon -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.inf.ethz.ch/pipermail/oberon/attachments/20161121/0e84a2c6/attachment.html>
> Previous message: [Oberon] Oberon for a C++ user.
> Next message: [Oberon] Non Oberon code in Oberon
> Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
> More information about the Oberon mailing list
> 
> Sent from my iPhone
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.inf.ethz.ch/pipermail/oberon/attachments/20161121/b351f958/attachment.html>


More information about the Oberon mailing list