======================================================================= 1 === Date: 1 Apr 93 09:45:47 GMT From: os102@cl.cam.ac.uk (Oliver Stephens) Subject: Re: thread operation In article <1993Apr1.030018.616@uxmail.ust.hk>, clfung@cs.ust.hk (Fung Chi Leun g) writes: |> Hello, |> |> 1. When I call Usocket.accept(...) inside a thread, the |> thread scheduler will hang up at the statement until |> the Usocket.accept(...) is reutrn. In my previous |> testings on the thread opertaions, the scheduler will |> pass the control to the other threads alternatively after |> the time slice of each thread is expired. However, the |> the thread calling Usocket.accept will not be suspended |> by the scheduler and the other threads do not have their |> turns to run. |> |> This problem is solved when I set the Usocket.accept(...) to |> a non-blocking operation and the thread scheduler will work |> properly. I am curious that does the thread support blocking |> operations? If not, what are the alternatives or necessary |> procedures can be used? |> The problem with a blocking call like this is that the whole process is suspended by the UNIX scheduler until the operation completes. The M3 runtime thread stuff does not know about this kind of blocking operation - the kind that is due to the "wait" command. You could teach it about the Unix "wait" command, getting it to do a non-blocking wait to determine when the thread can be re-activated, but the problem is many unix commands have a "wait" inside them (like "system") - I'm not sure there are non-waiting equivalents of all of these. Below, I have included my solution to the problem that the "system" command halts the process until completion. I wrote this because I wanted to do a "system" command at the response of a button press from a user interface, but I didn't want the interface to hang until it was complete. It may give you some pointers. DISCLAIMER: I only wrote this the other day - I am not convinced it is bomb-proof yet. ---+--- FILE Uwait.i3 ---+--- UNSAFE INTERFACE Uwait ; (* stuff which should be in Uexec but isn't + mktemp() because I needed it *) FROM Ctypes IMPORT Int, IntStar, CharStar, CharStarStar ; <* EXTERNAL *> PROCEDURE waitpid(pid : Int ; statusp : IntStar ; options : Int) : Int ; <* EXTERNAL *> PROCEDURE mktemp(template : CharStar) : CharStar ; CONST WNOHANG = 1 ; WUNTRACED = 2 ; END Uwait. ---+--- FILE SystemCmd.i3 ---+--- (* Author : Olly Stephens *) INTERFACE SystemCmd ; (* To use the UNIX "system" command, you usually have to turn off thread preemption. Even if you don't have to do this, the "system" commmand does not return your process to its normal state until the command has been completed and so pre-emption is effectively turned off. This interface provides a method of executing shell commands without forsaking preemption. There are two procedures - "Do" will execute the command given in "cmd" and returns the status. "Start" starts off a similar execution but returns immediately. It calls back on the "callback" closure when the command is complete - this is especially useful inside button action procedures of a user interface for example, because you want to minimise your time inside them as the VBT tree is locked on entry. The "Start" procedure returns the "Thread.T" which is performing the shell commands. To abort the commands, alert the thread by calling "Thread.Alert". To wait for completion of the commands (or of the aborting), call "Thread.Join". The value returned by "Thread.Join" will be a "REF INTEGER" which holds the result of the execution. The result will be: -1 if the procedures failed to execute the commands -2 if "wait" returns a negative value (check errno) -3 if the shell was interrupted by a signal -4 if the command was aborted (by Thread.Alert) 0 if the shell command succeeded 1..LAST(INTEGER) if the shell command failed *) IMPORT Thread ; PROCEDURE Do(cmds : TEXT) : INTEGER ; TYPE Callback = OBJECT METHODS done(result : INTEGER) END ; PROCEDURE Start(cmds : TEXT ; callback : Callback) : Thread.T ; END SystemCmd. ---+--- FILE SystemCmd.m3 ---+--- UNSAFE MODULE SystemCmd ; IMPORT Ctypes, Dir, FileStream, M3toC, RTThread, Thread, Time, Uexec, Unix, Usignal, Uwait, Word, Wr ; TYPE Closure = Thread.Closure BRANDED OBJECT cmd : TEXT ; callback : Callback := NIL OVERRIDES apply := Apply END ; PROCEDURE Apply(c : Closure) : REFANY = VAR file : TEXT ; VAR fileS : Ctypes.CharStar ; VAR wr : Wr.T ; VAR argv := ARRAY [0..1] OF Ctypes.CharStar { NIL, NIL } ; VAR waitstate, status, pid : INTEGER ; VAR result := NEW(REF INTEGER) ; BEGIN fileS := Uwait.mktemp(M3toC.CopyTtoS("/tmp/scXXXXXX")) ; file := M3toC.StoT(fileS) ; argv[0] := fileS ; TRY TRY wr := FileStream.OpenWrite(file) ; TRY Wr.PutText(wr, "#!/bin/sh\n\n") ; Wr.PutText(wr, c.cmd) ; Wr.PutChar(wr, '\n') FINALLY Wr.Close(wr) ; EVAL Unix.chmod(fileS, 8_700) END ; pid := Unix.vfork() ; CASE pid OF -1 => result^ := -1 | 0 => RTThread.disallow_sigvtalrm() ; IF (Uexec.execv(fileS, ADR(argv)) < 0) THEN Unix.exit(1) ELSE <* ASSERT FALSE *> END ELSE REPEAT waitstate := Uwait.waitpid(pid, ADR(status), Uwait.WNOHANG) ; IF (waitstate = 0) THEN IF (Thread.TestAlert()) THEN EVAL Usignal.kill(pid, Usignal.SIGKILL) ; RAISE Thread.Alerted END ; Time.LongPause(5) END UNTIL (waitstate # 0) ; IF (waitstate < 0) THEN result^ := -2 ELSE IF (Word.And(status, 16_7F) # 0) THEN result^ := -3 ELSE result^ := Word.And(status, 16_FF00) DIV 16_80 END END END FINALLY M3toC.FreeS(fileS) ; Dir.Delete(file) END EXCEPT Thread.Alerted => result^ := -4 ELSE result^ := -1 END ; IF ((result^ # -4) AND (c.callback # NIL)) THEN c.callback.done(result^) END ; RETURN result END Apply ; PROCEDURE Do(cmd : TEXT) : INTEGER = VAR result : REF INTEGER ; BEGIN result := Thread.Join(Thread.Fork(NEW(Closure, cmd := cmd))) ; RETURN result^ END Do ; PROCEDURE Start(cmd : TEXT ; callback : Callback) : Thread.T = BEGIN RETURN Thread.Fork(NEW(Closure, cmd := cmd, callback := callback)) END Start ; BEGIN END SystemCmd. ------------------------------------------------------------------------- Olly Stephens oliver.stephens@cl.cam.ac.uk Computer Laboratory University of Cambridge Loved you there and then, and now like a sheep United Kingdom - Van Morrison ======================================================================= 2 === Date: 1 Apr 1993 09:01:01 GMT From: laverman@cs.rug.nl (Bert Laverman) Subject: SRC-m3 vs -O If I remember correctly, there have been some problems with using optimization on the C compiler pass, some versions ago. Is there anybody using -O with the current version auccessfully? It would save considerable on size of the libraries... Bert -- #include Bert Laverman, Dept. of Computing Science, Groningen University Friendly mail to: laverman@cs.rug.nl The rest to: /dev/null ======================================================================= 3 === Date: 1 Apr 93 06:34:26 GMT From: tas@cs.uq.oz.au (Tasman Hayes) Subject: new vbtkit and formsvbt docs on gatekeeper.dec.com I don't seem to be able (to have access) to ftp the new formsvbt and vbtkit documentation at gatekeeper.doc.com in pub/DEC/Modula-3/contrib. Do I have software problems OR are they not meant for public consumption OR have their file permissions simply been incorrectly set? Thanks, Tasman Hayes ======================================================================= 4 === Date: 1 Apr 93 10:20:28 GMT From: os102@cl.cam.ac.uk (Oliver Stephens) Subject: Re: thread operation In article <1993Apr1.094547.20409@infodev.cam.ac.uk>, os102@cl.cam.ac.uk (Olive r Stephens) writes: |> In article <1993Apr1.030018.616@uxmail.ust.hk>, clfung@cs.ust.hk (Fung Chi L eung) writes: |> |> Hello, |> |> |> |> 1. When I call Usocket.accept(...) inside a thread, the |> |> thread scheduler will hang up at the statement until |> |> the Usocket.accept(...) is reutrn. In my previous |> |> testings on the thread opertaions, the scheduler will |> |> pass the control to the other threads alternatively after |> |> the time slice of each thread is expired. However, the |> |> the thread calling Usocket.accept will not be suspended |> |> by the scheduler and the other threads do not have their |> |> turns to run. |> |> |> |> This problem is solved when I set the Usocket.accept(...) to |> |> a non-blocking operation and the thread scheduler will work |> |> properly. I am curious that does the thread support blocking |> |> operations? If not, what are the alternatives or necessary |> |> procedures can be used? |> |> |> |> The problem with a blocking call like this is that the whole process is |> suspended by the UNIX scheduler until the operation completes. The M3 runti me |> thread stuff does not know about this kind of blocking operation - the kind |> that is due to the "wait" command. Ooops. Before I get flamed, I better change what I said. I've just realised that Leung is talking about "Usocket.accept" which is not bound by the "wait" command. What I said in my last message is correct for commands like "system" so I don't regret saying it :-) File and Socket based calls can be handled by the thread package through the use of the RTScheduler.IOSelect or RTScheduler.IOAlertSelect. These procedures are functionally equivalent to the unix "select" command, except they do not prevent other threads from running. To quote from the "accept" man page: It is possible to select(2) a socket for the purposes of doing an accept() by selecting it for read. ------------------------------------------------------------------------- Olly Stephens oliver.stephens@cl.cam.ac.uk Computer Laboratory University of Cambridge Loved you there and then, and now like a sheep United Kingdom - Van Morrison ======================================================================= 5 === Date: Thu, 1 Apr 1993 03:00:18 GMT From: clfung@cs.ust.hk (Fung Chi Leung) Subject: thread operation Hello, Recently, I am developing a distrubuting system using M3 with a lot of thread operations and I come across several questions about the thread: 1. When I call Usocket.accept(...) inside a thread, the thread scheduler will hang up at the statement until the Usocket.accept(...) is reutrn. In my previous testings on the thread opertaions, the scheduler will pass the control to the other threads alternatively after the time slice of each thread is expired. However, the the thread calling Usocket.accept will not be suspended by the scheduler and the other threads do not have their turns to run. This problem is solved when I set the Usocket.accept(...) to a non-blocking operation and the thread scheduler will work properly. I am curious that does the thread support blocking operations? If not, what are the alternatives or necessary procedures can be used? 2. My second question is about the performance of the thread. Since I want to give higher priority ( in terms of CPU time ) to some threads, I will call Thread.Yield( ) to pass the control from some lower priority threads to higher priority threads, but the performance of overall system does not match my expectation. :) Is there any comment on that? Is it a right way to use Thread.Yield( ) in doing such priority tasks? 3. The last question is: Any hint of using thread operations efficiently? ( other than the stuff covered in the System Programming book ) Thanks in advance. Any reply would be highly appreciated. -- Leung [ Chi-Leung Fung ] << E-Mail: clfung@cs.ust.hk ## Phone: (852) 358 7023 >> ======================================================================= 6 === Date: Thu, 1 Apr 93 18:04:29 GMT From: mjordan@src.dec.com (Mick Jordan) Subject: Re: SRC-m3 vs -O I can only speak for the DECstations, but I have found gcc v2.2 to be very reli able in its -O2 mode. In fact it is now my C compiler of choice, partly because the Mips cc exhibits buggy behaviour on large programs. You get a factor of 2 speed up using -O2, and a noticeable reduction in code size. Mick Jordan ======================================================================= 7 === Date: Thu, 01 Apr 93 09:12:52 -0800 From: mhb@src.dec.com Subject: Re: new vbtkit and formsvbt docs on gatekeeper.dec.com Yes, there are new versions of the VBTkit and FormsVBT manuals in gatekeeper.pa.dec.com in pub/DEC/Modula-3/contrib. They seem to have the correct permissions: % ls -l -r--r--r-- 1 root 503965 Mar 25 16:15 formsvbt.25Mar93.ps.Z -r--r--r-- 1 root 109243 Mar 26 14:57 formsvbt.AppC.26Mar93.ps.Z -r--r--r-- 1 root 241681 Mar 25 16:14 vbtkit.25Mar93.ps.Z I just tried to ftp these files, and had no problems. If you are still having problems, send email to m3-request@src.dec.com. These files are not part of Modula-3/release; they are meant for semi-public consumption. We have made extensive changes to VBTkit and a slew of small changes to FormsVBT. We are using the new software here at SRC, and it will probably be part of the next release of M3 onto gatekeeper. Jim Meehan and I plan to freeze VBTkit and FormsVBT for the foreseeable future (of course, we'll make bug fixes and we encourage other people to add to both packages!). Part of freezing the software is to also freeze the documentation and publish it like the Trestle reference manual. Before doing so, we've asked a number of VBT-enthusiats to review the manuals. Storing them in Modula-3/contrib is the easiest way to make the documents available for non-DEC folks. Other people are welcome to look them over too, but, since they do not correspond to the released software, non-experienced VBT-hackers might have a difficult time with them. Marc ======================================================================= 8 === Date: Thu, 1 Apr 1993 15:21:34 GMT From: dagenais@alberich.vlsi.polymtl.ca (Michel Dagenais) Subject: Re: 1Mb Hello World...!? Is this normal? Following the release of DEC SRC M3 2.07, shared libraries were discussed on this newsgroup. I then believed that postprocessing libraries to make them dynamic would reduce the possibilities of sharing memory, when two or more m3 programs execute, but that the execution time would not be affected. The recent postings led me to recompile eeeeeeverything from scratch with real "position independent code" shared libraries. The results are very interesting. The total elapsed time to compile, link and run a 100 lines program that uses trestle (a very large library) goes from 2:46 minutes to 50 seconds, mainly because of reduced i/o and dynamic linking time. After all, a C++ program using InterViews would probably take just about as much time even with a native compiler because of the zillions of nested include files usually involved. Modula3-2.07 with postprocessed libraries on a lightly loaded Sparc 2: froh> time m3 -o DrawRect DrawRect.m3 -lm3ui -lm3X11R4 -lX11 26.9user 8.39system 2:00.06elapsed 28%CPU (0text+5405data 5320max)k 428inputs+79outputs (716major+3095minor)pagefaults 0swaps froh> ls -als DrawRect 80 -rwxrwxr-x 1 dagenais analyste 81920 Oct 15 17:27 DrawRect* froh> time ./DrawRect 12.23user 2.23system 0:46.91elapsed 30%CPU (0text+4203data 4232max)k 38inputs+3outputs (385major+1230minor)pagefaults 0swaps Modula3-2.11 with real shared libraries under pretty much the same conditions: froh> time m3 -o DrawRect DrawRect.m3 -lm3ui -lm3X11R4 -lX11 24.74user 3.88system 0:40.66elapsed 70%CPU (0text+5904data 5764max)k 247inputs+26outputs (643major+2273minor)pagefaults 0swaps froh> ls -als DrawRect 64 -rwxrwxr-x 1 dagenais 65536 Apr 1 10:13 DrawRect* froh> time ./DrawRect 2.80user 0.85system 0:10.22elapsed 35%CPU (0text+2459data 3744max)k 52inputs+1outputs (364major+454minor)pagefaults 0swaps -- --------------------------------------------------------------------- Prof. Michel Dagenais dagenais@vlsi.polymtl.ca Dept of Electrical and Computer Eng. Ecole Polytechnique de Montreal tel: (514) 340-4029 --------------------------------------------------------------------- ======================================================================= 9 === Date: Thu, 1 Apr 93 17:42:53 GMT From: Eric Muller Subject: Modula-3 Frequently Asked Questions (FAQ) Archive-name: Modula-3-faq Last-modified: Apr 1 1993 Modula-3 Frequently Asked Questions =================================== 1. The language 1.1. What is Modula-3 ? 1.2. Is Modula-3 a superset of Modula-2 ? 2. The documentation 2.1. Where can I get a description of Modula-3 ? 2.2. Where can I get other information on Modula-3 ? 3. The implementations 3.1. Where can I get an implementation ? 3.2. What is SRC Modula-3 ? 3.3. What is m3pc ? 3.4. What is GNU Modula-3 ? 4. FTP 4.1. What if I don't have ftp access ? 5. Contributing 5.1. Can I contribute Modula-3 software ? 1.1. What is Modula-3 ? The goal of Modula-3 is to be as simple and safe as it can be while meeting the needs of modern systems programmers. Instead of exploring new features, we studied the features of the Modula family of languages that have proven themselves in practice and tried to simplify them into a harmonious language. We found that most of the successful features were aimed at one of two main goals: greater robustness, and a simpler, more systematic type system. Modula-3 descends from Mesa, Modula-2, Cedar, and Modula-2+. It also resembles its cousins Object Pascal, Oberon, and Euclid. Modula-3 retains one of Modula-2's most successful features, the provision for explicit interfaces between modules. It adds objects and classes, exception handling, garbage collection, lightweight processes (or threads), and the isolation of unsafe features. 1.2. Is Modula-3 a superset of Modula-2 ? No; valid Modula-2 programs are not valid Modula-3 programs. However, there is a tool to help convert Modula-2 programs to Modula-3. 2.1. Where can I get a description of Modula-3 ? The definition of Modula-3 is contained in: System Programming with Modula-3 Edited by Greg Nelson Prentice Hall Series in Innovative Technology ISBN 0-13-590464-1 L.C. QA76.66.S87 1991 also known as SPwM3. Here is the table of contents: 1. Introduction 2. Language Definition 3. Standard Interfaces 4. An Introduction to Programming with Threads 5. Thread Synchronization: A Formal Specification 6. I/O Streams: Abstract Types, Real Programs 7. Trestle Window System Tutorial 8. How the Language Got its Spots Chapters 2 and 3 have been reprinted in Sigplan Notices, Volume 27, Number 8, August 1992, pp 15-42. Sam Harbison has written a more tutorial book about Modula3: Modula-3 Samuel P. Harbison Prentice Hall, 1992 ISBN 0-13-596396-6 The errata sheet is available via anonymous ftp from gatekeeper.dec.com in pub/DEC/Modula-3/errata. 2.2. Where can I get other information on Modula-3 ? There is a Usenet newsgroup, comp.lang.modula3. The archives of that group are available via anonymous ftp from gatekeeper.dec.com in pub/DEC/Modula-3/comp.lang.modula3. If you do not have access to Usenet, there is a relay mailing list; send a message to m3-request@src.dec.com to be added to it. There are a couple high-level overview articles available: "Modula-3", Sam Harbison, Byte, Vol. 15, No. 12, November 1990, pp 385+. "Safe Programming with Modula-3", Sam Harbison, Dr. Dobb's Journal, Vol. 17, No. 10, October 1992, pp 88+. A description of the Modula-3 type system is in "The Modula-3 Type System", Luca Cardelli, Jim Donahue, Mick Jordan, Bill Kalsow, Greg Nelson, Conference Record of the Sixteenth Annual ACM Symposium on Principles of Programming Languages (POPL), Austin Texas, January 11-13 1989, pp 202-212. The Trestle window system toolkit and higher-level FormsVBT toolkit, available with Modula-3, are documented in the following reports: "Trestle Reference Manual", Mark S. Manasse and Greg Nelson, SRC Research Report 68, December 1991. "Trestle Tutorial", Mark S. Manasse and Greg Nelson, SRC Research Report 69, May 1, 1992. "The FormsVBT Reference Manual", Marc H. Brown and James R. Meehan, (soon to be SRC Research Report ??). These reports can be ordered by e-mail; send your request to src-reports@src.dec.com. 3.1. Where can I get an implementation ? Two implementations are available, SRC Modula-3 and a PC version of it (m3pc). Work is also progressing on GNU Modula-3. 3.2. What is SRC Modula-3 ? SRC Modula-3 was built by the DEC Systems Reseach Center and is available via anonymous ftp from gatekeeper.dec.com in pub/DEC/Modula-3/release. The current version, 2.11, implements the language defined in SPwM3. There are versions for the following machines: AIX386 IBM PC running AIX/PS2, AP3000 Apollo DN4500 running Domain/OS ARM Acorn R260 running RISC iX 1.21 DS3100 DECstation 3100 and 5000 running Ultrix 4.0 and 4.2 HP300 HP 9000/300 running HP-UX 8.0 HPPA HP 700/800 running HP-UX 8.0 IBMR2 IBM R6000 running AIX 3.1, IBMRT IBM RT running IBM/4.3, NEXT NeXT running ? OKI Okidata 7300 (i860) running AT&T SVR4.0 SPARC SPARCstation running SunOS 4.1.x SUN3 SUN3 running SunOS SUN386 Sun 386i running SunOS 4.0.1 UMAX Encore Multimax running UMAX 4.3 (R4.1.1) VAX VAX running Ultrix 3.1 SRC Modula-3 includes a user manual, compiler, runtime library, some libraries and a few other goodies (see below). The compiler generates C as an intermediate language and should be fairly easy to port. Except for the very lowest levels of the thread implementation, the entire system is written in Modula-3. 3.3. What is m3pc ? m3pc is available via anonymous ftp from gatekeeper.dec.com in pub/DEC/Modula-3/contrib/m3pc. From: laszlo@post.ifi.uni-klu.ac.at (Prof.Dr.Laszlo BOESZOERMENYI) Subject: M3 pn PC Date: 8 Mar 1993 13:13:52 GMT The Modula-3 system ported by us on the PC and available on the gatekeeper, runs with MSDOS, gnu c compiler and djgpp memory manager (detailed description in the read me file). You may compile, link and run Modula-3 programs, without threads. From the library modules only those are tested which are used by the compiler. In the course of a student project a "student-friendly" environment is in development. It will be available at end of June (hopefully). 3.4. What is GNU Modula-3 ? From: moss@cs.cmu.edu (Eliot Moss) Subject: GNU Modula-3 alpha release status Date: 25 Mar 93 17:53:12 GMT We said we'd try to get the initial (alpha) release of GNU Modula-3 out some time this month (March), and we're in the process of figuring out what to release and how to package it up. We expect to have something in roughly two weeks (watch this space for a notice). What would this be? First, it is a compiler for the VAX (only) under Ultrix (only), definitely without threads, and probably still failing a small number of the tests in the SRC test suite (which implies that not all of libm3 is likely to work either). The actual release information will detail more about what's working and what's not at that time. We DO currently pass all the compiler tests that the SRC compiler did when it was first released (i.e., the ones we fail are more obscure things that users uncovered over time). Second, the release itself will be a compressed tar file including sources and executables. The executables will probably work only if you put libraries, etc., in the expected places (otherwise, you'll need to rebuild from sources).The compiler is written in C and should be compiled with a recent version of gcc (so you'll need gcc installed). The system also uses gld (the GNU linker). This release should be most useful to people undertaking ports to other machines and operating systems, since it will give them a head start on understanding the compiler and getting the full system ready. It may be of some use for ordinary programming, but it really depends on whether you tend to use features that tickle the remaining bugs. We are indeed interested in alpha test reports, but only if they tell us something new (i.e., we'll provide a list of known deficiencies). When the release is made, we'll also start email discussions with the various parties who have indicated they might undertake ports, to help sort out who will do what. Regards, and thanks for your continued interest and encouragement -- EM 4.1. What if I don't have ftp access ? Unfortunately, we cannot deliver Modula-3 other than by anonymous ftp. Fortunately, Prime Time Freeware (PTF) includes Modula-3. PTF is a set of two ISO-9660 CDroms filled with 3GB of freeware, issued semi-annually. The latest issue, Volume 1, Number 2, July 1992, contains SRC Modula-3 2.07. PTF is distributed via bookstores and mail. You can reach PTF using: Email: ptf@cfcl.com Fax: [1] (408) 738 2050 Voice: [1] (408) 738 4832 Mail: Prime Time Freeware 415-112 N. Mary Ave., Suite 50 Sunnyvale, CA 94086 USA 5.1. Can I contribute Modula-3 software ? Certainly. Send us what you are willing to share, be it programs, libraries or other things. We'll put them in the distribution. Right now, the pub/DEC/Modula-3/contrib directory contains: m3rpc an rpc system from Xerox Parc M2toM3 a translator from Modula-2 to Modula-3 m3pc an implementation of Modula-3 for PCs. -- Eric. ======================================================================= 10 === Date: 1 Apr 1993 10:07:55 -0500 From: Christian Schaepper Subject: RESULT: comp.lang.oberon passes 237:17 comp.lang.oberon R E S U L T S Here are the results of the CFV on the creation of the comp.lang.oberon newsgroup. votes cast: 254 yes votes: 237 (93.3%) no votes: 17 ( 6.7%) The requirements for group creation are met and the new newsgroup can be created after a waiting period of 5 days. During this waiting period the net has a chance to correct any errors in the voter list appended below. Thanks to anyone who cast a vote! YES votes: "A. Evers" aburke@BIX.com adcmail!jasons@uu4.psi.com (Jason Smith) Adrian Howard aki@bnlux1.bnl.gov alane@wozzle.linet.org (J. Alan Eldridge) Alexander Tuninga altmann@swe.uni-linz.ac.at "(Andreas Garzotto)" "(Andreas Margelisch)" andrew%srsuna@srsuna.shlrc.mq.edu.au (Andrew McVeigh) ATJBF%ASUACAD.BITNET@CEARN.BITNET (John Foster) Barry Allebone Barry Cornelius bbking!kgs@VFL.Paramax.COM ben@nj8j.blackwlf.mese.com (Ben Coleman) Bernhard Leisch Bert Bos biff@biff.jpunix.com (Dwight Everhart) Bill Wallace borchert@mathematik.uni-ulm.de (Andreas Borchert) Boris Nordenstroem brent@rcx1.ssd.csd.harris.com (Brent Benson) Brian Beattie Brian Excarnate brueni@csgrad.cs.vt.edu (Dennis Brueni) Cedric Didier Baechler "Cheryl Lins" "(Christoph MALLOTH)" claudio@amsoft.net.ch (Claudio Nieder) Clemens Szyperski clerc@gla.ecoledoc.ibp.fr cond@hyperion.lsi-j.co.jp (Yoshiyuki KONDO) Conor O'Neill cspt@giraffe.ru.ac.za (Pat Terry) Curlen H. Phipps CZSORO@zcvx00.decnet.ascom.ch d90-awe@nada.kth.se David Derbes "David M. Brumley" David.Sims@UC.Edu (David Sims) Denisov Andrey Dennis Michl Dirk Muysers dm_devaney@pnlg.pnl.gov Dmitry Sagatelyan dnord@cs.gmu.edu (David J. Nordstrom) Douin Jean Michel dov@menora.weizmann.ac.il (Dov Grobgeld) eberhard@vptt.ch Edin Hodzic elidriss@enserb.u-bordeaux.fr ((Elho) ELIDRISSI) epl@world.std.com (Edward P Luwish) eric blair hanneken Eric Stechmann - SP erv@everest.tandem.com (E. Videki) euzebio@dcc.unicamp.br (Marcos J. C. Euzebio) ezavada@rucs2.sunlab.cs.runet.edu "(Fernando D. Mato Mira)" fld@informatik.uni-bremen.de (Guenter Feldmann) foulques@email.teaser.com ( dominik latouche) frings@mathematik.uni-ulm.de (Astrid Frings) frode@toaster.SFSU.EDU (Frode Odegard) FSSPR@acad3.alaska.edu geser@ares.informatik.uni-ulm.de gesswein@pcpool1.informatik.uni-ulm.de ggw@wolves.Durham.NC.US (Gregory G. Woodbury) grabert@mathematik.uni-ulm.de (Matthias Grabert) "Greg (G.T.) Stovall" gsc@coombs.anu.edu.au (Sean Case) Guenter Dotzel <100023.2527@CompuServe.COM> guenter@prism.gatech.edu (Brian Guenter) gwg@salmon.aux.apple.com (Gene Garbutt) halpin@vsg1.dsg.dec.com (Stephen E. Halpin) Hans Eberle Hans J. Froehlich "(Hansjakob Emch)" hartmut@oberon.nbg.sub.org (hartmut Goebel hartmut Goebel) Hasse Haitto hausutzu@chamber.in-berlin.de (Utz-Uwe Haus) "Heberto Ghezzo" holger@lsd.nbg.sub.org (Holger Mitterwald) HSSEMMIB%CPHKVX.BITNET@CEARN.BITNET "J. Adrian Zimmer" jaime@afs.com Jarmo Pussinen jds@cs.UMD.EDU (James da Silva) jeffo@uiuc.edu (J.B. Nicholson-Owens) "Jeffrey R. Brown" jerry.bujas@itc.univie.ac.at (Jerry Bujas (gst)) jjan@cs.rug.nl (Beeblebrox) "Joachim Michely" joel@pa.dec.com (Joel McCormack) "Jon. Hallett" Jordan Henderson jordan@uniblab.aero.org (Larry M. Jordan) Josef Templ jpg@ee.edinburgh.ac.uk jpussi@cs.joensuu.fi (Jarmo Pussinen) Jyrki J Wahlstedt kardaras@ecn.purdue.edu (George S Kardaras) katcher@netcom.com (Jeff Katcher) "Kevin R. Coombes" kluge@avalon.physik.unizh.ch (kluge daniel) knapp@cs.purdue.edu (Edgar Knapp) Kristian Butorac krumke@cs.albany.edu (Sven Oliver Krumke) ksackett@cs.uah.edu (Karl R. Sackett) laffra@watson.ibm.com (C.Laffra) larry@titan.tsd.arlut.utexas.edu (Larry Maturo) lchen@ponder.csci.unt.edu (Lee Li-Jen Chen) lendecke@namu01.gwdg.de (Volker Lendecke EIFFEL) lima!lima-3!reh@uu5.psi.com (Rich Hoffarth) longjohn@adnovum.ch (Stefan Wengi) lvin@vucnit.voronezh.su lytras@avalon.physik.unizh.ch (Apostolos Lytras) maartenb@na47sun05.cern.ch (Maarten Ballintijn) mani@ppvku.ericsson.se (Markus Nikolopoulos) Manuel Eduardo Correia Marc Brandis Marcel Waldvogel Mark Skipper Markus Geltz martin@mathematik.uni-ulm.de (Martin Hasch) martino@alseng.boeing.com matt@amex-trs.com (The Libertarian Underground) "Matthew (M.) Holiday" Matthias Neeracher matwood@peruvian.cs.utah.edu (Mark Atwood) Maximilian Spring mcbreen@wg.estec.esa.nl mcintosh@ccwf.cc.utexas.edu (aubrey mcintosh) mdt26@cas.org (Ming-Ding Tsao) Michael John Haertel mich@trl.mei.co.jp mikeg@psg.com (Mike Gallo) mjl@cs.rit.edu (Michael J Lutz) Nedorya Alexey neurogen@reks.uia.ac.be (Neurogenetica) norman@bellcore.com (Norman Ramsey) Paolo Bucci pareto!steffan@wupost.wustl.edu (Mike Steffan) Patrick Saladin Paul McRae Paul Prescod Paul.Tvete@ii.uib.no pcroom-user@ntucc-pcroom.ntu.edu.tw Peter Hertel peter@ficc.ferranti.com (Peter da Silva) "pfterry" pjc@luke.ATdiv.Lanl.GOV (Paul J. Channell) ploesch@swe.uni-linz.ac.at pomberger@swe.uni-linz.ac.at pshuang@Athena.MIT.EDU psp@spectrospin.ch (Panagiotis Spiliopoulos) pwau@alcbel.be (Patrick Wauters) R James Noble Ralf Bauer "Ramon E. Pereda" randy@psg.com (Randy Bush) Ray Jackson reinhold@swe.uni-linz.ac.at "Rett Bull, Pomona College" Richard Hable Rick Moore Rik Watson "R.J.D.Elias" "(Robb Nebbe)" Robert Cowell rod@cosc.canterbury.ac.nz (R. Harries) Roger Vossler rohm@mpimfhd.mpimf-heidelberg.mpg.de (Klaus Rohm) romu@spectrospin.ch (Roger Mueller) rose@cs.wisc.edu (Scott Rose) rschnapp@metaflow.com (Russ Schnapp) rschoen@mathematik.uni-ulm.de (Reinhard Schoen) ruess@ares.informatik.uni-ulm.de (Harald Ruess) sametinger@swe.uni-linz.ac.at schauler@mathematik.uni-ulm.de (Markus Schauler) schiffer@swe.uni-linz.ac.at schramm@prosun.first.gmd.de (Andreas Schramm) sclafani@netcom.com (Michael Sclafani) sibrahim@cs.usc.edu (Shahril Ibrahim) stanglow@mathematik.uni-ulm.de (Werner Stanglow) Stefan Esser Stefan Odendahl stefan@fostam.nbg.sub.org (Stefan Stammler) "(Stelio Tzonis)" stephan@stack.urc.tue.nl (Stephan Eggermont) stewartg@ERE.UMontreal.CA (Stewart Gilles) stritzinger@swe.uni-linz.ac.at swg@mathematik.uni-ulm.de (Franz Schweiggert) T0FG000 thacker@src.dec.com Thomas F. Reid Thomas Ingold "Thomas J. Herbert" Thomas Wainwright thutt "Todd A. Proebsting" tomk@ee.edinburgh.ac.uk Tony Sloane Toshinori.Maeno troyer@ips.id.ethz.ch TSOS@uni-duesseldorf.de (Detlef Lannert) uli@decum.enet.dec.com (uli@decum.enet.dec.com) Ulrich Hoffmann ulrich@mips.complang.tuwien.ac.at (Ulrich Neumerkel) Urs Blum vev@vevdec.cs.murdoch.edu.au (Val Veraart) vilva@viikki21.helsinki.fi (VEIJO VILVA (KEJAL)) "(Vincent Kohler)" wald@mathematik.uni-ulm.de (Bernd Waldbauer) wald@theory.lcs.mit.edu (David Wald) walische@mathematik.uni-ulm.de (Hanno Walischewski) wbirkhol@mathematik.uni-ulm.de (Detlef Birkholz) wfugmann@mathematik.uni-ulm.de (Andreas Fugmann) whitney@christie.Meakins.McGill.CA (Whitney de Vries) WI00227@wipool.wifo.uni-mannheim.de wnj@indigo.hobby.nl (Willy Jacobs) Wolfgang Pree wrc@cs.rit.edu (Warren R Carithers) x920031@bus072.rz.ruhr-uni-bochum.de (Jost Krieger) yeung@cse.ogi.edu (Woodrow Yeung) NO votes: claude@trc.mew.mei.co.jp (Claude Huss) emcguire@intellection.com (Ed McGuire) "Eric J. Olson" Igor Metz Marc Moorcroft mhpower@Athena.MIT.EDU owens@cookiemonster.cc.buffalo.edu (Bill Owens) peirce@gumby.cc.wmich.edu (Leonard J. Peirce) Peter Hermann "Phil Scadden, Scadden Research" rick@crick.ssctr.bcm.tmc.edu (Richard H. Miller) Roland Kaltefleiter srogers@tad.eds.com (Steve Rogers) Stephen Lau tchannon@black.demon.co.uk (Tim Channon) tkoppel@cassandra.cair.du.edu (Ted Koppel) trier@slc6.INS.CWRU.Edu (Stephen C. Trier) ======================================================================= 11 === Date: Fri, 2 Apr 93 01:05:20 GMT From: steveg@src.dec.com (Steve Glassman) Subject: Re: Why are exceptions not resumable? First, there were very few uses of resumable exceptions in Mesa. As I recall, most could be recoded by catching the exception and retrying or by handling a specific condition with a direct procedure call. In large, multi-threaded programs it was hard to resume an exception because the system was not in a known/clean state while the exception was being handled before being resumed. For instance, the procedure that is prepared to handle the exception, makes a call on a procedure that acquires locks, makes more procedure calls, etc. Eventually, some descendant of that call raises the exception which is to be handled. Unfortunately, the caller can not know (in general) what the state of the system is (for locks, resources, invariants, etc) and thus can't safely fix the condition. If the exception is caught and reraised, then all intervening procedures (should) have restored the state to a point where the condition can be fixed and the operation retried. Alternatively, when the caller/raiser is a small predetermined set then the raiser and caller can cooperate (via a direct call on some procedure that understands the current stata) to fix the condition and (logically) resume. In gneral, the Mesa exception model had a lot of complexity that has been deemed unnecessary for Modula-3. Steve ======================================================================= 12 === Date: Thu, 1 Apr 1993 19:42:42 GMT From: wunder@hpl.hp.com (Walter Underwood) Subject: Why are exceptions not resumable? I've been looking at Modula-3, and I noticed a feature that was in Mesa, but is not in Modula-3: the ability to for a handler to cause execution to resume after the RAISE. I don't have a burning need to do this, but I'm curious whether it was left out for a particular reason. I can make guesses: it wasn't used by Mesa programmers, it increases the coupling between modules, etc. So, was there a rationale, and if so, what was it? wunder ======================================================================= 13 === Date: 1 Apr 93 11:40:19 From: vixie@pa.dec.com (Paul A Vixie) Subject: Re: new vbtkit and formsvbt docs on gatekeeper.dec.com > Yes, there are new versions of the VBTkit and FormsVBT manuals > in gatekeeper.pa.dec.com in pub/DEC/Modula-3/contrib. They > seem to have the correct permissions: that's gatekeeper.dec.com. just fyi. -- Paul Vixie, DEC Network Systems Lab Palo Alto, California, USA "Don't be a rebel, or a conformist; decwrl!vixie they're the same thing, anyway. Find vixie!paul your own path, and stay on it." -me ======================================================================= 14 === Date: 2 Apr 1993 12:44:22 GMT From: mead@bucknell.edu (Jerry Mead) Subject: Modula3 texts Yesterday I was visited by a rep from one of the large text book publishers. In the course of our conversation he noticed my copy of Harbison's book. He hadn't heard of Modula3. He asked if there were any introductory CS texts using Modula3 - I told him there were none but that I thought it wouldn't be difficult to convert one of the many Modula2 texts to a Modula3 version. Do any of you know whether there are any publishers persuing this direction? --------------------- Jerry Mead Dept of Computer Science Bucknell University Lewisburg, PA 17837 mead@bucknell.edu ======================================================================= 15 === Date: Thu, 1 Apr 1993 20:28:28 GMT From: mg@elan (Michael Golan) Subject: Re: Debuggers meehan@src.dec.com writes: >There isn't a specific M3 debugger; since the released compiler generates >C code, we use dbx or gdb. Not great, but better than nothing. Here >are some tips: [good tips deleted] If you use gdb, you might want to get and install Duel, a special language for debugging. Duel is designed specifically for C, but if you use the C mode for gdb's "print" you are better off with Duel (which links in with gdb to add a single new command, "dl"). As a simple example, the following code would print the positive elements of array mymodule.x. (gdb) dl x__mymodule[1..100] >? 0 Below is some farther information on how to get Duel and what it does. Duel is about 6000 lines of C code that is gdb-independent and in the public domain (not GNUish), so you can port it to other debuggers. Because Duel is small and self contained, it will probably be easier to "teach" duel about M3 name demangling, open arrays, etc., then to teach gdb. If you get/try duel, please (please!) drop me a line with any comments, good or bad. -- Michael Golan mg@cs.princeton.edu ----------------------------------------------------------------------------- DUEL - A high level language for debugging C programs. ----------------------------------------------------------------------------- Duel is a special purpose language designed for concise state exploration of debugged C programs under existing debuggers. It lets you to explore the program's state better than either the debugger's commands, a C interpreter, or print statements added to your code. The debugger is extended with the new 'dl' command for Duel expressions, e.g., gdb> dl x[0..10].level >? 5 x[3].level = 14 x[8].level = 6 prints the "level" fields of array elements x[0] to x[10] that are greater than 5. The output includes the values 14 and 6, as well as their symbolic representation "x[3].level" and "x[8].level". Linked list and other complex data structures are just as easy. Most of C (e.g. for, if) is also supported, e.g., int i; for(i=0; i<11; i++) if(x[i].level>5) x[i]. Duel is debugger-independent, but the current distribution interfaces only with gdb. You will need the source for gdb-4.6, 4.7 or 4.8. All supported gdb environments should work with Duel. It was tried at least on dec/mips, sparc, sgi/iris, sony, hp9000, aix/rs6000, and sysV. Duel is public domain code. Do whatever you like with it - add it to commercial debuggers, to dbx/sdb or even make it part of the GNU project. No part of this distribution contains any copyright or derived code, (i.e. no GPL code, either). No disclaimer - free public domain software don't need one! Even if you don't normally use debuggers, but you are programming in C, give Duel a try! The man page & help even include a summary of useful gdb commands. Duel is available for anonymous ftp from ftp.cs.princeton.edu, in /duel/duel.tar.Z. A "tar.Z" format means you should use the command "zcat duel.tar.Z | tar xf -" to unpack the files. The Usenix Jan/93 paper about Duel is also available as tech report 399, in /reports/1992/399.ps.Z on ftp.cs.princeton.edu DUEL is "Debugging U (might) Even Like" or "Don't Use this Exotic Language" you should judge which is better! Michael Golan mg@cs.princeton.edu ----------------------------------------------------------------------------- The tutorial part from the manual page follows: Duel is based on expressions which return multiple values. The x..y operator returns the integers from x to y; the x,y operator returns x and then y, e.g. gdb> dl (1,9,12..15,22) prints 1, 9, 12, 13, 14, 15 and 22. Such expressions can be used wher- ever a single value is used, e.g. gdb> dl x[0..99]=0 ; assigns zero to the first 100 elements of array x. The semantics of x[i] are the same as in C. They are applied for each of the values returned by 0..99, which can be thought of as an implied external loop. The trailing semicolon indicates evaluation for side-effects only, with no output. Duel incorporates C operators, casts C statements as expres- sions, and supports limited variable declaration: gdb> dl int i;for(i=0;i<100;i++) if(x[i]<0) printf("x[%d]=%d\n",i,x[i]); x[7] = -4 The semicolon prevents Duel output; only output from printf is printed. Aliases are defined with x:=y and provide an alternative to variable declaration. We could also return x[i] instead of using printf: gdb> dl if(x[i:=0..99]<0) x[i] x[i] = -4 The symbolic output "x[i]" can be fixed by surrounding i with {}, i.e. gdb> dl if(x[i:=0..99]<0) x[{i}] x[7] = -4 The {} are like (), but force the symbolic evaluation to use i's value, instead of "i". You can usually avoid this altogether with direct Duel operators: gdb> dl x[..100] =?y, etc., operators compare their left side operand to their right side operand as in C, but return the left side value if the comparison result is true. Otherwise, they look for the next values to compare, without returning anything. Duel's x.y and x->y allow an expression y, evaluated under x's scope: gdb> dl emp[..100].(if(code>400) (code,name)) emp[46].code = 682 emp[46].name = "Ela" The if() expression is evaluated under the scope of each element of emp[], an array of structures. In C terms, we had to write: gdb> dl int i; for(i=0; i<100 ; i++) if(emp[i].code>400) emp[{i}].code,emp[{i}].name A useful alternative to loops is the x=>y operator. It returns y for each value of x, setting `_' to reference x's value, e.g. gdb> ..100 => if(emp[_].code>400) emp[_].code,emp[_].name Using `_' instead of `i' also avoids the need for {i}. Finally, the x-->y operator expands lists and other data structures. If head points to a linked list threaded through the next field, then: gdb> dl head-->next->data head->data = 12 head->next->data = 14 head-->next[[2]]->data = 20 head-->next[[3]]->data = 26 produce the data field for each node in the list. x-->y returns x, x->y, x->y->y, x->y->y->y, ... until a NULL is found. The symbolic output "x-->y[[n]]" indicates that ->y was applied n times. x[[y]] is also the selection operator: gdb> dl head-->next[[50..60]]->data return the 50th through the 60th elements in the list. The #/x operator counts the number of values, so gdb> dl #/( head-->next->data >? 50 ) counts the number of data elements over 50 on the list. [There is a lot more in the full manual. Cyclic lists, strings, arrays like argv, etc] --------------------------------------------------------------------------- ======================================================================= 16 === Date: 2 Apr 93 08:38:56 GMT From: os102@cl.cam.ac.uk (Oliver Stephens) Subject: Re: SRC-m3 vs -O In article <1peb0d$33p@rug4.cs.rug.nl>, laverman@cs.rug.nl (Bert Laverman) writ es: |> If I remember correctly, there have been some problems with using |> optimization on the C compiler pass, some versions ago. Is there |> anybody using -O with the current version auccessfully? It would |> save considerable on size of the libraries... |> With version 2.11, SPARC cc works fine with -O. DEC cc doesn't (I tried building the compiler but it crashes straight away complaining about a very large negative open array size.) Compiling on the DECs with no options (ie. neither -g or -O) works fine and seriously reduces the size of things. I haven't tried gcc - perhaps I should. I guess I presume it to be a slower compiler - people seem to be just as bothered at speed of compilation as they are at size of output around here - but then when you've got 100 undergraduates all compiling FormsVBT programs, there's not much I can do about turnaround time :-) ------------------------------------------------------------------------- Olly Stephens oliver.stephens@cl.cam.ac.uk Computer Laboratory University of Cambridge Loved you there and then, and now like a sheep United Kingdom - Van Morrison ======================================================================= 17 === Date: Fri, 02 Apr 93 09:31:02 -0800 From: mhb@src.dec.com Subject: Re: Modula3 texts On a related matter, Bob Sedgewick just completed "ALGORITHMS IN MODULA-3", and the camera-ready copy is someplace between Princeton, Palo Alto, Mountain View, and Reading as I type. This book is for a 2nd or 3rd semester course concentrating on algorithms and data structures, not intro programming. It should be available in 6-8 weeks. There's a project here at SRC to prepare a slew of algorithm animations corresponding to the key algorithms in that text. A feel for what's planned is available on gatekeeper.dec.com in the Modula-3 distribution. ======================================================================= 18 === Date: 2 Apr 93 19:16:32 GMT From: mday@jukebox.lcs.mit.edu (Mark Day) Subject: Re: Why are exceptions not resumable? wunder@hpl.hp.com (Walter Underwood) writes: I've been looking at Modula-3, and I noticed a feature that was in Mesa, but is not in Modula-3: the ability to for a handler to cause execution to resume after the RAISE. I don't have a burning need to do this, but I'm curious whether it was left out for a particular reason. I can make guesses: it wasn't used by Mesa programmers, it increases the coupling between modules, etc. So, was there a rationale, and if so, what was it? Modula-3 exceptions are similar to CLU exceptions, since both languages have a termination model and neither language allows signals to propagate through multiple levels of abstraction. You might find it interesting to read the rationale for the CLU model: Barbara Liskov and Alan Snyder, "Exception Handling in CLU." IEEE Transactions on Software Engineering 5(6): 546-558 (November 1979). --Mark Day mday@lcs.mit.edu ======================================================================= 19 === Date: Fri, 2 Apr 1993 21:45:10 GMT From: emery@goldfinger.mitre.org (David Emery) Subject: Re: Why are exceptions not resumable? There's also a discussion of this in the Ada rationale, as Ada has similar "abandonment" semantics. On the other hand, Ada exceptions *do* propogate through multiple levels of abstractions, and there is no requirement for an Ada subprogram to explicitly identify the exceptions that it can raise. dave ======================================================================= 20 === Date: Fri, 2 Apr 93 23:23:49 CST From: lampman@fullfeed.com (Ray Lampman) Subject: Re: Modula-3 Frequently Asked Questions (FAQ) Please also cross-post this FAQ to "comp.answers", thankx much, Ray. -- Ray.Lampman@FullFeed.Com ,^-_ FullFeed provides public access to FullFeed Communications L `; Usenet news and E-mail, plus UUCP Madison, WI 53704, USA \ . J connections to the Madison area voice +1 608 246 4239 L__] data +1 608 246 2701 login guest ======================================================================= 21 === Date: Sun, 4 Apr 1993 22:45:12 GMT From: moss@cs.cmu.edu (Eliot Moss) Subject: Re: efficiency of open arrays There's a reasonably obvious reason this might be happening. In the fixed array case, since the FOR loop bounds are static and within the array, it is not too hard to eliminate bounds checks -- I suspect the SRC compiler does it, and I'm pretty sure the GNU one will in this case, too. In the open array case, the size information is carried by the specific value (the NEW array), not in the type of the variable, and requires more sophisticated analysis to enable the bounds checks to be removed. If you nreally need open arrays, you'll probbaly have the bounds checks anyway, and will not be able to get the higher speed loop. Improving array access performance by eliminating needless checks is something all the compiler writers have on their agenda, but I can't promise great solutions soon ..... EM -- J. Eliot B. Moss, Associate Professor Visiting Associate Professor Department of Computer Science School of Computer Science Lederle Graduate Research Center Carnegie Mellon University University of Massachusetts 5000 Forbes Avenue Amherst, MA 01003 Pittsburgh, PA 15213-3891 (413) 545-4206, 545-1249 (fax) (412) 268-6767, 681-5739 (fax) Moss@cs.umass.edu Moss@cs.cmu.edu ======================================================================= 22 === Date: 5 Apr 1993 22:09:19 GMT From: joel@decwrl.dec.com (Joel McCormack) Subject: Re: efficiency of open arrays Actually, there is absolutely no reason for bounds checks of open arrays not to be moved from within a FOR loop to outside the loop. It is, in fact, exactly the same code as moving constant bounds checks, but you load variables instead of constants where the check is moved outside the loop. To do this for FOR loops requires none of the more complex analysis that code movement out of loops in general requires. In the examples from Chris Thewalt's message, the version without open arrays makes it easy to remove the bounds checks completely, as they can be done at compile time. A smart compiler might be able to do so with the open array version as is. If instead of using ``Num_iter'' or ``Num_size'' as a limit he had used ``HIGH(xxx)'' a less smart compiler could remove the bounds tests completely without much trouble. But even if the compiler didn't bother, it wouldn't matter: the loops execute 1000 and 10000 times, anyway, so as long as you don't do bounds checking EACH ITERATION you'd be fine. I'm sure that the SRC people doing M3 compilers noticed the ``it is now obvious that the open array overhead makes the use of Modula3 impossible'' in Chris Thewalt's message. Knowing Bill, they'll probably do something about it, too, if they haven't already. This is a compiler problem, not a Modula-3 problem. The WRL Modula-2 compiler had no trouble moving these types of bounds checks out of FOR loops. -- - Joel McCormack (decwrl!joel, joel@decwrl.dec.com) ======================================================================= 23 === Date: 5 Apr 93 21:04:14 GMT From: thewalt@canuck.ce.berkeley.edu (C. Thewalt) Subject: Re: efficiency of open arrays In article moss@cs.cmu.edu (Eliot Moss) writes: >There's a reasonably obvious reason this might be happening. In the fixed >array case, since the FOR loop bounds are static and within the array, it is >not too hard to eliminate bounds checks -- I suspect the SRC compiler does it, >and I'm pretty sure the GNU one will in this case, too. In the open array >case, the size information is carried by the specific value (the NEW array), >not in the type of the variable, and requires more sophisticated analysis to >enable the bounds checks to be removed. If you nreally need open arrays, >you'll probbaly have the bounds checks anyway, and will not be able to get the >higher speed loop. >Improving array access performance by eliminating needless checks is something >all the compiler writers have on their agenda, but I can't promise great >solutions soon ..... EM >-- >J. Eliot B. Moss, Associate Professor Visiting Associate Professor Thanks for your response, I have looked at the C code and your guess sounds correct. I had been considering modula3 for a fairly large analytical package, and had a couple of students learning it, but the package will do lot of linear algebra and the matrix/vector sizes vary from problem to problem. A basic core of linear algebra functions (like BLAS in FORTRAN) is required, and it is now obvious that the open array overhead makes the use of Modula3 impossible. I just ran a benchmark of a matrix multiply with open and fixed array sizes and the speed ratio is 4.8:1 and we can't take a hit like that. Thanks for the clue, Chris -- Christopher Robin Thewalt (thewalt@ce.berkeley.edu) Dept. of Civil Engineering These opinions are not necessarily University of California, Berkeley shared by my employer... ======================================================================= 24 === Date: Wed, 7 Apr 1993 01:43:44 GMT From: ellis@parc.xerox.com (John Ellis) Subject: Re: efficiency of open arrays Joel raised an issue of optimizing bounds checks that I also encountered in the Vulcan M2+ compiler. I think Joel's suggested optimization requires a little more elaboration that may be obvious to some readers. Consider the following loop: FOR i := m TO n DO ...a[ i ]... I think Joel was proposing that the bounds checks for a[ i ] would get moved to the beginning of the loop: IF n >= m AND (LOW( a ) < m OR HIGH( a ) > n) THEN ...error... END; FOR i := m TO n DO ...a[ i ]... Before making this transformation, the compiler must ensure that the loop actually executes for all the values of i = [m..n]. Otherwise, if the loop terminates prematurely, then the transformation above could incorrectly signal a subscript error. Here are two examples of loops that may exit prematurely: FOR i := m TO n DO IF i > C THEN EXIT; END; ...a[ i ]... FOR i := m TO n DO P(); /* Raises an exception */ ...a[ i ]... So it seems safe to do the transformation if: The loop body contains no EXITs. All exceptions raised by the loop body are caught within the body. Given the pervasive use of exceptions, this second condition makes the optimization less useful than you might think initially (though it is still useful). ======================================================================= 25 === Date: Wed, 7 Apr 1993 12:40:59 GMT From: dave@kanga.lcs.mit.edu (David Sternlicht) Subject: seeking trestle/mt experiences -- Good morning. I have been taking a long hard look at trestle and modula-3 from the standpoint of taking its experience in multi-threading and using it in the X consortiums development of a next generation GUI toolkit, aka Fresco. Admitedley the development language here is c++, not m3 (I do like m3 alot however!). I have been thinking along the lines of taking trestles locking level system for the procedures and data of its interfaces and doing the same thing for the various public members of Fresco's classes. I guess I'm looking for some war stories here. Has anybody written a trestle program that makes extensive use of threads. Are their any weaknesses in the design decisions taken? Particular strengths that should be mentioned? dave sternlicht mit X consortium dave@expo.lcs.mit.edu ======================================================================= 26 === Date: Wed, 7 Apr 1993 16:09:58 GMT From: cfr@tyrolia.Princeton.EDU (Chuck Rose) Subject: m3 for SGI Does anyone have information about m3 for SGIs? Has anyone successfully ported m3 to the SGI? Thanks in advance, chuck. ======================================================================= 27 === Date: Thu, 08 Apr 1993 01:04:37 GMT From: urban@CS.ColoState.EDU (david urban) Subject: Interfaces Cstring & M3toC A software design class I am in stores strings of text in the cells of a spreadsheet which need to be parsed for references to other cells. I noticed in Harbison's book that there are interfaces Cstring and M3toC which would make the parsing alot easier. Are there any references on how these interfaces are used since the book does not explain them? Any help with this would be greatly appreciated. David Urban -- David S. Urban email : urban@cs.colostate.edu To be the person, you must know the person. To know the person, you must understand the person. To understand the person, you must listen. To listen, you must open your mind and put aside all preconceived ideas and notions. ======================================================================= 28 === Date: 8 Apr 93 21:28:10 GMT From: sasaki@netop3.harvard.edu (Marty Sasaki) Subject: Problems getting the compiler working I'm trying to get the DS3100 version of m3 working on my DS5000 running Ultrix 4.3. The compiler runs fine and generates configuration information. netop3:7> m3 -\? pass 0 := /usr2/local/lib/m3/m3compiler pass 1 := /bin/cc -G 0 -Wf,-XNp200000 -Wf,-XNd150000 pass 2 := /bin/cc -G 0 pass 2 base := -N pass 3 := /bin/ar cru pass 4 := /usr/bin/ranlib pass 5 := /bin/ld -A pass 5 mid := -G 0 -g2 pass 5 tail := -lc_G0 def path := . /usr2/local/include/m3 lib path := . /usr2/local/lib/m3 include := /usr2/local/lib/m3 server limit := 0 megabytes make mode := FALSE bootstrap := FALSE std libs := TRUE -lm3 -lm keep files := FALSE coverage := FALSE /usr2/local/lib/m3/report_coverage.o resolve libs := FALSE CC paranoid := FALSE -O => -O2 -g => -g2 When I try to use m3make to create libm3 I get an error: netop3:5> m3make -f m3makefile.libm3 all install -------------------------------------- libm3/DS3100 /usr2/local/bin/m3 -w1 -make -why -nostd -times -g -a libm3.a -F.PGM _SOURCES new source -> compiling ../C/src/generic/Cerrno.i3 seconds #times operation 0.25 1 flattening search path 0.09 5 checking object timestamps 0.24 1 compiling Modula-3 -> C 0.05 3 removing temporary files 0.31 2 garbage collection 0.38 other --------------------------------------------------- 1.32 TOTAL Fatal Error: program "/usr2/local/lib/m3/m3compiler" got fatal signal 1 1 *** Error code 255 Stop. *** Error code 1 Stop. Anything obviously wrong? How do I begin to look at things? -- Marty Sasaki Harvard University Sasaki Kite Fabrications sasaki@noc.harvard.edu Network Operations Division 26 Green Street 617-496-4320 10 Ware Street Jamaica Plain, MA 02130 Cambridge, MA 02138-4002 phone/fax: 617-522-8546 ======================================================================= 29 === Date: 9 Apr 1993 15:31:57 GMT From: mead@bucknell.edu (Jerry Mead) Subject: Solaris2.1 version of M3? Has anyone had success bringing modula3 up on Solaris 2.1? Suggestions and/or war stories are of interest. --------------------- Jerry Mead Dept of Computer Science Bucknell University Lewisburg, PA 17837 mead@bucknell.edu ======================================================================= 30 === Date: 9 Apr 93 19:14:22 GMT From: sasaki@netop3.harvard.edu (Marty Sasaki) Subject: Re: Problems getting the compiler working In article <1993Apr8.212810.27881@das.harvard.edu>, sasaki@netop3.harvard.edu ( Marty Sasaki) writes: >When I try to use m3make to create libm3 I get an error: Thanks to those who offered suggestions and help. On the hunch of some one I just rebuilt things form the distribution. The new version seems to be working fine. -- Marty Sasaki Harvard University Sasaki Kite Fabrications sasaki@noc.harvard.edu Network Operations Division 26 Green Street 617-496-4320 10 Ware Street Jamaica Plain, MA 02130 Cambridge, MA 02138-4002 phone/fax: 617-522-8546 ======================================================================= 31 === Date: Sat, 10 Apr 1993 17:23:44 GMT From: robsch@robkaos.GUN.de (Robert Schien) Subject: M3 for 386BSD Does it exist? Or is anybody porting it? Thanks in advance. Robert -- Robert Schien robsch@robkaos.GUN.de "To err is human, to really foul things up requires a computer" ======================================================================= 32 === Date: Tue, 13 Apr 1993 20:31:53 GMT From: woolsey@mri.com (Jeff Woolsey) Subject: Re: Solaris2.1 version of M3? In article <1q44td$ifh@coral.bucknell.edu> mead@bucknell.edu writes: >Has anyone had success bringing modula3 up on Solaris 2.1? >Suggestions and/or war stories are of interest. A-step-in-that-direction story: I have a fairly monolithic old-mainframe CPU simulator that's my favorite benchmark these days. It's compiled by m3-2.11 on SunOS 4.1.1. Solaris 2.1 is supposed to have a SunOS-4 compatibility mode for dynamically-linked programs. We have received a few SPARCstation LX machines in house recently, and I wanted to "benchmark" these guys, but they run Solaris 2.1. I hauled the binary over there, and started it up. Assertion failed at line 832 in Thread.m3. I poked around the various .i3, .m3, and .mc files that came with the compiler, and eventually found that there was a variable somewhere called "__M3__stack_grows_down". The assertion had to do with stack direction, so on a hunch I decided to nail it. I changed it from a zero to a one with adb (easiest way, actually) and tried it out. This worked well enough for me, but interactive I/O wasn't working, and I have no idea whether threads would work (my program doesn't use them). Incidentally, by my figures an LX is about the same speed as an ELC. -- -- Jeff Woolsey 800 950 5554 woolsey@mri.COM Microtec Research, Inc. +1 408 980 1300 woolsey@netcom.COM Nothing like a three-address mailer.... woolsey@jlw.com ======================================================================= 33 === Date: Wed, 14 Apr 1993 10:07:54 GMT From: jbowyer@cis.vutbr.cs (Bowyer Jeff) Subject: We Want Your Work We want you to announce your work on our mailing list! Do you use a program that has a non-English interface? Have you converted any software to support more than one language for its interface? Will you sponsor a conference that might concern software with a non-English interface? Please tell us! INSOFT-L on LISTSERV@CIS.VUTBR.CS Internationalization of Software Discussion List Internationalization of software relates to two subjects: 1. Software that is written so a user can easily change the language of the interface; 2. Versions of software, such as Czech WordPerfect, whose interface language differs from the original product. Topics discussed on this list will include: -- Techniques for developing new software -- Techniques for converting existing software -- Internationalization tools -- Announcements of internationalized public domain software -- Announcements of foreign-language versions of commercial software -- Calls for papers -- Conference announcements -- References to documentation related to the internationalization of software This list is moderated. To subscribe to this list, send an electronic mail message to LISTSERV@CIS.VUTBR.CS with the body containing the command: SUB INSOFT-L Yourfirstname Yourlastname Owner: Center for Computing and Information Services Technical University of Brno Udolni 19, 602 00 BRNO Czech Republic INSOFT-L-REQUEST@CIS.VUTBR.CS ======================================================================= 34 === Date: Thu, 15 Apr 93 21:17:38 GMT From: mjordan@src.dec.com (Mick Jordan) Subject: Re: .m3 + .c ? In article <1qkedi$12m@usenet.INS.CWRU.Edu>, bf148@cleveland.Freenet.Edu (Shad Todd) writes: |> |> Hello, |> I am trying to compile the following simple modula-3 program without |> success. This is the error I get when I try to compile: |> |> m3 test.m3 cstuff.c cstuff.i3 |> |> undefined version stamp: cstuff.cprocedure |> test.m3 cstuff.i3 |> |> Fatal Error: incomplete program |> |> Can anyone tell me what I am doing wrong here, or point me |> towards documentation for calling C routines from modula-3? |> Thanks very much for your time, |> | |> --cstuff.i3------ |> UNSAFE INTERFACE cstuff; |> |> PROCEDURE cprocedure(x, y: INTEGER): INTEGER; |> END cstuff. |> Since "cprocedure" is implemented in C, you need to say: <*EXTERNAL*> PROCEDURE cprocedure(x, y: INTEGER): INTEGER; The linker is looking for a Modula-3 implementatioin and not finding it. Mick Jordan ======================================================================= 35 === Date: Thu, 15 Apr 93 23:17:45 GMT From: harrison@src.dec.com (Stephen Harrison) Subject: Re: .m3 + .c ? Shad Todd described a problem linking Modula-3 and C. His Modula-3 interface omitted the <*EXTERNAL*> pragma from the declaration of the C procedure. It should read: INTERFACE cstuff; <*EXTERNAL*> PROCEDURE cprocedure(x, y: INTEGER): INTEGER; END cstuff. Cheers, /Stephen -- Stephen Harrison | harrison@pa.dec.com Systems Research Center | Digital Equipment Corporation | work +1 (415) 853-2140 130 Lytton Avenue | fax +1 (415) 853-2104 Palo Alto, CA 94301, USA | home +1 (408) 739-7734 ======================================================================= 36 === Date: 15 Apr 1993 19:52:18 GMT From: bf148@cleveland.Freenet.Edu (Shad Todd) Subject: .m3 + .c ? Hello, I am trying to compile the following simple modula-3 program without success. This is the error I get when I try to compile: m3 test.m3 cstuff.c cstuff.i3 undefined version stamp: cstuff.cprocedure test.m3 cstuff.i3 Fatal Error: incomplete program Can anyone tell me what I am doing wrong here, or point me towards documentation for calling C routines from modula-3? Thanks very much for your time, Shad -- Shadrach Todd shtodd@vassar.edu --test.m3--------- MODULE test EXPORTS Main; FROM cstuff IMPORT cprocedure; VAR result: INTEGER; BEGIN result:=cprocedure(1, 2); END test. --cstuff.c------- int cprocedure(x, y) int x,y; { return x+y; } --cstuff.i3------ UNSAFE INTERFACE cstuff; PROCEDURE cprocedure(x, y: INTEGER): INTEGER; END cstuff. ======================================================================= 37 === Date: Thu, 15 Apr 1993 20:39:12 GMT From: jkpchang@laplace.uwaterloo.ca (Jorge 'CS-Geek' Chang) Subject: Modula-3 for IBM PCs Anyone know where I can get a Modula-3 compiler for IBM PC. If you know please either email me or post on this newsgroup exactly where I can get it and how... Thanks... Jorge ======================================================================= 38 === Date: Fri, 16 Apr 1993 13:08:08 GMT From: cpshelle@undergrad.math.uwaterloo.ca (cameron shelley) Subject: Re: Modula-3 for IBM PCs In article you write: > > Anyone know where I can get a Modula-3 compiler for IBM PC. If you know pleas e > either email me or post on this newsgroup exactly where I can get it and how. .. The PC Modula-3 compiler is archived at archive.uwaterloo.ca in directory micro/m3pc. Please consult the FAQ file for your course as was posted in uw.cs.cs246 or in the directory /u/cs246/documents for more information. Subject: kwic of the comp.lang.modula3 archives I have created a Key Word In Context index on the subjects of the messages sent to comp.lang.modula3. It will appear very soon on gatekeeper.dec.com in pub/DEC/Modula-3/comp.lang.modula3/kwic and I will maintain it as I add new volumes to this archive. The following words have been ignored: A M3 Modula-3 Modula Modula3 Questions Question Re about an and another as at for from help i is again all are be does is it of on Please, let me know if you think I should modify that list. Here is a sample, for the keyword "syntax": 90-01: SRC compiler syntax accepted by the 90-01: SRC compiler Re: syntax accepted by the 90-01: TRY statement syntax non-problem 90-01: Re: TRY statement syntax non-problem 90-12: SRC Modula-3 syntax and semantics 90-12: constants Modula-3 syntax and semantics for 90-12: constants Modula-3 syntax and semantics for 90-12: constants Modula-3 syntax and semantics for 91-01: method/ new syntax for overriding 92-09: Syntax of WITH and TRY 92-10: Syntax of Modula-3 92-10: Re: Syntax of Modula-3 The left-hand side is the name of the file that contains the message, and conveniently tells you when the message was posted. The current version is not too big: % wc kwic 7523 47010 486556 kwic For those of you who have more resources, I recommend the ni program (available on gatekeeper.dec.com in pub/DEC/ni.tar.Z) which builds full indexes (not just on the subject) of newsgroups and provides a simple interface to find and read those articles that contain certain words. The amount of disk space it takes is not too bad, and well worth it; here at SRC, we could not do without ni anymore. -- Eric. ======================================================================= 46 === Date: 23 Apr 1993 09:54:59 GMT From: laszlo@post.ifi.uni-klu.ac.at (Laszlo BOESZOERMENYI) Subject: Bug In Set.mg I have found a bug in the Generic-set "Set.mg". In the procedure "copy" the line cur := self.a [b]; must be properly: cur := self.a [b]; prevN:= NIL; I wonder, if anybody has ever used this module??!! Cheers Laszlo ------------------------------ Prof. Laszlo Boeszoermenyi Institut fuer Informatik Universitaet Klagenfurt Universitaetsstr. 65-67 A-9022 Klagenfurt / Austria e-mail: laszlo@ifi.uni-klu.ac.at Tel.: 00-43-463-2700-509 00-43-463-2700-506 (secr.) Fax.: 00-43-463-2700-505 ======================================================================= 47 === Date: Fri, 23 Apr 93 22:28:10 GMT From: Eric Muller Subject: Re: Problem with RealFloat? |> I am getting a core dump when I try to use RealFloat.Sqrt. [on AIX386] Most of the RealFloat implementation is machine specific, and we haven't tried to guess the proper implementation for the machines we don't have access to. In the case of Sqrt, the implementation of the DS3100 version should work fine on most machines: RETURN FLOAT (Math.Sqrt (FLOAT (x, LONGREAL)), T); I'll include that for the next release. Of course, if somebody can provide a full implementation of the machine-specific interfaces and modules for floating point, it will be even better. Look in libm3/float/src. -- Eric. ======================================================================= 48 === Date: 23 Apr 93 20:54:23 GMT From: barton@chopin.eche.ualberta.ca (Bob Barton System Administrator (403)4 92 5160) Subject: Problem with RealFloat? I am getting a core dump when I try to use RealFloat.Sqrt. The problem can be demonstrated with the following code - MODULE FloatTst EXPORTS Main; IMPORT Fmt, RealFloat, Wr, Stdio; VAR testValue : REAL; BEGIN Wr.PutText(Stdio.stdout, "Test of Sqrt from RealFloat\n"); testValue := RealFloat.Sqrt(4.0); Wr.PutText(Stdio.stdout,"\nThe square root of 4.0 is: "); Wr.PutText(Stdio.stdout, Fmt.Real(testValue)); Wr.PutText(Stdio.stdout,"\n"); END FloatTst. which produces - *** *** runtime error *** ASSERT failed *** file "RealFloat.m3", line 63 *** Test of Sqrt from RealFloat I am probably doing something incorrectly but I have not identified it. I have accomplished the square root by using Math.sqrt and multiple FLOATs but that is pretty kludgey. I am working with m3 version 2.11 on an IBM RS/6000 with AIX 3.2.3. --,,,, | D | R.L. Barton Department of Chemical Engineering | A | Tel (403) 492-5160 University of Alberta | C | Fax (403) 492-2881 Edmonton, Alberta, Canada T6G 2G6 | S | Internet barton@chopin.eche.ualberta.ca --'''' ======================================================================= 49 === Date: 23 Apr 93 17:29:52 GMT From: muzok@microsoft.com (Muzaffer Kal) Subject: Re: Modula-3 for IBM PCs In article <93Apr16.091142edt.246216-2@undergrad.math.uwaterloo.ca> cpshelle@un dergrad.math.uwaterloo.ca wrote: > In article you write: > > > > Anyone know where I can get a Modula-3 compiler for IBM PC. If you know ple ase > > either email me or post on this newsgroup exactly where I can get it and ho w... > > The PC Modula-3 compiler is archived at archive.uwaterloo.ca in > directory micro/m3pc. Please consult the FAQ file for your course as > was posted in uw.cs.cs246 or in the directory /u/cs246/documents for > more information. > > -- > Cameron Shelley |"In the beginning, there was nothing. Then > cpshelle@descartes.uwaterloo.ca| God said `Let there be light', and there > Math & Computer Rm 1014 | was still nothing, but youse could see it." > Phone (519) 885-1211 x6827 | --Dave Thomas, SCTV:_Sunrise Semester_ is there an ftp source for this compiler ? Also is there an oberon compiler and /or environment for PCs ? please give fully resolved addresses. ======================================================================= 50 === Date: Sat, 24 Apr 1993 07:50:44 GMT From: stjk100@cl.cam.ac.uk (S.T.J. Kam) Subject: M3 vs C++ Could anybody give a comparison between M3 and C++? I am particularly interested in their OOP features. S.T.J. Kam Keywords: ======================================================================= 51 === Date: 24 Apr 93 12:22:48 From: vixie@pa.dec.com (Paul A Vixie) Subject: Re: M3 vs C++ >Could anybody give a comparison between M3 and C++? >I am particularly interested in their OOP features. > > S.T.J. Kam C++ has operator overloading and multiple inheritance but no garbage collection (though it can be added later, there's no standard for it yet). My article in ";login:" (the USENIX Association Newsletter) a few issues ago provides a light comparison between M3 and C++. If you don't get ;login: and can't find it, let me know and I'll mail you a copy electronically. -- Paul Vixie, DEC Network Systems Lab Palo Alto, California, USA "Don't be a rebel, or a conformist; decwrl!vixie they're the same thing, anyway. Find vixie!paul your own path, and stay on it." -me ======================================================================= 52 === Date: 24 Apr 93 23:07:55 From: vixie@pa.dec.com (Paul A Vixie) Subject: Re: M3 vs C++ I wrote: > [...] My article in ";login:" (the USENIX Association Newsletter) a few > issues ago provides a light comparison between M3 and C++. If you don't > get ;login: and can't find it, let me know and I'll mail you a copy > electronically. It turns out that the ;login: people don't mind and I already got publication approval from my employer, so here it is. Note that it has a very polemic style, one I would not normally use on Usenet since it tends to cause flame wars. There several actual facts contained herein, though, so give it a read if you care about this sort of thing. by the way, those of you who don't receive ;login: are missing out. send mail to office@usenix.org if you want to join; i think the membership rate is $35 a year for individuals, less for students. note: i am not a spokesman for or a representative of Usenix or ;login: -- just a happy contributor and reader. Copyright (c) 1993: do not separate the following text from the above text, including enough of the article header to show authorship. otherwise you may redistribute at will, with or without fee. ============================ begin ;login: article ============================ Have you seen Modula-3? Consider: MODULE Main; (* hello1.m3 *) IMPORT Stdio, Wr; BEGIN Wr.PutText(Stdio.stdout, "Hello, world.\n"); END Main. The above program is written in Modula-3, one of the latest languages to descend from Algol. As you can see, the source looks a lot like Modula-2 or Pascal (or, if you live on the bleeding edge, you might agree that it looks a lot like Oberon). As is true of the "Hello, World" program when written in other languages, our example does not begin to explicate Modula-3's interesting features; however, as with C, if you started by looking at a program which used all or even some of the interesting features, you would probably giggle and turn the page. Modula-3 has explicit boundaries between modules. Types, constants, variables and procedures declared in a module are only accessable to other modules if the declaring module explicitly "exports" them. (Contrast this to C, where all top-level names in a source file are globally visible at link time unless they are declared "static".) A module which depends on entities from some other module must explicitly "import" the symbols it needs. Consider: MODULE Main; (* hello2.m3 *) FROM Wr IMPORT PutText; FROM Stdio IMPORT stdout; BEGIN PutText(stdout, "Hello, world.\n"); END Main. In the first example, we imported the symbol tables from the Wr and Stdio modules, and then used their PutText and stdout symbols by qualifying those symbols with the names of the modules that exported them. In this second example, we imported only the PutText and stdout symbols -- now we can refer to them without module qualifiers. (Note that the current recommended practice among experienced Modula-3 programmers is to always import symbol tables and use qualified references; you will rarely or never see local symbol aliases used in published Modula-3 source.) Modula-3 is a strongly typed language whose loopholes are difficult enough and inconvenient enough to use that one tends to localize them to one or only a few "modules" (which, for now, you can think of as "source files"). This leads toward that ideal state of affairs where most of the ugly and nonportable code in a software system is located in one place; modules which are not declared to the compiler as "able to contain ugly, nonportable code" are prohibiting from containing such code. Examples of such code include most kinds of type casts, pointer arithmetic which could lead to alignment or byte-order gaffes, and use of dynamic memory in ways that could lead to memory leaks. Noone has yet invented a compiler which rejects code that is _portably_ ugly. Modula-3 has "objects", which for the OO-impaired are basically "records" (think "structs") which you can "subclass" (make another object just like this one but which adds some fields at the end or overrides the default values of existing fields) and which can contain "methods" (fields which are procedure ("function") pointers, calls to which are automagically rewritten by the compiler to pass as the first parameter the object variable whose method is being referenced). Modula-3 has "garbage collection" which means that you almost never "free" dynamic memory when you are done with it; it is reclaimed by the runtime system at some time after the last reference to it disappears. In fact the DISPOSE procedure needed to deallocate dynamic memory is only available in modules which are declared to the compiler as UNSAFE (meaning that they are allowed to contain ugly, nonportable code). Modula-3 has a defined "threads" interface, which means that coprocessing programs can look like what they do instead of being twisted around a very busy select(2) or poll(2) system call. The freely-available uniprocessor implementation of Modula-3's threads package uses select(2) and setjmp(2) and longjmp(2), but programmers don't have to think in terms of these details and the resulting improvement in readability -- and writability -- of coprocessing programs is quite dramatic. And of course, if you use threads in your code and someday move it to a multiprocessor with thread support, you'll get multiprocessing and concurrency for free. In support of threads, Modula-3 has mutex semaphores and a built-in LOCK statement to lock and unlock these mutexes around critical sections of code, as well as a general interface that lets threads share access to "condition variables", which BSD kernel hackers will recognize as "like sleep() and wakeup(), only how do they do that in user mode?" For example, Figure 1 shows short cycle burner that will prove that the thread scheduler is indeed preemptive: ==================================================================== Figure 1 MODULE Main; IMPORT Stdio, Wr, Fmt, Thread, Text, Time; TYPE LockedIndex = MUTEX OBJECT index := 0; END; VAR Inner := NEW(LockedIndex); Outer := 0; PROCEDURE InnerF(self: Thread.Closure): REFANY RAISES {} = BEGIN LOOP LOCK Inner DO INC(Inner.index); END; END; END InnerF; BEGIN EVAL Thread.Fork(NEW(Thread.Closure, apply := InnerF)); LOOP Time.LongPause(1); LOCK Inner DO Wr.PutText(Stdio.stdout, "Inner=" & Fmt.Int(Inner.index) & "; " & "Outer=" & Fmt.Int(Outer) & "\n"); Wr.Flush(Stdio.stdout); INC(Outer); Inner.index := 0; END; END; END Main. ================================================================ end Figure 1 This program forks off a thread which increments, with locking, a global index variable. We made this variable an "object" which subclasses the "MUTEX" object type, since this is the usual style for object types with a single mutex to lock all of its resources. We could as easily have made this a "record" type with an explicit mutex field; for that matter we could have made the index and the mutex separate global variables with no "record" or "object" type to aggregate them. Anyway, the main thread forks a thread that executes the ApplyF function, which loops forever, incrementing the global index variable which is protected by a mutex. The main thread then loops, waiting one second and then printing and clearing the index that the other thread is furiously incrementing. On the author's workstation, this program prints: % ./a.out Inner=144204; Outer=0 Inner=126392; Outer=1 Inner=114215; Outer=2 Inner=125996; Outer=3 ^C Exceptions Last in our brief survey of Modula-3's features, we note "exceptions". An experienced C programmer knows that there are two kinds of code: the kind where you check the return codes of all system and library calls, and then there's the kind that people actually write. In the first kind (which has been characterized as "you're crossing the street to buy an ice cream cone, so after every step you stop and check yourself all over to see if you have just been hit by a crashlanding 747 jetliner"), you discover that return codes breed more return codes, since if your function discovers an unusual error it would like to propagate this unusualness to its caller, which must do the same, all the way up the call stack until some caller "handles" it (or more often in the code we've seen, casts it to "void"). Modula-3 has as part of every procedure declaration a list of "conditions" which that procedure is capable of "raising". Code which calls that procedure has the option of wrapping the call in a TRY...EXCEPT...END statement if it wants to have a chance to "handle" certain exceptions; in the absence of any caller who cares, the program exits with an error. This leaves the return value available for a full range of useful things, none of which are reserved as magic cookies. It also avoids most occasions where an error encoding must be mapped from "-1 was an error" to "but NULL is *my* return error code". A Larger Example So, why would you care about Modula-3, given that the world seems to be switching to C++ and Objective-C, or pouring megaspecmarks into Common Lisp? Simply put, "it ain't over 'til the fat lady sings." C++ is an endlessly flexible language, much worse so than C; measured by the ability to write code which other programmers cannot understand or to write code which even the author cannot understand or to write code which does not do what it looks like it should be doing, C++ is the first language to eclipse C. (Sorry, Larry, C++ beat Perl by a couple of years.) One could (and has) argued that C++'s design not only permits bad code, it encourages it. Common Lisp, on the other hand, is a beautiful, elegant language which will someday join ADA in the museum of beached whales. Of the languages whose definitions are in the public domain and for which there are freely-available, portable implementations available for most of the popular POSIX-like platforms, Modula-3 is the one in which it is hardest to write code which does not do what it looks like it should be doing, or which even the author cannot understand, or which other programmers cannot understand. You may not see this from the examples shown so far, but consider the program in Figure 2, which sends an IP/UDP datagram (think "packet") requesting the network time from all inetd(8)'s on the local subnet, collects the replies, and prints the average or "network" time. ================================================================== Figure 2 UNSAFE MODULE Main; IMPORT Datagram, Netdb, Net, MyTime; (* local hacks *) IMPORT Stdio, Wr, Fmt, Thread, Time, Text; (* standard *) IMPORT Word, Ctypes; (* nonportable *) TYPE T = Ctypes.long; (* 64-bit machines will in be trouble here *) VAR Done := FALSE; Rcvd := 0; Waits := 0; NetTime: T; CONST TimeDifferential = -2085978496; (* inetd(8)'s offset *) PROCEDURE ProtocolF(self: Thread.Closure): REFANY RAISES {} = VAR port := Datagram.NewClient(NIL, mayBroadcast := TRUE); server := Netdb.NewRemotePort("255.255.255.255", "time", "udp"); timeval := NEW(REF T); BEGIN port.send(NIL, 0, server); (* 0-length datagram is a "request" *) LOOP EVAL port.recv(timeval, BYTESIZE(timeval^), server); timeval^ := Word.Minus(Net.ntohl(timeval^), TimeDifferential); IF Rcvd = 0 THEN NetTime := timeval^; ELSE NetTime := Word.Divide(Word.Plus(NetTime, timeval^), 2); END; INC(Rcvd); Done := FALSE; END; END ProtocolF; BEGIN EVAL Thread.Fork(NEW(Thread.Closure, apply := ProtocolF)); REPEAT Done := TRUE; Time.LongPause(1); INC(Waits); UNTIL Done; IF Rcvd = 0 THEN Wr.PutText(Stdio.stdout, "No Replies.\n"); ELSE NetTime := Word.Minus(NetTime, Waits); Wr.PutText(Stdio.stdout, "Network time: " & MyTime.TimeToText(NetTime) & " (" & Fmt.Int(Rcvd) & " replies)\n"); END; END Main. =============================================================== end Figure 2 One important note about this code: the Datagram module is a quick and dirty hack that we cobbled together to test some assumptions about IP/UDP performance; the actual IP/UDP interface supported in Modula-3 is likely to be quite different. Likewise the Netdb, Net, and MyTime modules are all local hacks that you don't have and wouldn't want anyway. As is true of any language which is less than a decade old, Modula-3's standard libraries are still evolving. The program makes slightly contrived use of the Thread interface; the goal is to keep collecting responses until none appear for one second. A C programmer would use alarm(2), or select(2) with a timeout. This program starts a thread which blocks in port.recv() (which, given the presence of the Thread interface, was designed without any explicit timeouts of its own); whenever a datagram comes in, this thread receives it and computes it into the running average. The main thread loops, waiting one second and then exiting the loop only when no datagrams have been received by the other thread during the last second. The code is sloppy in that it should protect its thread-shared variables with mutexes, but as a demonstration it is already as complicated as would be useful. The program is also of the "ugly and nonportable" variety; a more robust implementation would hide all of the details of the Word ("unsigned") arithmetic in other modules so that this module could do its job as straighforwardly as possible. We chose this example because it shows Modula-3 code trying to deal with the UNIX system call interface. This, in other words, is as ugly as system-dependent Modula-3 source ever has to get. You might wonder why we NEW() the timeval variable and dereference it every- where rather than creating a normal variable and passing it by ADR() in the one place we actually need its address. This has to do with the declaration of the Datagram object's recv method, which due to dampness behind its authors' ears, was rather more selective than it could have been. To get an idea of what is really possible given threads and garbage collection, consider an IP/DNS name server which needs to concurrently process multiple incoming and outgoing "zone transfers" over IP/TCP, all the while receiving, forwarding, and generating DNS requests and replies over IP/UDP. The popular BIND name server forks a subprocess for each zone transfer -- a major performance penalty if you don't have a copy-on-write fork() and your nameserver core image is tens of megabytes in size. BIND also has a very busy select(2) at its core, along with a memory management scheme that can make grown programmers want to quit their jobs and go drive tow-trucks. Given garbage collection and threads, the hardest parts of this sort of program just obviously slide into place with almost zero insertion force. Any C programmer who likes to use the CPP to layer garbage collection on top of malloc(3) and threads on top of select(2) will probably not enjoy Modula-3 very much since all that stuff is done for you and your application's code is mostly goal- rather than mechanism-oriented. Comparisons The features highlighted by the last example are: (1) variables can be given types, or initial values, or both, and if both are specified then the initial value must be of the given type; (2) this is also true of formal procedure parameters; (3) actual procedure parameters may be given positionally or by name; (4) aggregates may be returned by functions, or assigned to local procedure ("auto") variables; (5) if you want to call a typed procedure ("function") and throw away the result, you have to explicitly EVAL it; (6) EVAL in Modula-3 does not do anything like what it does in Lisp or Perl; (7) expressions of type TEXT, which includes "quoted strings" and results of functions of type TEXT, can be catenated inline with the "&" operator; (8) the ever-present newline ("\n") works as you'd expect; (9) most statements are innately compound, which means that IF and WHILE need an END, but BEGIN is meaningless for them; (10) dynamic variables created with NEW can be forgotten about, with no explicit deallocation; (11) expressions can be contained in parenthesis but need not be, and the expression used for IF and WHILE and REPEAT can be parenthesisless. Features which are not highlighted in this example but which are interesting: (1) (*comments (*can be*) nested*); (2) NEW can fill in or override default values of fields in record ("struct") or object ("struct with magic") types; (3) record and object fields can _have_ default values, which, as with variables and formal procedure parameters, cause the type to be imputed if no type is specified. Differences from C which you will probably find bizarre or irritating: (1) NEW takes as its argument a pointer type rather than the size or type of the thing being allocated; (2) there are no (pre,post)-(inc,dec)rement operators, so you have to use INC(x) for x++ and DEC(x) for x--, and neither INC() or DEC returns the new value; (3) arith- metic on unsigned integers is painful and awkward; (4) compilation time and object size are both very large compared to PCC or GCC if you use the current version of the freely-available DEC SRC compiler (which is the only one in existence at this time); (5) case is significant even for built-ins, so you _must_ type a fair amount of your program text in UPPER CASE; (6) printf() is not impossible but not straightforward, either. Differences from C++ which will either make you tense or relieved: (1) there are no enforced constructors or destructors, and though there is a convention for constructors there is none for destructors; (2) multiple inheritance, long considered either a botch or a blight (depending on who you ask), isn't here at all. The advantages (or disadvantages, depending on who you ask) of strong type checking have already been argued elsewhere. To the oft-quoted "strong type-checking is for weak minds" argument, we counter that "software systems are getting larger and more complex; programmers' minds are not." History Modula-3 was designed in the late 1980's by researchers at Digital's Systems Research Center ("DEC SRC") in Palo Alto, California, and at the Olivetti Research Center ("ORC") in Menlo Park, California. It descends most recently from Modula-2+, which came from Cedar and Mesa and Pascal; Modula-3 was lightly cross-pollinated with Oberon, as Niklaus Wirth (creator of Pascal, Modula-2, Oberon, and more recently Oberon-2) was on sabbatical at DEC SRC during part of the time that Modula-3 was being conceived. Legend has it that Wirth's main contribution to Modula-3 was to encourage its designers to leave things out; this "smallness" is apparent in that Modula-3 is smaller by far than Modula-2+, though it is still larger than Oberon or Oberon-2. A portable implementation of Modula-3 was written at DEC SRC and has been made more-or-less freely available by Digital Equipment Corporation. This compiler generates C as its intermediate language, which accounts for its portability but also its moderate speed and largish object code size; on the bright side it is free, and runs on most of the common POSIX-like platforms including Ultrix (MIPS and VAX), SunOS (SPARC and 68000), RS6000, and HP-UX (PA-RISC and 68000). More ports are under way, as is development and standardization of the runtime library. There are restrictions on the use of this compiler for commercial products, but you should get those details by reading the release notes that come with the DEC SRC compiler. Future To many programmers, C and C++ seem like forgone conclusions. Modula-3 is the only serious challenger to C++ as the next massively popular system and application programming language. This author believes that there is a good chance that there will be a market for programmers and CASE tools in Modula-3 in the next year or two, since it is a practical yet elegant software design and implementation tool which encourages clean, bug-free code and is a true pleasure to work in no matter how large the project might be (or become). If you enjoyed Modula-2 or Pascal but found them incomplete and limiting, it's a safe bet that you will find whatever you were missing...in Modula-3. If C is driving you nuts but you get cold sweats whenever you think about C++, you may find a way out of your dilemma...in Modula-3. Resources "System Programming with Modula-3", Greg E. Nelson et al, Prentice Hall "Modula-3", Samual P. Harbison, Prentice Hall comp.lang.modula3 (usenet newsgroup) m3@src.dec.com or decwrl!m3 (mailing list, gatewayed to comp.lang.modula3) gatekeeper.dec.com:~ftp/DEC/Modula-3/* (a freely available, portable Modula-3 compiler for several UNIX variants including Ultrix, SunOS, HP-UX.) $Id: m3-art,v 1.4 1992/10/13 16:47:07 vixie Exp $ ========================== end ;login: article ================================ -- Paul Vixie, DEC Network Systems Lab Palo Alto, California, USA "Don't be a rebel, or a conformist; decwrl!vixie they're the same thing, anyway. Find vixie!paul your own path, and stay on it." -me ======================================================================= 53 === Date: 26 Apr 93 20:29:25 GMT From: holt@turing.toronto.edu (Ric Holt) Subject: Object Oriented Turing Demo on FTP OBJECT ORIENTED TURING: DEMO AVAILABLE VIA FTP OOT (Object Oriented Turing) is a programming language that has been developed at the University of Toronto. An OOT demo, which includes the fully implemented language, is available for Sun/4's running X windows. See below for instructions to copy the demo to your site. OOT supports the standard OOPL features of information hiding, classes, polymorphism and generics, as well as the usual features in C and Pascal style languages. It also supports concurrency, exception handling and system programming (pointer arithmetic, bit manipulation, etc). The OOT environment is designed for teaching Computer Science. It is being used in introductory programming courses, courses on OO concepts, compiler courses, OS courses, etc. The OOT environment is fully integrated, with multi-window editing, turbo speed compiler, integrated color graphics, GUI user interface, implicit MAKE, on-line manual, integrated demos, etc. The system includes an experimental CASE tool with an interface browser and a visual system browser. HOW TO ACCESS THE OBJECT ORIENTED TURING DEMO You can get the instructions for accessing the OOT demo as follows. Start up FTP (File Transfer Protocol) by giving this UNIX command: % ftp 128.100.1.192 When you are asked for your "name", you should type: anonymous When you are asked for your "password", you should type your email address, eg: jsmith@csri.toronto.edu Once you have successfully "logged in", give the following commands to FTP: ftp> cd pub ftp> get ootDistrib Once the transfer is complete, exit FTP with the command: ftp> quit Now read the your file 'ootDistrib', which contains the instructions for accessing the OOT demo. -- Ric Holt University of Toronto holt@turing.toronto.edu ======================================================================= 54 === Date: 27 Apr 93 09:29:11 GMT From: clfung@cs.ust.hk (Fung Chi Leung) Subject: BUG in Moudla3? Hi folks, Here is a set of small programs to demonstrate a tricky bug in M3. The aim of these set of programs is to copy a file, "test.dat" to "result.dat" by two indenpendent threads, play and record. You can compile the program by "m3make -f memakefile.gc" and create a file "test.dat" to test it. The file "test.dat" should be greater than 50k in order to let bug occur before the program endedi, you can simple copy the executable GCTEST to test.dat. Here is a short description of each file: GenKeyList.ig,mg - The generic module of a simple list. CMMRecvQueueElement.i3,m3 - Data type definition for the generic list module. DMMRecvQueue.i3,m3 - Instantiation of the generic list using CMMRecvQueueElement. PMMO.i3,m3 - The play and record thread. ModuleA.i3 - Global defination of the variables. GCTEST.m3 - Main program. I found that the problem is come from the empty record definition in the file, CMMRecvQueueElement.i3. If you define an empty record there, the garbage collector will have an run-time error after a short while. However, if you insert a dummy field into the record or simple delete the empty record, everything will be alright. My system is sun sparc station running sunos 4.1.3 and the version of m3 is 2.11. Pls let me know if you have any idea about this, thanks. #!/bin/sh # This is a shell archive (produced by shar 3.49) # To extract the files from this archive, save it to a file, remove # everything above the "!/bin/sh" line above, and type "sh file_name". # # made 04/27/1993 09:00 UTC by clfung@cssu11 # Source directory /staff1/cs/clfung/Project/src/BUG/FINAL # # existing files will NOT be overwritten unless -c is specified # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 276 -rw-r----- CMMRecvQueueElement.i3 # 60 -rw-r----- CMMRecvQueueElement.m3 # 78 -rw-r----- DMMRecvQueue.i3 # 75 -rw-r----- DMMRecvQueue.m3 # 263 -rw-r----- DataMessageManager.i3 # 1576 -rw-r----- DataMessageManager.m3 # 302 -rw-r----- GCTEST.m3 # 643 -rw-r----- GenKeyList.ig # 2401 -rw-r----- GenKeyList.mg # 129 -rw-r----- ModuleA.i3 # 225 -rw-r----- PMMO.i3 # 2957 -rw-r----- PMMO.m3 # 175 -rw-r----- m3makefile.gc # # ============= CMMRecvQueueElement.i3 ============== if test -f 'CMMRecvQueueElement.i3' -a X"$1" != X"-c"; then echo 'x - skipping CMMRecvQueueElement.i3 (File already exists)' else echo 'x - extracting CMMRecvQueueElement.i3 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'CMMRecvQueueElement.i3' && INTERFACE CMMRecvQueueElement; X TYPE X BufferType = REF ARRAY OF CHAR; X X Key = RECORD (* IF you comment the line below, there will be a run-time error *) (* i : INTEGER; *) X END; X X T = RECORD X rKey : Key; X pacBuffer : BufferType; X END; X END CMMRecvQueueElement. SHAR_EOF chmod 0640 CMMRecvQueueElement.i3 || echo 'restore of CMMRecvQueueElement.i3 failed' Wc_c="`wc -c < 'CMMRecvQueueElement.i3'`" test 276 -eq "$Wc_c" || echo 'CMMRecvQueueElement.i3: original size 276, current size' "$Wc_c" fi # ============= CMMRecvQueueElement.m3 ============== if test -f 'CMMRecvQueueElement.m3' -a X"$1" != X"-c"; then echo 'x - skipping CMMRecvQueueElement.m3 (File already exists)' else echo 'x - extracting CMMRecvQueueElement.m3 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'CMMRecvQueueElement.m3' && MODULE CMMRecvQueueElement; X BEGIN END CMMRecvQueueElement. SHAR_EOF chmod 0640 CMMRecvQueueElement.m3 || echo 'restore of CMMRecvQueueElement.m3 failed' Wc_c="`wc -c < 'CMMRecvQueueElement.m3'`" test 60 -eq "$Wc_c" || echo 'CMMRecvQueueElement.m3: original size 60, current size' "$Wc_c" fi # ============= DMMRecvQueue.i3 ============== if test -f 'DMMRecvQueue.i3' -a X"$1" != X"-c"; then echo 'x - skipping DMMRecvQueue.i3 (File already exists)' else echo 'x - extracting DMMRecvQueue.i3 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'DMMRecvQueue.i3' && INTERFACE DMMRecvQueue = GenKeyList( CMMRecvQueueElement ) X END DMMRecvQueue. SHAR_EOF chmod 0640 DMMRecvQueue.i3 || echo 'restore of DMMRecvQueue.i3 failed' Wc_c="`wc -c < 'DMMRecvQueue.i3'`" test 78 -eq "$Wc_c" || echo 'DMMRecvQueue.i3: original size 78, current size' "$Wc_c" fi # ============= DMMRecvQueue.m3 ============== if test -f 'DMMRecvQueue.m3' -a X"$1" != X"-c"; then echo 'x - skipping DMMRecvQueue.m3 (File already exists)' else echo 'x - extracting DMMRecvQueue.m3 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'DMMRecvQueue.m3' && MODULE DMMRecvQueue = GenKeyList( CMMRecvQueueElement ) X END DMMRecvQueue. SHAR_EOF chmod 0640 DMMRecvQueue.m3 || echo 'restore of DMMRecvQueue.m3 failed' Wc_c="`wc -c < 'DMMRecvQueue.m3'`" test 75 -eq "$Wc_c" || echo 'DMMRecvQueue.m3: original size 75, current size' "$Wc_c" fi # ============= DataMessageManager.i3 ============== if test -f 'DataMessageManager.i3' -a X"$1" != X"-c"; then echo 'x - skipping DataMessageManager.i3 (File already exists)' else echo 'x - extracting DataMessageManager.i3 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'DataMessageManager.i3' && INTERFACE DataMessageManager; X TYPE X BufferType = REF ARRAY OF CHAR; X T <: PublicT; X PublicT = OBJECT METHODS X X Enqueue( pacDataMsg : BufferType ); X X SendDataMsg( pacDataMsg : BufferType ); X X Init( ) : PublicT; X X InitLoop( ); X END; X END DataMessageManager. SHAR_EOF chmod 0640 DataMessageManager.i3 || echo 'restore of DataMessageManager.i3 failed' Wc_c="`wc -c < 'DataMessageManager.i3'`" test 263 -eq "$Wc_c" || echo 'DataMessageManager.i3: original size 263, current size' "$Wc_c" fi # ============= DataMessageManager.m3 ============== if test -f 'DataMessageManager.m3' -a X"$1" != X"-c"; then echo 'x - skipping DataMessageManager.m3 (File already exists)' else echo 'x - extracting DataMessageManager.m3 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'DataMessageManager.m3' && UNSAFE MODULE DataMessageManager; X IMPORT Wr, Stdio, Text, Thread; IMPORT CMMRecvQueueElement, DMMRecvQueue; FROM ModuleA IMPORT oPMMOTest; X X REVEAL T = PublicT BRANDED OBJECT X mQueue : Thread.Mutex; X oRecvQueue : DMMRecvQueue.T; OVERRIDES X Enqueue := Enqueue; X InitLoop := InitLoop; X Init := Init; END; X X X X (* Init : Initialize all the internal variables and start to scan X * through the receiving queue and distribute the data packets X * to corresponding object. X *) PROCEDURE Init( self : T ) : PublicT = BEGIN X self.mQueue := NEW( Thread.Mutex ); X self.oRecvQueue := NEW( DMMRecvQueue.T ); X EVAL Thread.Fork( NEW( InitLoopDaemon, oDataMgr := self ) ); X RETURN self; END Init; X X X X TYPE X InitLoopDaemon = Thread.Closure OBJECT X oDataMgr : T; X OVERRIDES X apply := InitLoopDaemonHandler; X END; X X PROCEDURE InitLoopDaemonHandler( self : InitLoopDaemon ) : REFANY = BEGIN X self.oDataMgr.InitLoop( ); X RETURN NIL; END InitLoopDaemonHandler; X X X PROCEDURE InitLoop( self : T ) = VAR X rItem : CMMRecvQueueElement.T; BEGIN X LOOP X TRY X LOCK self.mQueue DO X rItem := self.oRecvQueue.GetQueueHead( ); X oPMMOTest.Enqueue( rItem.pacBuffer ); X END; (* LOCK *) X EXCEPT X | DMMRecvQueue.ListEmpty => X Thread.Yield( ); X END; (* TRY *) X END; (* LOOP *) END InitLoop; X X PROCEDURE Enqueue( self : T; pacDataMsg : BufferType ) = VAR X rItem : CMMRecvQueueElement.T; BEGIN X rItem.pacBuffer := pacDataMsg; X LOCK self.mQueue DO X self.oRecvQueue.InsertQueueEnd( rItem ); X END; END Enqueue; X X BEGIN END DataMessageManager. SHAR_EOF chmod 0640 DataMessageManager.m3 || echo 'restore of DataMessageManager.m3 failed' Wc_c="`wc -c < 'DataMessageManager.m3'`" test 1576 -eq "$Wc_c" || echo 'DataMessageManager.m3: original size 1576, current size' "$Wc_c" fi # ============= GCTEST.m3 ============== if test -f 'GCTEST.m3' -a X"$1" != X"-c"; then echo 'x - skipping GCTEST.m3 (File already exists)' else echo 'x - extracting GCTEST.m3 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'GCTEST.m3' && MODULE Main; X IMPORT RTHeap; IMPORT PMMO, DataMessageManager; FROM ModuleA IMPORT oPMMOTest, oDMMTest; X BEGIN X (* X RTHeap.GCOff( ); X *) X oPMMOTest := NEW( PMMO.T ); X oDMMTest := NEW( DataMessageManager.T ); X oPMMOTest.Init( ); X EVAL oDMMTest.Init( ); X oPMMOTest.Start( ); X LOOP END; END Main. SHAR_EOF chmod 0640 GCTEST.m3 || echo 'restore of GCTEST.m3 failed' Wc_c="`wc -c < 'GCTEST.m3'`" test 302 -eq "$Wc_c" || echo 'GCTEST.m3: original size 302, current size' "$Wc_c" fi # ============= GenKeyList.ig ============== if test -f 'GenKeyList.ig' -a X"$1" != X"-c"; then echo 'x - skipping GenKeyList.ig (File already exists)' else echo 'x - extracting GenKeyList.ig (Text)' sed 's/^X//' << 'SHAR_EOF' > 'GenKeyList.ig' && GENERIC INTERFACE GenKeyList( Element ); X EXCEPTION X ListFull; (* raise when it is a bounded limit queue and X * the number of element is greater than the limit X *) X ListEmpty; (* raise when removing a node from a empty list *) X TYPE X Status = BOOLEAN; X X T <: PublicT; X PublicT = OBJECT X METHODS X X (* Set the upper boundary of the queue *) X Init( nLength : CARDINAL := 0 ): PublicT; X X (* Insert a node at the queue end *) X InsertQueueEnd( rItem : Element.T ) RAISES { ListFull }; X X (* Return the queue head node *) X GetQueueHead( ) : Element.T RAISES { ListEmpty }; X X END; (* OBJECT *) X END GenKeyList. SHAR_EOF chmod 0640 GenKeyList.ig || echo 'restore of GenKeyList.ig failed' Wc_c="`wc -c < 'GenKeyList.ig'`" test 643 -eq "$Wc_c" || echo 'GenKeyList.ig: original size 643, current size' "$Wc_c" fi # ============= GenKeyList.mg ============== if test -f 'GenKeyList.mg' -a X"$1" != X"-c"; then echo 'x - skipping GenKeyList.mg (File already exists)' else echo 'x - extracting GenKeyList.mg (Text)' sed 's/^X//' << 'SHAR_EOF' > 'GenKeyList.mg' && GENERIC MODULE GenKeyList( Element ); X TYPE X PtrNode = REF RECORD (* Abstract node of type element.T *) X rContent : Element.T; (* data type of node element *) X rpNext : PtrNode := NIL; (* Pointer to next node *) X END; X REVEAL T = PublicT BRANDED OBJECT X rpHead, rpTail, rpCurrent : PtrNode; (* head and tail pointer *) X (* If nMaxListLength = 0 THEN there is no list queue limiation *) X nMaxListLength : CARDINAL; (* maximum list length *) X nCurListLength : CARDINAL; (* current list length *) X OVERRIDES X Init := Init; X InsertQueueEnd := InsertQueueEnd; X GetQueueHead := GetQueueHead; X END; X X (* Init: Initialize all the internal variables X * IN: nLength - Maximum list length X *) PROCEDURE Init( self : T; nLength : CARDINAL := 0 ) : PublicT = BEGIN X IF self = NIL THEN X self := NEW( T ); X END; (* IF *) X self.rpHead := NIL; self.rpTail := NIL; self.rpCurrent := NIL; X self.nMaxListLength := nLength; X self.nCurListLength := 0; X RETURN self; END Init; X X (* InsertQueueEnd: Insert a item to the end of the list X * IN: rItem - Node item to be added X * ECP: ListFull - Raise if the list larger than the maximum list length X *) PROCEDURE InsertQueueEnd( self : T; rItem : Element.T ) RAISES { ListFull } = VAR prTmp : PtrNode; BEGIN X IF self.nCurListLength >= self.nMaxListLength AND self.nMaxListLength # 0 TH EN X RAISE ListFull; X ELSE X prTmp := NEW( PtrNode ); X prTmp.rpNext := NIL; X prTmp.rContent := rItem; X IF self.rpTail = NIL THEN (* Case of none element *) X self.rpHead := prTmp; X self.rpTail := prTmp; X ELSE X self.rpTail.rpNext := prTmp; X self.rpTail:= prTmp; X END; (* IF *) X INC( self.nCurListLength ); X END; (* IF *) END InsertQueueEnd; X X (* GetQueueHead: Remove and return the first element from the list X * OUT: The First element X * ECP: ListEmpty - Raise if the list is empty X *) PROCEDURE GetQueueHead( self : T ) : Element.T RAISES { ListEmpty } = VAR rpTmp : PtrNode; BEGIN X IF self.nCurListLength <= 0 THEN X RAISE ListEmpty; X ELSE X IF self.rpHead = self.rpTail THEN (* Case of one element *) X rpTmp := self.rpHead; X self.rpHead := NIL; X self.rpTail := NIL; X ELSE X rpTmp := self.rpHead; X self.rpHead := self.rpHead.rpNext; X END; (* IF *) X DEC( self.nCurListLength ); X RETURN rpTmp.rContent; X END; (* IF *) END GetQueueHead; X X BEGIN END GenKeyList. SHAR_EOF chmod 0640 GenKeyList.mg || echo 'restore of GenKeyList.mg failed' Wc_c="`wc -c < 'GenKeyList.mg'`" test 2401 -eq "$Wc_c" || echo 'GenKeyList.mg: original size 2401, current size' "$Wc_c" fi # ============= ModuleA.i3 ============== if test -f 'ModuleA.i3' -a X"$1" != X"-c"; then echo 'x - skipping ModuleA.i3 (File already exists)' else echo 'x - extracting ModuleA.i3 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'ModuleA.i3' && INTERFACE ModuleA; X IMPORT PMMO, DataMessageManager; X VAR X oPMMOTest : PMMO.T; X oDMMTest : DataMessageManager.T; X END ModuleA. SHAR_EOF chmod 0640 ModuleA.i3 || echo 'restore of ModuleA.i3 failed' Wc_c="`wc -c < 'ModuleA.i3'`" test 129 -eq "$Wc_c" || echo 'ModuleA.i3: original size 129, current size' "$Wc_c" fi # ============= PMMO.i3 ============== if test -f 'PMMO.i3' -a X"$1" != X"-c"; then echo 'x - skipping PMMO.i3 (File already exists)' else echo 'x - extracting PMMO.i3 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'PMMO.i3' && INTERFACE PMMO; X CONST X BUFFERSIZE = 512; X TYPE BufferType = REF ARRAY OF CHAR; X T <: PublicT; X PublicT = OBJECT METHODS X Record( ); X Play( ); X Init( ); X Start( ); X Enqueue( pacBuffer : BufferType ); END; X END PMMO. SHAR_EOF chmod 0640 PMMO.i3 || echo 'restore of PMMO.i3 failed' Wc_c="`wc -c < 'PMMO.i3'`" test 225 -eq "$Wc_c" || echo 'PMMO.i3: original size 225, current size' "$Wc_c" fi # ============= PMMO.m3 ============== if test -f 'PMMO.m3' -a X"$1" != X"-c"; then echo 'x - skipping PMMO.m3 (File already exists)' else echo 'x - extracting PMMO.m3 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'PMMO.m3' && MODULE PMMO; X IMPORT Wr, Rd, Text, Char, Thread, FileStream, Stdio; IMPORT DMMRecvQueue, CMMRecvQueueElement; FROM ModuleA IMPORT oDMMTest; X REVEAL T = PublicT BRANDED OBJECT X mPMMOQueue : Thread.Mutex; X oPMMOQueue : DMMRecvQueue.T; OVERRIDES X Enqueue := Enqueue; X Play := Play; X Record := Record; X Start := Start; X Init := Init; END; X X PROCEDURE Init( self : T ) = BEGIN X self.mPMMOQueue := NEW( Thread.Mutex ); X self.oPMMOQueue := NEW( DMMRecvQueue.T ); END Init; X X PROCEDURE Enqueue( self : T; pacBuffer : BufferType ) = VAR X rNewItem : CMMRecvQueueElement.T; BEGIN X rNewItem.pacBuffer := pacBuffer; X LOCK self.mPMMOQueue DO X self.oPMMOQueue.InsertQueueEnd( rNewItem ); X END; END Enqueue; X PROCEDURE Record( self : T ) = VAR X pFileId : Rd.T; X pacBuffer : BufferType; X iCount, iSwitch : INTEGER := 0; BEGIN X pFileId := FileStream.OpenRead( "test.dat" ); X REPEAT X (* The first byte is used to indicate the end of file *) X (* When it is the last buffer, the first byte is set to 'e', X * otherwise set to 'n' X *) X pacBuffer := Char.NewArray( BUFFERSIZE+1, ' '); X iCount := 0; X WHILE ( NOT Rd.EOF ( pFileId ) AND iCount < BUFFERSIZE ) DO X pacBuffer[iCount+1] := Rd.GetChar( pFileId ); X iCount := iCount+1; X END; X Wr.PutText( Stdio.stderr, "Read one buffer\n" ); X IF NOT Rd.EOF( pFileId ) THEN X pacBuffer[0] := 'n'; X ELSE X pacBuffer[0] := 'e'; X END; X oDMMTest.Enqueue( pacBuffer ); X (* X iSwitch := iSwitch + 1; X IF iSwitch = 2 THEN X iSwitch := 0; X Thread.Yield( ); X END; X *) X UNTIL Rd.EOF( pFileId ); X Rd.Close( pFileId ); END Record; X X PROCEDURE Play( self : T ) = VAR X pFileId : Wr.T; X pacBuffer : BufferType; X rItem : CMMRecvQueueElement.T; X bEnd := FALSE; BEGIN X pFileId := FileStream.OpenWrite( "result.dat" ); X REPEAT X TRY X LOCK self.mPMMOQueue DO X rItem := self.oPMMOQueue.GetQueueHead( ); X END; X pacBuffer := rItem.pacBuffer; X FOR iTmp := 1 TO BUFFERSIZE DO X Wr.PutChar( pFileId, pacBuffer[iTmp] ); X END; X Wr.PutText( Stdio.stderr, "Write one buffer\n" ); X IF pacBuffer[0] = 'e' THEN X bEnd := TRUE; X END; X EXCEPT X | DMMRecvQueue.ListEmpty => X (* X Thread.Yield( ); X *) X END; X UNTIL bEnd; X Wr.Close( pFileId ); END Play; X X TYPE X PlayThread = Thread.Closure OBJECT X oPMMO : T; X OVERRIDES X apply := PlayThreadHandler; X END; X X RecordThread = Thread.Closure OBJECT X oPMMO : T; X OVERRIDES X apply := RecordThreadHandler; X END; X X PROCEDURE Start( self : T ) = BEGIN X EVAL Thread.Fork( NEW( RecordThread, oPMMO := self ) ); X EVAL Thread.Fork( NEW( PlayThread, oPMMO := self ) ); END Start; X X PROCEDURE PlayThreadHandler( self : PlayThread ) : REFANY = BEGIN X self.oPMMO.Play( ); X RETURN NIL; END PlayThreadHandler; X PROCEDURE RecordThreadHandler( self : RecordThread ) : REFANY = BEGIN X self.oPMMO.Record( ); X RETURN NIL; END RecordThreadHandler; X BEGIN END PMMO. SHAR_EOF chmod 0640 PMMO.m3 || echo 'restore of PMMO.m3 failed' Wc_c="`wc -c < 'PMMO.m3'`" test 2957 -eq "$Wc_c" || echo 'PMMO.m3: original size 2957, current size' "$Wc_c" fi # ============= m3makefile.gc ============== if test -f 'm3makefile.gc' -a X"$1" != X"-c"; then echo 'x - skipping m3makefile.gc (File already exists)' else echo 'x - extracting m3makefile.gc (Text)' sed 's/^X//' << 'SHAR_EOF' > 'm3makefile.gc' && module(DMMRecvQueue) module(CMMRecvQueueElement) module(PMMO) module(DataMessageManager) generic_module(GenKeyList) interface(ModuleA) implementation(GCTEST) program(GCTEST) X SHAR_EOF chmod 0640 m3makefile.gc || echo 'restore of m3makefile.gc failed' Wc_c="`wc -c < 'm3makefile.gc'`" test 175 -eq "$Wc_c" || echo 'm3makefile.gc: original size 175, current size' "$Wc_c" fi exit 0 -- Leung [Chi-Leung Fung] | email: clfung@cs.ust.hk | phone: (852) 358 7023 Smile, it makes people wonder what you are thinking. ======================================================================= 55 === Date: Tue, 27 Apr 93 15:53:10 GMT From: kalsow@src.dec.com (Bill Kalsow) Subject: Re: BUG in Moudla3? Thanks for the bug report. I've fixed the problem in my copy of the compiler. The fix will be included in the next release. The problem was that the compiler was generating "struct { int filler; }" for empty records, but claiming that they occupied zero bytes. Empty structs cause C compilers to get grumpy. The workaround is to avoid empty records in structures that are heap allocated. If you're desperate, the patch is to add the five marked lines below at about line 181 of compiler/src/types/RecordType.m3: (* assign the final offsets to each field *) SizeAndAlignment (p.scope, p.recSize, p.align); > IF (p.recSize = 0) THEN > (* add the 'filler' field *) > p.align := MAX (Target.INTSIZE, Target.STRUCTURESIZEBOUNDARY); > p.recSize := RoundUp (Target.INTSIZE, p.align); > END; (* compute the hash value for this record *) hash := Word.Plus (Word.Times (943, p.recSize), p.align); Please send bug reports to m3-request@src.dec.com. Thanks - Bill Kalsow ======================================================================= 56 === Date: 27 Apr 93 23:59:06 -0600 From: rustad@mhd.moorhead.msus.edu Subject: Survey Pros & Cons OOP Object-Oriented Programming Survey This survey is a meant to find the current relationship between programmers and Object-Oriented Programming. Please return this survey before May 5, 1993. Return to rustad@mhd.moorhead.msus.edu Would you like a copy of the published statistics? (yes/no) _______ Your Occupation: __________________________________________________________________________ Years of Programming Experience: __________________________________ Programming Languages you're associated with: __________________________________________________________________________ Years of OOP experience: __________________________________ Your preferred OOP language: __________________________________________________________________________ Is there an advantage to OOP (yes/no) _________ Is OOP coding faster than traditional programming (yes/no) _________ Is OOP maintenance quicker and easier than traditional (yes/no or opinion): __________________________________________________________________________ Comments: (pros & cons with Object-Oriented Programming) ======================================================================= 57 === Date: 29 Apr 1993 08:49:45 GMT From: laverman@cs.rug.nl (Bert Laverman) Subject: Small patch to RCS to recognize modula-3 files After having to edit an RCS maintained file for the umptienth time, I decided to patch RCS so it will recognize the modula-3 filename suffixes (i3, ig, m3, mg) and use the currect comment leader for multiline comments (" * ") in stead of the annoying "# ". *** rcsfnms.old Thu Apr 29 10:43:34 1993 --- rcsfnms.c Thu Apr 29 10:43:53 1993 *************** *** 189,199 **** --- 189,203 ---- "h", " * ", /* C-header */ "hpp", "// ", /* C++ header */ "hxx", "// ", + "i3", " * ", /* Modula-3 interface */ + "ig", " * ", /* Modula-3 generic interface */ "l", " * ", /* lex NOTE: conflict between lex and franzlisp */ "lisp",";;; ", /* Lucid Lisp */ "lsp", ";; ", /* Microsoft Lisp */ + "m3", " * ", /* Modula-3 Module */ "mac", ";; ", /* macro (DEC-10, MS-DOS, PDP-11, VMS, etc) */ "me", ".\\\" ",/* me-macros t/nroff*/ + "mg", " * ", /* Modula-3 generic module */ "ml", "; ", /* mocklisp */ "mm", ".\\\" ",/* mm-macros t/nroff*/ "ms", ".\\\" ",/* ms-macros t/nroff*/ Greetings, Bert -- #include Bert Laverman, Dept. of Computing Science, Groningen University Friendly mail to: laverman@cs.rug.nl The rest to: /dev/null ======================================================================= 58 === Date: Fri, 30 Apr 93 01:15:15 GMT From: msm@src.dec.com Subject: Re: seeking trestle/mt experiences Date: Thu, 29 Apr 93 18:14:58 -0700 X-Received: by gillie.pa.dec.com; id AA03154; Thu, 29 Apr 93 18:15:08 -0700 X-Received: by src-news.pa.dec.com; id AA05733; Thu, 29 Apr 93 18:15:12 -0700 X-Mts: smtp A while ago, David Sternlicht asked about experience with locking levels, and with the locking strategies used in Trestle. Here's my perspective, after a brief intro: For those not familiar with the intricacies of locking in Trestle, the main thing to be aware of is that there are some, since we're trying to accomodate multi-threaded applications without falling into race conditions. In particular, we want to deliver events to the application in a way that's consistent with the window tree at the time we deliver the event. Since VBTs do event propagation for themselves (as opposed to having a centralized mechanism containing the entire window tree), there are really only three alternatives: 1) while relaying the event down the tree, use the local geometry, and don't worry about it being the same at the time the method of that split goes on to relay things further. The problem with this is that there's no guarantee that the position of the button click (say) will still even be inside the window when we get around to processing it. Thus, it's possible that an event will have to be discarded, since we won't know where to send it. We decided that users that clicked while their application was rearranging itself shouldn't care which window got the button press, but they ought to be able to count on the fact that some window that will, and that it should be a window that could have received the button press if event delivery was infinitely fast compared to rearranging. 2) as in 1), except that we keep a versioned history of the window tree. When relaying an event, we can use the geometry as of the time of the event. This has many virtues, along with one serious drawback: it's really annoying to implement. Since we wanted split writing to be easy (and full consistency would require that leaf VBT writers also support historied geometry!) we reluctantly decided that this was too much of a burden. 3) as in 1), except that we lock the geometry during event delivery, so that everything is consistent with some version of the layout. The problem with this is that it means that some lock on the geometry will be held even while we're delivering events to normal client code. That means that the procedures they call in such a state must support being called with this lock, VBT.mu, held. Since this is supposed to be our geomtry lock, we also need client code that intends to modify the window tree to acquire VBT.mu. In fact, for some actions, we allow a finer-grain of locking, VBT.mu.v, which is v's share of VBT.mu. We use this when it's safe to deliver events concurrently to all the subwindows of a window; for example when we're asking the application to repair damage. This makes the assumption that it's unreasonable for an application to change its overall layout in response to having a small piece fix some damage. We could have decided to step outside the locks provided by the language, and support thread-reentrant locks; that is, a mutex which can be repeatedly reacquired by a single thread. We chose not to, since it complicates entry and exit from the lock, it's against SRC religion, and it doesn't help an application that wants to do some work synchronously in a forked thread. It would have permitted us to claim that everything was a relatively simple monitor, howeve; one where we would hide the work of acquiring or reacquiring the mutex as needed. At any rate, to support multi-threaded programs, we would still have had to tell programmers what locks were held when callbacks were activated, and what locks they needed to hold (or make sure stayed held) to make a call. The locking level scheme that we adopted is relatively simple: to avoid deadlock, we assume that there's a partial order on locks, with VBT.mu down near the bottom, and that programs can only acquire a lock if every lock they hold is smaller in the partial order. Every method declaration, callback procedure parameter, and procedure has an annotation that describes what locks may, will, or must be held when the procedure is activated; for example, a method may say LL.sup = VBT.mu; this means that on entry (and exit) VBT.mu will be held, and no greater lock will be. LL, the locking level, is just the set of locks that are stably held in the environment of the calling thread (if there's a thread synchronously waiting for this thread to do something, and it holds locks, you should count those, too). LL.sup denotes the supremum of LL, so its the tightest lock held (or held for) the thread. Thus, it's safe for this thread to call any procedure that expects VBT.mu IN LL, or to acquire any mutex greater than VBT.mu in order to call some procedure with a more demanding locking level. It mustn't call a procedure that expects LL.sup < VBT.mu. To keep track of the partial ordering, we annotate declarations of mutexes with a description of where they fall in the partial order, in comparison with all of the mutexes that we reasonably expect to be in the scope of any program that imports the interface where this mutex is declared. Sometimes we'll just say that a mutex is maximal; we usually do this for mutexes that are used by implementations that don't make any out calls. Some clients may import essentially disconnected parts of the mutex space. In this case, it's incumbent on the client to discover if there's any secret implementation-dependent ordering of the mutexes that it ought to respect; in general, it's safest not to try to define an ordering between them. In addition, to solve data race conditions, we annotate the declaration of a variable, or a field of a record or object, with the locks that protect it. Our usual policy is that you need to hold any one of the locks in order to read the data, and all of them in order to write. This comes in handy when you have some data that has to be read under uncontrolled circumstances (like the clipping information you need in order to paint), but which you only modify when something exciting is happening. At any rate, Greg and I found this technique invaluable in building Trestle. Before we invented our notation for this, we basically had to keep the knowledge of lock ordering and procedure requirements in our heads, which proved to be quite fallible over the course of time; we had a modest number of deadlocks, and more race conditions than I care to recall in the very earliest versions of Trestle (circa 1986-7; the rewrite in M3 has always been pretty clean in this area). Over the years, we've even gained a few converts: when you write a large system, it just gets too hard to keep it all in your head, and potential race conditions invariably happen; the really good ones usually don't happen until several months after you've shipped some library to a bunch of new programmers and completely forgotten exactly how everything worked. By not having reentrant mutexes, we gain some advantages; our locking levels can almost always just mention the supremum of the locks held. With reentrant mutexes, there's probably a bit more of a temptation to take advantage of locks that are in your LL but that are fairly deep in the ordering below the supremum. In addition, you would need to be careful in specifying which procedures you could safely call, by explaining exactly which locks might be needed, so that you don't have to worry that it might need some lock higher than the one that it first tries to acquire (but which might be lower than some other lock you already have--deadlock city!) Mark