all OS functions should be "nothrow @trusted @nogc"

Shachar Shemesh via Digitalmars-d digitalmars-d at puremagic.com
Tue Jul 25 23:44:51 PDT 2017


On 25/07/17 18:29, Moritz Maxeiner wrote:
> On Tuesday, 25 July 2017 at 14:39:15 UTC, Shachar Shemesh wrote:
>> On 25/07/17 17:24, Moritz Maxeiner wrote:
>>> On Tuesday, 25 July 2017 at 13:50:16 UTC, Shachar Shemesh wrote:
>>>> The title really does says it all.
>>>
>>> Since you explicitly state *all* OS functions:
>>> nothrow: Should be OK (only callbacks could violate this and they 
>>> should be nothrow, anyway).
>> Technically, any system call that is a pthreads cancellation point may 
>> throw a C++ exception.
> 
> Good to know, then since D is supposed to be able to catch C++ 
> exceptions (and can on 64bit Linux [1]) none of those may be attributed 
> as `nothrow`, because C++ exceptions don't derive from `Error` >
>>
>> If we go down that route, however, calling system calls from nothrow 
>> becomes completely impossible, which is another way of saying that 
>> decorating just about anything with nothrow becomes impossible.
> 
> No. `nothrow` functions can call throwing ones, as long as they catch 
> any exceptions not derived from Error thrown by them.
> 

And right there and then you've introduced a serious problem. The 
purpose of the C++ exception thrown on cancellation point is to 
terminate the thread. It is designed to be uncatchable.

Had that been D, it might derive from Error, or even directly from 
Throwable. This is C++, however. It some weirdly named class.

I think labeling these "nothrow" is the correct course of action.

>> The decoration's situation with callbacks is pretty horrible 
>> throughout D.
> 
> Do you mean throughout druntime and phobos?

I'm rechecking what I mean. I may have misspoke.

> 
>> I'm not sure this is the most compelling argument, however. The 
>> function passed to pthread_create does not, logically, run in the 
>> pthread_create function. As such, I don't think this logic holds.
> 
> Then the @nogc definition would need to be updated from: "or indirectly 
> through functions it may call" to reflect this, because that can be 
> interpreted both ways.
> 
>>
>> As for pthread_join, I have no idea what you meant by it. Please 
>> elaborate why you think it is a problem.
> 
> Possible scenario on single core (no hyperthreading) system:
> - thread 1 spawns thread 2
> - thread 1 enters @nogc function `foo` and calls `pthread_join` on 
> thread 2 before its own timeslice is over (and thus enters blocked state)
> - thread 2 does work allocating via the GC, then terminates
> - thread 1 wakes up and leaves @nogc function `foo`
> 
> Because @nogc (in contrast to nothrow) is explicitly designed as 
> transitive, logically speaking, `foo` violated its @nogc constraint (it 
> *caused* the GC allocations in thread 2).

Following that logic, ANY function that might affect another thread 
cannot be @nogc. I think this way madness lies. I don't think other 
threads action, even if linked in some weird semantic way to ours, make 
us accountable to their actions.

If you pass a callback that is not @nogc to pthread_create, then your 
other thread might allocate. This doesn't change the fact that 
pthread_create doesn't allocate.

At Weka, we use this understanding of the semantics all the time. Our 
main thread is as @nogc as we can possibly make it. Whenever we need 
anything that violates our usual restrictions, we send it either to 
other threads or other processes for execution, and use the results when 
they return. Defining the various attributes too strictly will simply 
mean we cannot use them anywhere (which is pretty much what happens 
today, but the very thing I'm trying to change here).

Shachar


More information about the Digitalmars-d mailing list