View previous topic :: View next topic |
Author |
Message |
sean
Joined: 24 Jun 2004 Posts: 609 Location: Bay Area, CA
|
Posted: Mon Apr 03, 2006 9:57 pm Post subject: Stdout vs. Cout |
|
|
Can someone explain why both of these exist? Is the purpose of Cout simply to offer a low-overhead alternative for very basic problems? I was a bit confused that the "hello world" example uses Cout, but that I wasn't able to use it for anything but strings. And Stdout/Stdin import Console, but don't actually use it anywhere... in fact, nothing in Mango uses mango.io.Console, so far as I can tell. Should it perhaps simply be deprecated? |
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Mon Apr 03, 2006 11:43 pm Post subject: Re: Stdout vs. Cout |
|
|
sean wrote: | Can someone explain why both of these exist? Is the purpose of Cout simply to offer a low-overhead alternative for very basic problems? I was a bit confused that the "hello world" example uses Cout, but that I wasn't able to use it for anything but strings. And Stdout/Stdin import Console, but don't actually use it anywhere... in fact, nothing in Mango uses mango.io.Console, so far as I can tell. Should it perhaps simply be deprecated? |
Hi Sean;
Console exposes a set of Buffer instances, tied to console IO. At this level, one can certainly think of them as low overhead concepts ~ because they truly are. However, being buffers, they don't support type conversion/coercion such as that exposed by the Reader/Writer layer. Still, they're really handy for buffered IO on the console ~ you can pass them directly to an Iterator, for example; and the mango.log package uses them in lieu of Stdout et. al.
Digging a bit deeper, you'll find that the Console buffers are tied to a ConsoleConduit. You can use these directly also, if you wish, for block-oriented read() & write() access.
If you take another look at Stdin & Stdout, you'll probably see that they enclose Cin, Cout, & Cerr ~ thus Stdin & Stdout are actually data conversion layers upon the Console instance buffers. That layer treats the console as just another set of buffered conduits. I imagine it was the static Cin, Cout, and Cerr instances within the Console module that threw you off?
The mango.io.Print module also uses the Console buffers, in a similar manner. I should note that the Console buffers/conduit are UTF8 only, and it's up to the higher levels to convert appropriately (which they do). This assertion greatly simplifies portability across Win32 and Linux, and eliminates a whole class of issues regarding console redirection (Console used to be templated for char/wchar/dchar, but the complexity went up quite dramatically).
- Kris |
|
Back to top |
|
|
sean
Joined: 24 Jun 2004 Posts: 609 Location: Bay Area, CA
|
Posted: Tue Apr 04, 2006 11:25 am Post subject: Re: Stdout vs. Cout |
|
|
kris wrote: | Console exposes a set of Buffer instances, tied to console IO. |
Sigh... I realized I forgot to check the object types after I'd posted and my laptop batteries died
Quote: | If you take another look at Stdin & Stdout, you'll probably see that they enclose Cin, Cout, & Cerr ~ thus Stdin & Stdout are actually data conversion layers upon the Console instance buffers. That layer treats the console as just another set of buffered conduits. I imagine it was the static Cin, Cout, and Cerr instances within the Console module that threw you off? |
It was. Between my experience with C++ and the "hello world" example, I blindly assumed that Cin, Cout, and Cerr were intended to serve a similar purpose to what I'd been used to, and it threw me when they didn't behave as expected. I suppose I need to add a few more modules to Ares as well then, as it doesn't have Stdin and Stdout yet. I must have simply been too busy with other things to test the included Mango stuff beyond simple string IO. |
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Tue Apr 04, 2006 1:11 pm Post subject: |
|
|
BTW: there's currently a bug in Stdin, which I haven't fixed yet (apologies to the original poster on that). |
|
Back to top |
|
|
sean
Joined: 24 Jun 2004 Posts: 609 Location: Bay Area, CA
|
Posted: Tue Apr 04, 2006 6:30 pm Post subject: |
|
|
No worries
So I've added Stdin, Stdout, and their dependencies, Ares builds fine and whatnot. But when I try to build a test app against the new Ares library I get a bunch of errors like this:
Quote: | C:\bin\dmd\bin\..\lib\phobos.lib(Stdin)
Error 42: Symbol Undefined __Class_3std2io10TextReader19__T11TextReaderTTaZ11TextReaderT
C:\bin\dmd\bin\..\lib\phobos.lib(Stdin)
Error 42: Symbol Undefined __Class_3std2io4text13QuoteIterator22__T14QuoteIteratorTTaZ14QuoteIteratorT |
This looks a lot like the "template is being instantiated into the wrong module" business that was talked about in the D.bugs forums a while back, but I've never encountered it before. Has this ever been a problem in Mango? If so, how did you get around it? |
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Tue Apr 04, 2006 9:13 pm Post subject: |
|
|
Egad ... No, I've not run into that before. And it does look suspiciously like the template "-g" issue. What's the official word on that, anyway? Is it not fixed yet?
I suppose one way to sidestep it is to eliminate templates from the library altogether; though that's not exactly productive. I wonder if some choice usage of "alias" can resolve it? |
|
Back to top |
|
|
sean
Joined: 24 Jun 2004 Posts: 609 Location: Bay Area, CA
|
Posted: Tue Apr 04, 2006 10:00 pm Post subject: |
|
|
Hopefully. The really weird thing is that I checked the asm in the object files and the class definitions were present so far as I could tell. I'm starting to wonder whether they're being discarded by the lib tool for some reason. But I'll keep investigating it and see what I can figure out. |
|
Back to top |
|
|
sean
Joined: 24 Jun 2004 Posts: 609 Location: Bay Area, CA
|
Posted: Wed Apr 05, 2006 2:59 pm Post subject: |
|
|
Okay, I found a description of the problem and a hack to address it:
http://www.digitalmars.com/d/archives/digitalmars/D/23685.html
Apparently, this can come up while importing any pure template module on Windows and is a result of how templates are instantiated (using a COMDAT). Walter has also said that there is no easy compiler fix for this, and while I'm skeptical, we're stuck with it for now. I've maed the following changes to address the problem:
- for a problem import file, add a block just below the module declaration and import blocks like so: Code: | module std.io.Blah;
version( Windows )
{
int tagBlah;
} |
- for a file importing the above, add a block in the same location like so: Code: | import std.io.Blah;
version( Windows )
{
private int* tagBlah = &std.io.Blah.tagBlah;
} |
So not at all ideal and perhaps something a bit more optimal could be discovered, but it works.
In related news, I tried running the code below: Code: | import std.io.Stdin;
import std.io.Stdout;
void main()
{
int i;
Stdout( "input: "c );
Stdin( i );
Stdout( "got: "c )( i )( CR );
} |
and got this output while running it: Quote: | C:\code\d>test
1
input: got: 1
C:\code\d> |
Adding a call to 'flush' fixed things however: Code: | import std.io.Stdin;
import std.io.Stdout;
void main()
{
int i;
Stdout( "input: "c ).flush();
Stdin( i );
Stdout( "got: "c )( i )( CR );
} |
I suppose this makes for a better design than trying to rig some way of flushing output on a read op, but the current behavior surprised me so I thought I'd mention it. I think what confused me is that Console flushes on every write, so this behavior was unexpected. |
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Wed Apr 05, 2006 3:44 pm Post subject: |
|
|
What do you think should happen vis-a-vis Stdout flushing? |
|
Back to top |
|
|
sean
Joined: 24 Jun 2004 Posts: 609 Location: Bay Area, CA
|
Posted: Wed Apr 05, 2006 4:40 pm Post subject: |
|
|
Seems I refer to C++ IOStreams a lot, but they're what I'm most familiar with, so... IOStreams have two methods devoted to this, defined like so:
Code: | // returns an output sequence that is tied to (synchronized with)
// the sequence controlled by the stream buffer.
basic_ostream<charT,traits>* tie() const;
// Ties to a new output stream and returns the previous value of tie().
basic_ostream<charT,traits>* tie(basic_ostream<charT,traits>* tiestr); |
Note that it's only possible to tie to an output stream, so input and output stream code contains something like this:
Code: | if( tiedObj != null )
tiedObj.flush();
// read from or write to device as appropriate |
Thus the tied stream is flushed whenever the tying stream has exhausted its buffer and needs to read/write the underlying device. Regarding Stdin/Stdout:
Quote: | After the object cin is initialized, cin.tie() returns &cout. |
So basically, I think Stdin and Stdout should be synchronized such that any time Stdin requests input from the console device it first flushes Stdout. This keeps interactive IO predictable while allowing some room for buffering console output. |
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Wed Apr 05, 2006 7:07 pm Post subject: |
|
|
Ahh. Right.
That sounds OK. Should the same thing happen with Cout & Cin ? |
|
Back to top |
|
|
sean
Joined: 24 Jun 2004 Posts: 609 Location: Bay Area, CA
|
Posted: Thu Apr 06, 2006 9:09 am Post subject: |
|
|
Probably, though as Cout already flushes after each write I don't think it's critical if the design doesn't fit at that level. |
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Fri Apr 07, 2006 1:44 am Post subject: |
|
|
Well, I was thinking that "hog-tie" should be at the Console level. If that were the case, Stdin & Stdout would comply automatically. As would Print. Of course, this means changing the current behaviour of Console a little ~ probably worthwhile?
- Kris |
|
Back to top |
|
|
sean
Joined: 24 Jun 2004 Posts: 609 Location: Bay Area, CA
|
Posted: Fri Apr 07, 2006 3:32 pm Post subject: |
|
|
Probably. If this occurs at the console level will it work for other stream types as well? It might be of limited use for socket streams or even file streams with the "all devices are files" aspect of Unix. |
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Fri Apr 07, 2006 6:51 pm Post subject: |
|
|
sean wrote: | Probably. If this occurs at the console level will it work for other stream types as well? It might be of limited use for socket streams or even file streams with the "all devices are files" aspect of Unix. |
I had imagined limiting it to mango.io.Console, but it may well be applicable elsewhere. I'll give that some thought over the weekend. Thanks! |
|
Back to top |
|
|
|