www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - pure and custom new / delete

reply Benjamin Thaut <code benjamin-thaut.de> writes:
As delete and new / delete overloading is deprecated and it was 
recommeneded to write tempaltes to repalce these expressions I did so.

But now as everything starts to work out pretty nice I've walked into 
the 'purity' issue. Pure functions are only allowed to call other pure 
functions and as far as I know there is no way to make functions 
"trusted pure". But I would need to make certain functions "trused 
pure", espeically my new and delete replacements. Any suggestions how to 
do this?

Kind Regards
Benjamin Thaut
Jun 26 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06/26/2012 05:59 PM, Benjamin Thaut wrote:
 As delete and new / delete overloading is deprecated and it was
 recommeneded to write tempaltes to repalce these expressions I did so.

 But now as everything starts to work out pretty nice I've walked into
 the 'purity' issue. Pure functions are only allowed to call other pure
 functions and as far as I know there is no way to make functions
 "trusted pure". But I would need to make certain functions "trused
 pure", espeically my new and delete replacements. Any suggestions how to
 do this?

 Kind Regards
 Benjamin Thaut
You can cast function pointers to pure, or mark extern(C) memory allocation functions as pure.
Jun 26 2012
parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 26.06.2012 18:02, schrieb Timon Gehr:
 On 06/26/2012 05:59 PM, Benjamin Thaut wrote:
 As delete and new / delete overloading is deprecated and it was
 recommeneded to write tempaltes to repalce these expressions I did so.

 But now as everything starts to work out pretty nice I've walked into
 the 'purity' issue. Pure functions are only allowed to call other pure
 functions and as far as I know there is no way to make functions
 "trusted pure". But I would need to make certain functions "trused
 pure", espeically my new and delete replacements. Any suggestions how to
 do this?

 Kind Regards
 Benjamin Thaut
You can cast function pointers to pure, or mark extern(C) memory allocation functions as pure.
extern(c) is not an options as there is a structure of various different allocators that implement a common interface which all is written in D. Is the compiler smart enough to optimize away a function pointer I created localy just so I can cast it? Kind Regards Benjamin Thaut
Jun 26 2012
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06/26/2012 06:05 PM, Benjamin Thaut wrote:
 Am 26.06.2012 18:02, schrieb Timon Gehr:
 On 06/26/2012 05:59 PM, Benjamin Thaut wrote:
 As delete and new / delete overloading is deprecated and it was
 recommeneded to write tempaltes to repalce these expressions I did so.

 But now as everything starts to work out pretty nice I've walked into
 the 'purity' issue. Pure functions are only allowed to call other pure
 functions and as far as I know there is no way to make functions
 "trusted pure". But I would need to make certain functions "trused
 pure", espeically my new and delete replacements. Any suggestions how to
 do this?

 Kind Regards
 Benjamin Thaut
You can cast function pointers to pure, or mark extern(C) memory allocation functions as pure.
extern(c) is not an options as there is a structure of various different allocators that implement a common interface which all is written in D. Is the compiler smart enough to optimize away a function pointer I created localy just so I can cast it? Kind Regards Benjamin Thaut
You can examine the assembly code. DMD is perhaps not smart enough (it is unable to inline directly called function literals, so I am not optimistic.) LDC and GDC should certainly optimize it out.
Jun 26 2012
parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 26.06.2012 18:44, schrieb Timon Gehr:
 On 06/26/2012 06:05 PM, Benjamin Thaut wrote:
 Am 26.06.2012 18:02, schrieb Timon Gehr:
 On 06/26/2012 05:59 PM, Benjamin Thaut wrote:
 As delete and new / delete overloading is deprecated and it was
 recommeneded to write tempaltes to repalce these expressions I did so.

 But now as everything starts to work out pretty nice I've walked into
 the 'purity' issue. Pure functions are only allowed to call other pure
 functions and as far as I know there is no way to make functions
 "trusted pure". But I would need to make certain functions "trused
 pure", espeically my new and delete replacements. Any suggestions
 how to
 do this?

 Kind Regards
 Benjamin Thaut
