September 01, 2012
http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP18

The proposal is to create a base for safe, non garbage-collected threads. This is done by adding nogc attribute for functions. nogc functions cannot perform operations that may allocate garbage collected memory. They are covariant with gc ones.

Any comments are welcome.
September 01, 2012
Piotr Szturmaj:

> This is done by adding nogc attribute for functions. nogc functions cannot perform operations that may allocate garbage collected memory.

I suggest to call that @nogc.

Time ago I have suggested a "@noheap" attribute for functions, that is similar to that "nogc", see the discussion there:
http://d.puremagic.com/issues/show_bug.cgi?id=5219

The difference is that @noheap disallows C functions like C malloc(), etc. Stack allocation like alloca() and variable length arrays is allowed in @noheap functions.

@noheap/@nogc is probably inferred for templated functions, as pure/nothrow.

The main disadvantage of an annotation like this is the proliferation of kinds of functions. The advantage is a more precise control of the effects of functions.

The Koka language has a function annotation similar to @noheap, I have discussed a little about Koka here:
http://forum.dlang.org/thread/ocxmiolhlcysehbjtcop@forum.dlang.org
but Koka has type inference for effects, so often you don't need to add that annotation to functions.

Bye,
bearophile
September 01, 2012
One more comment, a quotation from the DIP18:

>Currently, all functions can use garbage collected memory. Threads that call those functions must be managed by the garbage collector, which may occasionally suspend them to perform collection. This can lead to unwanted pauses, that are not acceptable in some situations, mainly real-time audio/video processing, gaming, and others.<

C heap functions like malloc(), calloc(), realloc() have the same problem, their run-time is not deterministic, so if you don't want pauses a @noheap is useful.

@noheap is not meant to forbid calling low-level system-specific memory allocation functions.

Bye,
bearophile
September 01, 2012
> If some of the function's arguments take references (directly or indirectly), then all of them are automatically added to the list of GC roots (addRoot()).

You still have a problem: you might have added an object passed as an argument to the GC roots, preventing the GC from collecting it, but if any thread is allowed to mutate a pointer inside this object pointing to some other data, using this other data in your thread is not safe, unless you have added a root for this other pointer too. You'd have to recursively add roots for this to work.

There's also the same issue with global variables, the ones which are pointers to other pointers.

-- 
Michel Fortin
michel.fortin@michelf.ca
http://michelf.ca/

September 01, 2012
I think this is an unnecessary addition.

I use D for game dev, and I avoid the GC + malloc like the plague, however I don't want to have to litter my code with distractions like nogc, @noheap or whatever keyword we choose.

It's easy enough to avoid these without expanding the type system. I add trace statements to the GC in druntime, and just avoid calling malloc. I think this is a more practical solution to this problem than extending the language and cluttering my code.
September 01, 2012
Peter Alexander wrote:
> I think this is an unnecessary addition.
>
> I use D for game dev, and I avoid the GC + malloc like the plague,
> however I don't want to have to litter my code with distractions like
> nogc, @noheap or whatever keyword we choose.
>
> It's easy enough to avoid these without expanding the type system. I add
> trace statements to the GC in druntime, and just avoid calling malloc. I
> think this is a more practical solution to this problem than extending
> the language and cluttering my code.

It's similar behavior to nothrow and pure. Instead of manually avoiding GC allocations, compiler does this checks for you. Imagine D doesn't have nothrow. You'd have to check every called function to see if it doesn't throw. In big programs throwing function may be left unnoticed and this is why we have static nothrow checks in D.
September 01, 2012
bearophile wrote:
> Piotr Szturmaj:
>
>> This is done by adding nogc attribute for functions. nogc functions
>> cannot perform operations that may allocate garbage collected memory.
>
> I suggest to call that @nogc.
>
> Time ago I have suggested a "@noheap" attribute for functions, that is
> similar to that "nogc", see the discussion there:
> http://d.puremagic.com/issues/show_bug.cgi?id=5219

Thanks, I didn't know that. There are some good arguments for @nogc.

> The difference is that @noheap disallows C functions like C malloc(),
> etc. Stack allocation like alloca() and variable length arrays is
> allowed in @noheap functions.
>
> @noheap/@nogc is probably inferred for templated functions, as
> pure/nothrow.

I would prefer @nogc, because nogc functions can manually allocate. Not using malloc, or preallocating using it is a lot easier than checking for GC allocations and manually managing non-gc threads.

The main reason under @nogc is not non-deterministic allocation of GC or malloc. The whole idea is to guarantee that nogc threads are not suspended by the GC.

> The main disadvantage of an annotation like this is the proliferation of
> kinds of functions. The advantage is a more precise control of the
> effects of functions.

The advantage is that you'd get the static checks similar to nothrow and pure.

> The Koka language has a function annotation similar to @noheap, I have
> discussed a little about Koka here:
> http://forum.dlang.org/thread/ocxmiolhlcysehbjtcop@forum.dlang.org
> but Koka has type inference for effects, so often you don't need to add
> that annotation to functions.

Well, __traits(hasGCallocations, func) will also do the trick.
September 01, 2012
Michel Fortin wrote:
>> If some of the function's arguments take references (directly or
>> indirectly), then all of them are automatically added to the list of
>> GC roots (addRoot()).
>
> You still have a problem: you might have added an object passed as an
> argument to the GC roots, preventing the GC from collecting it, but if
> any thread is allowed to mutate a pointer inside this object pointing to
> some other data, using this other data in your thread is not safe,
> unless you have added a root for this other pointer too. You'd have to
> recursively add roots for this to work.
>
> There's also the same issue with global variables, the ones which are
> pointers to other pointers.

Yes, there is no obvious solution, but I think it could be done. For example non-immutable references may be disallowed at all. The other solution is to copy the whole referenced object using malloc, and add it to the GC roots.
September 01, 2012
On Saturday, 1 September 2012 at 11:37:39 UTC, Piotr Szturmaj wrote:
> It's similar behavior to nothrow and pure. Instead of manually avoiding GC allocations, compiler does this checks for you. Imagine D doesn't have nothrow. You'd have to check every called function to see if it doesn't throw. In big programs throwing function may be left unnoticed and this is why we have static nothrow checks in D.

I understand the benefit. However, there are at least two significant costs:

1. If I want my entire program to be GC free, I have to annotate every single function with 'nogc'. This is not something I want to do.

2. It's a new language feature and has all the associated costs: initial implementation, bug fixing, marking up of functions in Phobos, documentation, etc.

Yes, with my approach, a rare allocation may go unnoticed, and you end up with an undesirable GC collection sometime in the future. It's not great, but it's not the end of the world, and I'm willing to risk that to avoid the costs I mentioned above.
September 01, 2012
On 01-Sep-12 15:47, Piotr Szturmaj wrote:
> bearophile wrote:
>
>> The Koka language has a function annotation similar to @noheap, I have
>> discussed a little about Koka here:
>> http://forum.dlang.org/thread/ocxmiolhlcysehbjtcop@forum.dlang.org
>> but Koka has type inference for effects, so often you don't need to add
>> that annotation to functions.
>
> Well, __traits(hasGCallocations, func) will also do the trick.

Make it __traits(hasAttribute, "nogc", func) and that might be something.
Actually, I'd love to see some proposal that
a) clarifies how @attributes are supposed to be used
b) adds generic infrastructure to to use them via __traits or whatever

-- 
Olshansky Dmitry
« First   ‹ Prev
1 2 3 4
Top | Discussion index | About this forum | D home