April 19, 2014
On Saturday, 19 April 2014 at 17:41:58 UTC, Walter Bright wrote:
> On 4/19/2014 6:14 AM, Dicebot wrote:
>> On Thursday, 17 April 2014 at 22:04:17 UTC, Walter Bright wrote:
>>> On 4/17/2014 1:03 PM, John Colvin wrote:
>>>> E.g. you can implement some complicated function foo that writes to a
>>>> user-provided output range and guarantee that all GC usage is in the control of
>>>> the caller and his output range.
>>>
>>> As mentioned elsewhere here, it's easy enough to do a unit test for this.
>>
>> Erm, no? You can possibly track GC calls by using custom druntime fork but you
>> can't track origins of such calls in source tree without compiler help.
>
> @nogc is there to help.
>
>
>>>> The advantage of having this as language instead of documentation is the
>>>> turtles-all-the-way-down principle: if some function deep inside the call chain
>>>> under foo decides to use a GC buffer then it's a compile-time-error.
>>>
>>> And that's how @nogc works.
>>
>> And it is not good enough for practical reasons, i.e. we won't be able to use
>> @nogc for most of the Phobos.
>
> The first step is to identify the parts of Phobos that unnecessarily use the GC. @nogc will help a lot with this.

I feel like the origin of the discussion has been completely lost here and we don't speak the same language right now. The very point I have made initially is that @nogc in a way it is defined in your DIP is too restrictive to be effectively used in Phobos.

In lot of standard library functions you may actually need to allocate as part of algorithm, strict @nogc is not applicable there. However, it is still extremely useful that no _hidden_ allocations happen outside of weel-defined user API and this is something that less restrictive version of @nogc could help with.

The fact that you propose me to use unit tests to verify same guarantees hints that I have completely failed to explain my proposal but I can't really rephrase it any better without some help from your side to identify the point of confusion.
April 19, 2014
On Saturday, 19 April 2014 at 18:05:48 UTC, Dicebot wrote:
> In lot of standard library functions you may actually need to allocate as part of algorithm, strict @nogc is not applicable there. However, it is still extremely useful that no _hidden_ allocations happen outside of weel-defined user API and this is something that less restrictive version of @nogc could help with.

What you want is to mark some functions with @allow_gc ? So that you only get GC where specified as a "contract"?

But isn't this more suitable for dynamic tracing/logging?

Because what you want is probably the frequency of GC allocations in a particular call tree?
April 19, 2014
On Saturday, 19 April 2014 at 18:12:32 UTC, Ola Fosheim Grøstad wrote:
> On Saturday, 19 April 2014 at 18:05:48 UTC, Dicebot wrote:
>> In lot of standard library functions you may actually need to allocate as part of algorithm, strict @nogc is not applicable there. However, it is still extremely useful that no _hidden_ allocations happen outside of weel-defined user API and this is something that less restrictive version of @nogc could help with.
>
> What you want is to mark some functions with @allow_gc ? So that you only get GC where specified as a "contract"?
>
> But isn't this more suitable for dynamic tracing/logging?
>
> Because what you want is probably the frequency of GC allocations in a particular call tree?

Original proposal, updated and re-worded as formal as possible.

"weak @nogc" functions / methods are identical to normal @nogc function but are allowed to trigger GC via functions / methods directly accessible via its arguments. Such weak @nogc functions can only call strict @nogc functions in any other context.

Exact details get tricky rather quick and this is something that needs thorough examination but rationale behind this is to move all allocation decisions exclusively to caller side. Frequency does not matter here, only the fact that function does not cause allocations of its own.

Again, example of a pattern that should be common in Phobos:

void foo(ref OutputBuffer buffer) @nogc
{
    buffer.put(42); // buffer.put may be not @nogc, this turns foo into "weak @nogc"
    throw new Exception(); // put this is prohibited anyway
    someGCFunction(); // as well as this..
    int[] arr; arr ~= 42; // ..and this
}

User of such functions will be 100% sure that if any allocations happen, he is the one to blame and can tweak it in his own code, possibly using OutputBuffer implementation that does not use GC or allocations at all.
April 19, 2014
On Saturday, 19 April 2014 at 18:05:48 UTC, Dicebot wrote:
> I feel like the origin of the discussion has been completely lost here and we don't speak the same language right now. The very point I have made initially is that @nogc in a way it is defined in your DIP is too restrictive to be effectively used in Phobos.
>
> In lot of standard library functions you may actually need to allocate as part of algorithm, strict @nogc is not applicable there. However, it is still extremely useful that no _hidden_ allocations happen outside of weel-defined user API and this is something that less restrictive version of @nogc could help with.
>
> The fact that you propose me to use unit tests to verify same guarantees hints that I have completely failed to explain my proposal but I can't really rephrase it any better without some help from your side to identify the point of confusion.

I feel what you are asking for is that something that is part of the interface (qualifier), make no actual promises about the function itself, but rather only help you with your implementation? That feels wrong.

I see little value in doing:

void fun(T)(ref T t) @nogc
{
    t.allocateOnGc(); //"This is fine because T does it?"
}

This is what you are asking for? Am I correct?

I also still don't see why @nogc would behave any different from nothrow, pure or @safe.

***THAT SAID***, unless I'm mistaken, wouldn't your requirements be better answered by the "qualified block" proposal? Remember that proposal that (would) have allowed us to do:

void fun() @safe
{
  @trusted { //doesn't create scope.
    T t = someUnsafeFunctionITrust();
  }

    t.doIt(); //doIt must be safe
}