You can cast function pointers to pure, or mark extern(C) memory allocation functions as pure.
extern(c) is not an options as there is a structure of various different allocators that implement a common interface which all is written in D. Is the compiler smart enough to optimize away a function pointer I created localy just so I can cast it? Kind Regards Benjamin Thaut
You can examine the assembly code. DMD is perhaps not smart enough (it is unable to inline directly called function literals, so I am not optimistic.) LDC and GDC should certainly optimize it out.
The more I get into this, the more I get the feeling that all this "D can be used without a GC" is just a marketing trick to get C++ guys to use D. I really like D because of a lot of nice features it has, but at the current rate I fear that the day I go back to c++ will come.
Jun 26 2012
parent reply "David Nadlinger" <see klickverbot.at> writes:
On Tuesday, 26 June 2012 at 16:52:48 UTC, Benjamin Thaut wrote:
 Am 26.06.2012 18:44, schrieb Timon Gehr:
 On 06/26/2012 06:05 PM, Benjamin Thaut wrote:
 Is the compiler smart enough to optimize away a function 
 pointer I
 created localy just so I can cast it?
 […]
You can examine the assembly code. DMD is perhaps not smart enough (it is unable to inline directly called function literals, so I am not optimistic.) LDC and GDC should certainly optimize it out.
The more I get into this, the more I get the feeling that all this "D can be used without a GC" is just a marketing trick to get C++ guys to use D.
This has nothing to do with the GC, just with the compiler turning an indirect jump to a statically known address into a direct one. Every decent compiler should optimize it away, and even if it doesn't, it still won't kill you in 99.9% of the use cases. David
Jun 26 2012
parent Benjamin Thaut <code benjamin-thaut.de> writes:
Am 26.06.2012 19:23, schrieb David Nadlinger:
 On Tuesday, 26 June 2012 at 16:52:48 UTC, Benjamin Thaut wrote:
 Am 26.06.2012 18:44, schrieb Timon Gehr:
 On 06/26/2012 06:05 PM, Benjamin Thaut wrote:
 Is the compiler smart enough to optimize away a function pointer I
 created localy just so I can cast it?
 […]
You can examine the assembly code. DMD is perhaps not smart enough (it is unable to inline directly called function literals, so I am not optimistic.) LDC and GDC should certainly optimize it out.
The more I get into this, the more I get the feeling that all this "D can be used without a GC" is just a marketing trick to get C++ guys to use D.
This has nothing to do with the GC, just with the compiler turning an indirect jump to a statically known address into a direct one. Every decent compiler should optimize it away, and even if it doesn't, it still won't kill you in 99.9% of the use cases. David
I'm not talking about the optimization here. I'm talking about not beeing able to do a propper replacement for new / delete with the features the language currently has.
Jun 26 2012
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 26 Jun 2012 12:05:55 -0400, Benjamin Thaut  
<code benjamin-thaut.de> wrote:

 Am 26.06.2012 18:02, schrieb Timon Gehr:
 You can cast function pointers to pure, or mark extern(C) memory
 allocation functions as pure.
extern(c) is not an options as there is a structure of various different allocators that implement a common interface which all is written in D.
extern(C) does not mean implemented in C, it just means C linkage. You can use arrays, classes, etc. in extern(C) functions. UFCS makes this really easy too: myalloc.d: interface Allocator { void * _alloc(size_t size); } extern(C) void *alloc(Allocator a, size_t size) pure; allocimpl.d: import myalloc; extern(C) void *alloc(Allocator a) // pure { return a._alloc(size) } mallocer.d: public import myalloc; import std.c.stdlib; // sample allocator class Mallocer : Allocator { void *_alloc(size_t size) { return malloc(size);} } main.d: import mallocer; void foo(Allocator a) pure { a.alloc(200); //a._alloc(200); // fails as expected } void main() { foo(new Mallocer); } -Steve
Jun 26 2012
parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 26.06.2012 19:19, schrieb Steven Schveighoffer:
 On Tue, 26 Jun 2012 12:05:55 -0400, Benjamin Thaut
 <code benjamin-thaut.de> wrote:

 Am 26.06.2012 18:02, schrieb Timon Gehr:
 You can cast function pointers to pure, or mark extern(C) memory
 allocation functions as pure.
