[M3devel] proposal for dealing with lazy console--please review and comment!

Randy Coleburn rcoleburn at scires.com
Thu Jun 19 05:18:59 CEST 2008


Jay:
 
I'd be satisfied just to deal with this on a per program instance, rather than at a thread level.  Indeed, I'm not sure it makes sense on a per thread level.  The Stdio module and global vars are shared by all code in the program process.
 
I'm wondering if it might be better at this point to use environment variables to control the behavior.  The current implementation initializes everything during module initialization at program startup.  Thus, this occurs before dependent modules get a chance to run and influence the behavior.
 
Perhaps the lazy console allocation should be the default unless a certain environment variable is set, say CM3_LazyConsole=FALSE.  In this case the initialization code would turn off the lazy allocation and in the case of a GUI-mode program on Windows the Stdio.stdin/stdout/stderr would be NIL.  If CM3_LazyConsole=TRUE or is not defined, you would get a lazy allocated console on Windows GUI-mode programs and a regular console otherwise.
 
This approach has the advantage that no interfaces have to change.
 
Of course, if folks want to add finer grains of control as you suggest, that would be ok.  I just want to be able to prevent the popup of the lazy allocated console.
 
I'm willing to make the modifications to the code unless someone objects to my approach.
 
Regards,
Randy

>>> Jay <jayk123 at hotmail.com> 6/18/2008 1:20 PM >>>
Randy, really, the vast majority of behavior is undocumented and not controllable.
However I agree making this controllable is perfectly reasonable.
The folks that did this were I believe Critical Mass, between "4.1" and "5.1", though granted the history is not completely known, just that 4.1 and earlier doesn't behave this way.
 
I strongly advocate a type-based solution here.
 
However, I believe there are several bits per handle however, not one.
Not at the Win32 level, but in terms of the control you would want in the Modula-3.
 
There is:
  Is the console visible?
    Either because it started that way, or because "someone" has written to it already.
 
  Should any/no write make it visible?
 
  Should "this particular" write make it visible?
 
That is, you probably want the ability to avoid the console becoming visible.
You probably want the ability to control this globally or per-write.
Maybe even per-thread and not just per-process.
And, say, if there is a severe error, you want to enable it becoming visible.
And, say, if someone else wrote an error and made it visible and now you just have a warning, you might want to "piggy back" on the visibility and go ahead and print.
 
You may even want to rehide the console, if that is possible.
(Could expose this in the interface and it make it a nop..)
 
Controlling this per-thread or per-process or per-write is actually pretty problematic.
  Because even if it is per-thread or per-process, I believe it should at the same time be per-handle. I should be able to block revelation on stdout for current thread, and then restore it when I am done. While leaving stderr unaltered, on the theory that stderr output is more important. Similarly per-process. But then each handle has per-thread locals. Ok, duh, per-process doesn't make sense, that's the same as per-handle.
 
Controlling it per-handle is not problematic. Each handle would just have a fixed set of extra bits.
 
I believe controlling it module-wide either per-process or per-thread *might* be interesting, but less so. Globals are bad. Even if hidden behind thread-safe functions. Just because Modula-3 nicely contains process-globals in modules, doesn't make them acceptable. I think modules are overrated actually, and "objects" -- instances of types are much more important. Modula-3 does "work", just that I should in general create Foo.T data and pass them as the first parameter to Foo.DoSomething. Programming is much more "type based" than "module based" imho. I know there is some disagreement here, but I'm not sure there is much.
 
Really, there is a general issue of globals vs. parameters to functions, throughout a callstack.
 
One implementation strategy would be to able to create a "wrapper" object.
You would set the "policy" on that object -- perhaps via which type you created in the first place. You would pass that around to all your code. That would achieve per-thread, or per-whatever-you want, BUT it'd require you pass it around to all of your code.
 
It is a tough discpline to really pass around all parameters, and not rely on some larger "global" or per-thread context. Thread locals and globals quite stink, and "plumbing the full depths of a call tree" can also be quite difficult". The problem, you know, of "oops, I forgot to add a parameter in lots of places. What do I do now? I know, I'll make a thread local, set it at the top of the call tree, check it in the middle or at the bottom, but not pass it all around..." It's a difficult problem. Much of the code in a particular call tree might not know or care about what the top and bottom care about, but somehow should be able to ferry along "context". Thread locals are so tempting and oh so problematic...
 
 - Jay

Date: Wed, 18 Jun 2008 12:50:29 -0400
From: rcoleburn at scires.com 
To: m3devel at elegosoft.com 
Subject: Re: [M3devel] proposal for dealing with lazy console--please review and comment!

Hi Rodney:
 
Thanks for your reply.
 
The issue is that for cm3 on Windows you can specify -gui as a command line option.  This option causes the program to be built as a Windows GUI-mode application, rather than as a console application.  For a GUI-mode application, the Stdio file handles are NIL because it has no console.
 
Seemingly, to prevent a lot of errors when trying to read/write Stdio, some folks introduced the idea of a lazy console post cm3 v4.1.  What happens now "under the covers" is that on a GUI-mode program the Stdio file handles are allocated as Lazy Consoles.  Then, whenever Stdio.stdout/stderr/stdin is used, the underlying code realizes the first use and magically allocates a new console window on the fly.  This console window pops up on the screen on top of your GUI-mode window.
 
My objection is that this behavior is not documented in any interface and the programmer has no way to control the behavior.  I want to make such control possible.
 
Hope this explanation helps a bit.
 
Regards,
Randy

>>> "rodney.bates" <rodney.bates at wichita.edu> 6/18/2008 10:36 AM >>>
I don't understand well enough what it means for a console
to be lazily-allocated, but I wonder if it makes any sense to
allow client code, by assignments to Stdio.stdout_Islazy, to 
change this property in general.  Why would a FileWr.T ever
be lazy, for example?  Can't the cases where the lazy property 
needs to be controlled by client code be enclosed inside procedures
that do it in a thread-safe way?

>4.  Modify Stdio implementation to properly initialize the new
>variables during module initialization.
>This change will be transparent to all clients.
>
>Now, with these changes, it will be possible for a client to know
>whether stdout, stderr, and/or stdin represent lazily allocated
>consoles or not, then act accordingly.
>
>For example, if I want to make sure messages written to stdout are
>recorded even for a GUI-app, but I don't want a popup, I could do the
>following:
>    IF (Stdio.stdOut_IsLazy) OR (Stdio.stdout = NIL)
>    THEN
>       Stdio.stdout := FileWr.Open("myLogFile.txt");
>       Stdio.stdOut_IsLazy := FALSE;
>    END;
>Now the above code fragment does show the possibility of a race
>condition in multi-threaded code.
>

Rodney Bates
Retired assistant professor
Computer Science


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20080618/dc965f12/attachment-0002.html>


More information about the M3devel mailing list