By the same standard, you could use it to enforce no GC. But only in certain areas.

EG:
void fun(T)(ref T t) //inferred
{
    t.allocate(); //I'm fine with this using GC

  @nogc : //But as of this line, I want the compiler to ban the GC altogether
    doThings(); //I can rest assured this won't allocate on the GC.
}

Personally, I still feel this would be a *much* more natural, idiomatic, and more transparent approach to doing things, than the current trusted lambda *crap* we've been doing. And it would indeed help with writing things correctly.
...

...or I misunderstood you, in which case I apologize.
April 19, 2014
On 4/19/2014 10:51 AM, monarch_dodra wrote:
> On Saturday, 19 April 2014 at 17:41:58 UTC, Walter Bright wrote:
>> The first step is to identify the parts of Phobos that unnecessarily use the
>> GC. @nogc will help a lot with this.
>
> Unless I missed it, I think we still haven't answered the issue with throwing
> exceptions. I'm in particular interested in asserts and Errors.

It wouldn't affect asserts.
April 19, 2014
On 4/19/2014 11:05 AM, Dicebot wrote:
> I feel like the origin of the discussion has been completely lost here and we
> don't speak the same language right now. The very point I have made initially is
> that @nogc in a way it is defined in your DIP is too restrictive to be
> effectively used in Phobos.
>
> In lot of standard library functions you may actually need to allocate as part
> of algorithm, strict @nogc is not applicable there. However, it is still
> extremely useful that no _hidden_ allocations happen outside of weel-defined
> user API and this is something that less restrictive version of @nogc could help
> with.
>
> The fact that you propose me to use unit tests to verify same guarantees hints
> that I have completely failed to explain my proposal but I can't really rephrase
> it any better without some help from your side to identify the point of confusion.

The way I understood your idea, was that a template could be marked @nogc, and yet still allow template arguments that themselves may gc.

This can be accomplished by creating a unit test that passes non-allocating template parameters, and then verifying the instantiation is @nogc.

April 19, 2014
I think it would be useful to be able to mark structs as @nogc_alloc or something similar.

Interpretation: this struct and any data directly reachable from it is guaranteed to not be GC allocated. Then a precise collector could avoid scanning those and pointers to them.

Even with @nogc threads for audio/visual real time computations the GC itself will have to get down to consistent < 50-200ms freezes to get fluid interaction for content computations.

April 19, 2014
Am Wed, 16 Apr 2014 20:32:20 +0000
schrieb "Peter Alexander" <peter.alexander.au@gmail.com>:

> On Wednesday, 16 April 2014 at 20:29:17 UTC, bearophile wrote:
> > Peter Alexander:
> >
> >> (I assume that nothrow isn't meant to be there?)
> >
> > In D nothrow functions can throw errors.
> 
> Of course, ignore me :-)
> 
> 
> >> You could do something like this:
> >>
> >> void foo() @nogc
> >> {
> >>    static err = new Error();
> >>    if (badthing)
> >>    {
> >>        err.setError("badthing happened");
> >>        throw err;
> >>    }
> >> }
> >
> > To be mutable err also needs to be __gshared.
> 
> But then it isn't thread safe. Two threads trying to set and throw the same Error is a recipe for disaster.

Also: As far as I remember from disassembling C++, static variables in functions are initialized on first access and guarded by a bool. The first call to foo() would execute "err = new Error();" in that case. This code should not compile under @nogc.

-- 
Marco

April 20, 2014
On 20 April 2014 06:56, via Digitalmars-d <digitalmars-d@puremagic.com>wrote:

> I think it would be useful to be able to mark structs as @nogc_alloc or something similar.
>
> Interpretation: this struct and any data directly reachable from it is guaranteed to not be GC allocated. Then a precise collector could avoid scanning those and pointers to them.
>

Why wouldn't precise GC be able to do this anyway? It already has data about everything it scans. It can easily produce a 'don't bother scanning this' bit at the start of that data without programmer assistance?


Even with @nogc threads for audio/visual real time computations the GC
> itself will have to get down to consistent < 50-200ms freezes to get fluid interaction for content computations.
>

50ms is 3 whole frames, 200ms is 12.5 frames! I thought you were a realtime
programmer?
In a visual realtime app, the GC will only be acceptable when it will not
interrupt for more than 1ms or so (and I consider that quite generous, I'd
be more comfortable with < 500µs). Otherwise you'll lose frames anyway; if
your entire world exists within 16ms slices, how can you budget the frame's
usual workload around the GC interruption?
And what if the GC interrupts more than once per frame? What if you have
very little free memory?


April 20, 2014
On Sunday, 20 April 2014 at 00:59:26 UTC, Manu via Digitalmars-d wrote:
>> Interpretation: this struct and any data directly reachable from it is
>> guaranteed to not be GC allocated. Then a precise collector could avoid
>> scanning those and pointers to them.
>
> Why wouldn't precise GC be able to do this anyway? It already has data
> about everything it scans. It can easily produce a 'don't bother scanning
> this' bit at the start of that data without programmer assistance?

It doesn't know what can be reached through a node in a graph. It doesn't know what is on the GC heap.

> In a visual realtime app, the GC will only be acceptable when it will not
> interrupt for more than 1ms or so (and I consider that quite generous, I'd
> be more comfortable with < 500µs). Otherwise you'll lose frames anyway; if

No, because the @nogc thread will not be interrupted.

Think MVC: the model is under GC, the view/controller is under @nogc.