extern(c) is not an options as there is a structure of various different allocators that implement a common interface which all is written in D.
extern(C) does not mean implemented in C, it just means C linkage. You can use arrays, classes, etc. in extern(C) functions. UFCS makes this really easy too: myalloc.d: interface Allocator { void * _alloc(size_t size); } extern(C) void *alloc(Allocator a, size_t size) pure; allocimpl.d: import myalloc; extern(C) void *alloc(Allocator a) // pure { return a._alloc(size) } mallocer.d: public import myalloc; import std.c.stdlib; // sample allocator class Mallocer : Allocator { void *_alloc(size_t size) { return malloc(size);} } main.d: import mallocer; void foo(Allocator a) pure { a.alloc(200); //a._alloc(200); // fails as expected } void main() { foo(new Mallocer); } -Steve
Thanks this works, but it seems to be a very ugly hack just to work around the type system. Also I have templated allocator functions I can not use this trick on. This is going to be a lot of work to get done properly, so I just ignore pure for now I think.
Jun 26 2012
next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, June 26, 2012 20:08:14 Benjamin Thaut wrote:
 Thanks this works, but it seems to be a very ugly hack just to work
 around the type system. Also I have templated allocator functions I can
 not use this trick on. This is going to be a lot of work to get done
 properly, so I just ignore pure for now I think.
Note that since telling the compiler something is pure when it doesn't think so _is_ forcing the type system, it's not entirely unreasonable that it not be super-easy to do. However, it would definitely be nice if it were a lot easier than it is. You could try std.traits.SetFunctionAttributes (it was recently added and is not in 2.59 IIRC). David Nadlinger created it specifically for being able to create easily add function attributes such as pure to a function. I haven't messed around with it yet, but it looks very easy to use. - Jonathan M Davis
Jun 26 2012
parent "David Nadlinger" <see klickverbot.at> writes:
On Tuesday, 26 June 2012 at 18:35:31 UTC, Jonathan M Davis wrote:
 You could try std.traits.SetFunctionAttributes (it was recently 
 added and is
 not in 2.59 IIRC). David Nadlinger created it specifically for 
 being able to
 create easily add function attributes such as pure to a 
 function. I haven't
 messed around with it yet, but it looks very easy to use.
I created it specifically for a related use case, but on its own, SetFunctionAttributes is strictly for manipulating function/delegate _types_ in terms of linkage. This is helpful because the D grammar for function types is quite clumsy. For example, the following is not valid D code, and can't trivially be corrected (in the first case, creating a separate alias for the function type would work, but that's clumsy especially in generic and/or generated code): --- void foo(extern(C) void function() nothrow cb); auto assumePure(T)(T t) { return cast(pure T)(t); } --- As mentioned in https://github.com/D-Programming-Language/phobos/pull/555, it would be easy to add »high-level primitives« on top of SetFunctionAttributes; assumePure and ExternC templates are included as examples its the documentation. Specifically for declaring »trusted pure« functions, making »alias assumePure!funcImpl func;« work would not be hard either. I just was not sure which of those tools are needed frequently enough to warrant inclusion in Phobos, if any. David
Jun 26 2012
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 26 Jun 2012 14:08:14 -0400, Benjamin Thaut  
<code benjamin-thaut.de> wrote:


 Thanks this works, but it seems to be a very ugly hack just to work  
 around the type system. Also I have templated allocator functions I can  
 not use this trick on. This is going to be a lot of work to get done  
 properly, so I just ignore pure for now I think.
Um... yeah :) If you are working around the type system, it *should* be ugly! Note that you should be *extremely* careful of saying something is pure when it is not typechecked by the compiler. If I were designing such an allocator system, I'd separate out pure and impure allocators into two separate hierarchies, and let the person implementing the actual underlying allocator jump the fence between pure and impure. For example, in the code I gave, really only C malloc should be forced-pure, everything else should be typechecked as pure by the compiler. But you were asking for a specific solution. -Steve
Jun 26 2012
parent "David Nadlinger" <see klickverbot.at> writes:
On Tuesday, 26 June 2012 at 19:48:26 UTC, Steven Schveighoffer 
wrote:
 Note that you should be *extremely* careful of saying something 
 is pure when it is not typechecked by the compiler.
I can only second that – especially because depending on what the signature of the function is, the compiler might optimize out calls to them. David
Jun 26 2012