June 03, 2020
On Wednesday, 3 June 2020 at 20:05:39 UTC, Walter Bright wrote:
> On 6/3/2020 7:58 AM, Stanislav Blinov wrote:
>> A good `writeln` would not call into C  at all.
>
> C's puts() is thread safe. No reason to not use it.
>
>
>> So it's OK, we're only missing a plain `writeln`.
>
> Doing the basic, common cases by going around the horn is not good engineering.

Superfluous special cases and premature optimization is not good software engineering either.
June 03, 2020
On 6/3/20 3:59 PM, Walter Bright wrote:
> On 6/3/2020 1:06 AM, Nick Treleaven wrote:
>> How does writeln tell that a zero terminated string has been passed?
> 
> D string literals always have a 0 terminator.

All compile-time strings should be both 0 terminated and implicitly convertible to immutable(char)*. I think there are some cases that aren't, but I don't remember all of them.

But the question above is still unanswered -- writeln receives a string as an immutable(char)[], and doesn't know that it's from a literal.

For example, if writeln blindly assumed that all immutable(char)[] were string literals, that it could pass to puts, this would be a problem:

writeln(somestr.idup);

-Steve
June 03, 2020
On Wednesday, 3 June 2020 at 19:59:31 UTC, Walter Bright wrote:
> On 6/3/2020 1:06 AM, Nick Treleaven wrote:
>> How does writeln tell that a zero terminated string has been passed?
>
> D string literals always have a 0 terminator.

Indeed, but the type system cannot distinguish literals from other strings.

That is, from writeln's perspective:

writeln("hello");

and

writeln("hello world"[0 .. 5]);

are indistinguishable, yet the latter is not zero terminated.

That's why writeln cannot just blindly forward to puts. It may be able to forward to fwrite() though... which is very close to what it actually does, it just checks some edge cases along the way which has a tiny cost in this case but buys us capabilities in other cases.
June 03, 2020
On 6/3/20 4:29 PM, Stanislav Blinov wrote:
> On Wednesday, 3 June 2020 at 20:05:39 UTC, Walter Bright wrote:
>> On 6/3/2020 7:58 AM, Stanislav Blinov wrote:
>>> A good `writeln` would not call into C  at all.
>>
>> C's puts() is thread safe. No reason to not use it.
> 
> A thread-safe writeln would be threadsafe_writeln. Or, alternatively there would be a writeln and a not_threadsafe_writeln. No reason to pay for something you're not using. And still neither implementation would call into C, the OS is right there.

writeln writes to a FILE *, which is C. There's no way around it. FILE * is buffered i/o, so going around it would mean odd out-of-order output.

-Steve
June 03, 2020
On Wednesday, 3 June 2020 at 21:04:23 UTC, Steven Schveighoffer wrote:

>> A thread-safe writeln would be threadsafe_writeln. Or, alternatively there would be a writeln and a not_threadsafe_writeln. No reason to pay for something you're not using. And still neither implementation would call into C, the OS is right there.
>
> writeln writes to a FILE *, which is C. There's no way around it. FILE * is buffered i/o, so going around it would mean odd out-of-order output.

There's no way around writing to a FILE*? I... hope you didn't mean what you wrote, all things considered ;)

I know what Phobos' writeln does. But whatever, this is not the topic. Maybe in another thread at another time...
June 03, 2020
On 6/3/20 5:29 PM, Stanislav Blinov wrote:
> On Wednesday, 3 June 2020 at 21:04:23 UTC, Steven Schveighoffer wrote:
> 
>>> A thread-safe writeln would be threadsafe_writeln. Or, alternatively there would be a writeln and a not_threadsafe_writeln. No reason to pay for something you're not using. And still neither implementation would call into C, the OS is right there.
>>
>> writeln writes to a FILE *, which is C. There's no way around it. FILE * is buffered i/o, so going around it would mean odd out-of-order output.
> 
> There's no way around writing to a FILE*? I... hope you didn't mean what you wrote, all things considered ;)

Well, no way around it if you want writeln to do expected things ;)

Unless you are suggesting that Phobos completely drop support for interleaving printf and writeln calls? If you are, I assure you Walter will not accept that.

> I know what Phobos' writeln does. But whatever, this is not the topic. Maybe in another thread at another time...

Not sure why you think the implementation of Phobos using C for I/O is not on-topic. It was you who suggested we could avoid it for certain calls to writeln.

-Steve
June 04, 2020
On Wednesday, 3 June 2020 at 22:21:41 UTC, Steven Schveighoffer wrote:
> On 6/3/20 5:29 PM, Stanislav Blinov wrote:

>> There's no way around writing to a FILE*? I... hope you didn't mean what you wrote, all things considered ;)
>
> Well, no way around it if you want writeln to do expected things ;)
>
> Unless you are suggesting that Phobos completely drop support for interleaving printf and writeln calls? If you are, I assure you Walter will not accept that.

Phobos can have whatever it has. That wasn't my point.

> Not sure why you think the implementation of Phobos using C for I/O is not on-topic. It was you who suggested we could avoid it for certain calls to writeln.

Because topic is template bloat, err... statistics :) And I'm well at fault for straying.
I was speaking figuratively. A *good* writeln need not go to C - that was my retort to bringing up puts in 2020. Not *the* writeln, *a* writeln. At the very least it shouldn't be the default. My point is we should be striving for better, not that there's anything wrong with puts or C.
June 03, 2020
On 6/3/2020 3:21 PM, Steven Schveighoffer wrote:
> Unless you are suggesting that Phobos completely drop support for interleaving printf and writeln calls? If you are, I assure you Walter will not accept that.

I just checked with him, and he assured me he won't.

Also, a plain writeln("hello") must be thread safe just like puts("hello"). The reason is simply customer demand. I recall the bad old days when multiple threads would write to stdout, and you'd get:

  heworllldo

and everyone would complain. People accept that printfs can be interleaved on the function call level, but not inside the call. Furthermore, stdout has to acquire a mutex before writing to it:

    acquire stdout mutex
    print 'h'
    release stdout mutex
    acquire stdout mutex
    print 'e'
    release stdout mutex
    acquire stdout mutex
    print 'l'
    release stdout mutex

turns out to be disastrously slower than:

    acquire stdout mutex
    print 'hello'
    release stdout mutex
June 03, 2020
On 6/3/20 9:27 PM, Stanislav Blinov wrote:
> On Wednesday, 3 June 2020 at 22:21:41 UTC, Steven Schveighoffer wrote:
>> On 6/3/20 5:29 PM, Stanislav Blinov wrote:
> 
>>> There's no way around writing to a FILE*? I... hope you didn't mean what you wrote, all things considered ;)
>>
>> Well, no way around it if you want writeln to do expected things ;)
>>
>> Unless you are suggesting that Phobos completely drop support for interleaving printf and writeln calls? If you are, I assure you Walter will not accept that.
> 
> Phobos can have whatever it has. That wasn't my point.

Ah, I get it, sorry for misunderstanding of your point. Yes, I'm in the same boat. I've hated how Phobos uses FILE * for its I/O.

> 
>> Not sure why you think the implementation of Phobos using C for I/O is not on-topic. It was you who suggested we could avoid it for certain calls to writeln.
> 
> Because topic is template bloat, err... statistics :) And I'm well at fault for straying.
> I was speaking figuratively. A *good* writeln need not go to C - that was my retort to bringing up puts in 2020. Not *the* writeln, *a* writeln. At the very least it shouldn't be the default. My point is we should be striving for better, not that there's anything wrong with puts or C.

Agree on all that, sorry for the confusion.

-Steve
June 04, 2020
On Thursday, 4 June 2020 at 01:38:50 UTC, Walter Bright wrote:
> Furthermore, stdout has to acquire a mutex before writing to it:

No need for any of this on the OS level, a write up to like 4k is guaranteed to be atomic.

It is the C buffer that isn't :(

And the C buffer is a consistent source of pain for user-interactive i/o. Buffering makes a big performance difference when you are actually outputting a block... but with user-interactive you rarely actually *want* buffering since users want to see their results ASAP! And remember, pipes are frequently user-interactive too and them not being flushed frequently is a FAQ among new users, especially IDE users.

I kinda feel buffering should not be done across function boundaries for stdout and stderr. Other files maybe.