October 21, 2013
On 10/20/2013 10:59 PM, Agustin wrote:

> That didn't work, but after reading how emplace works, i had to make
> some changes.
>
>      public T allocate(T : Object, A...)(auto ref A arguments) {
>          auto pMemory = rawAllocate(__traits(classInstanceSize, T),
> T.alignof);

Does rawAllocate still return void*? For classes, emplace requires (or at least "also accepts" a slice).

Your code will be simpler if rawAllocate returned a slice:

import std.conv;

void[] rawAllocate(size_t, size_t)
{
    static ubyte[1000] buffer;
    return buffer;
}

T allocate(T : Object, A...)(auto ref A arguments) {
    auto pMemory = rawAllocate(__traits(classInstanceSize, T), T.alignof);

    return emplace!T(pMemory, arguments);
}

class C
{
    this(int i, double d)
    {}
}

void main()
{
    auto c = allocate!C(42, 1.5);
}

If it has to return void*, you can make a slice from a plain pointer with the following syntax:

void * rawAllocate(size_t, size_t)
{
    static ubyte[1000] buffer;
    return buffer.ptr;
}

import std.stdio;

void main()
{
    enum requiredLength = 42;
    auto rawPtr = rawAllocate(requiredLength, 16);
    auto slice = rawPtr[0..requiredLength];  // <-- slice from plain pointer
    writeln(slice);
}

Ali

October 21, 2013
Am 21.10.2013 04:17, schrieb Adam D. Ruppe:
> On Monday, 21 October 2013 at 02:06:02 UTC, Agustin wrote:
>> I'm implementing some custom memory allocator, is possible to call an
>> object destructor directly?
>
>
> destroy(object);
>
> destroy is in the automatically imported object.dm so you don't have to
> import anything,
>
> The source code is in dmd2/src/druntime/src/object_.d, there's a few
> overloads if you are curious how it is implemented. Short answer is
> there's a pointer to the destructor in the TypeInfo and destroy calls it.

Using destroy will zero the entire memory block after destroying the object. If you are freeing the memory right after destroying this is going to cost you performance.

To avoid this declare:

extern (C) void rt_finalize2(void* p, bool det = true, bool resetMemory = true);

and then call

rt_finalize(cast(void*)object, false, false);

Also if you want to give a nice error message in case you are calling a construcor that does not exist you should take a look at my AllocatorNew function:

https://github.com/Ingrater/druntime/blob/merge64/src/core/allocator.d#L616

Doing it the way emplace does will just result in a error message

"Dont know how to initialize a object of type YourObject"

With some meta programming you can get error messages like:

"Dont know how to initialize a object of type YourObject
Available constructors:
this(int, int)
this(float)
this(void*)"

Kind Regards
Benjamin Thaut
October 21, 2013
On Monday, 21 October 2013 at 11:48:11 UTC, Benjamin Thaut wrote:
> Using destroy will zero the entire memory block after destroying the object. If you are freeing the memory right after destroying this is going to cost you performance.
>
> To avoid this declare:
>
> extern (C) void rt_finalize2(void* p, bool det = true, bool resetMemory = true);

It is probably a good idea to use malloc/free for deterministic allocators anyway as GC is not really supposed to be used that way by design.
October 21, 2013
On Monday, 21 October 2013 at 07:31:30 UTC, Ali Çehreli wrote:
> On 10/20/2013 10:59 PM, Agustin wrote:
>
> > That didn't work, but after reading how emplace works, i had
> to make
> > some changes.
> >
> >      public T allocate(T : Object, A...)(auto ref A
> arguments) {
> >          auto pMemory =
> rawAllocate(__traits(classInstanceSize, T),
> > T.alignof);
>
> Does rawAllocate still return void*? For classes, emplace requires (or at least "also accepts" a slice).
>
> Your code will be simpler if rawAllocate returned a slice:
>
> import std.conv;
>
> void[] rawAllocate(size_t, size_t)
> {
>     static ubyte[1000] buffer;
>     return buffer;
> }
>
> T allocate(T : Object, A...)(auto ref A arguments) {
>     auto pMemory = rawAllocate(__traits(classInstanceSize, T), T.alignof);
>
>     return emplace!T(pMemory, arguments);
> }
>
> class C
> {
>     this(int i, double d)
>     {}
> }
>
> void main()
> {
>     auto c = allocate!C(42, 1.5);
> }
>
> If it has to return void*, you can make a slice from a plain pointer with the following syntax:
>
> void * rawAllocate(size_t, size_t)
> {
>     static ubyte[1000] buffer;
>     return buffer.ptr;
> }
>
> import std.stdio;
>
> void main()
> {
>     enum requiredLength = 42;
>     auto rawPtr = rawAllocate(requiredLength, 16);
>     auto slice = rawPtr[0..requiredLength];  // <-- slice from plain pointer
>     writeln(slice);
> }
>
> Ali

Thanks!, i didn't knew i could do that, void[] sounds like an array of nothing :P.

On Monday, 21 October 2013 at 11:48:11 UTC, Benjamin Thaut wrote:
> Am 21.10.2013 04:17, schrieb Adam D. Ruppe:
>> On Monday, 21 October 2013 at 02:06:02 UTC, Agustin wrote:
>>> I'm implementing some custom memory allocator, is possible to call an
>>> object destructor directly?
>>
>>
>> destroy(object);
>>
>> destroy is in the automatically imported object.dm so you don't have to
>> import anything,
>>
>> The source code is in dmd2/src/druntime/src/object_.d, there's a few
>> overloads if you are curious how it is implemented. Short answer is
>> there's a pointer to the destructor in the TypeInfo and destroy calls it.
>
> Using destroy will zero the entire memory block after destroying the object. If you are freeing the memory right after destroying this is going to cost you performance.
>
> To avoid this declare:
>
> extern (C) void rt_finalize2(void* p, bool det = true, bool resetMemory = true);
>
> and then call
>
> rt_finalize(cast(void*)object, false, false);
>
> Also if you want to give a nice error message in case you are calling a construcor that does not exist you should take a look at my AllocatorNew function:
>
> https://github.com/Ingrater/druntime/blob/merge64/src/core/allocator.d#L616
>
> Doing it the way emplace does will just result in a error message
>
> "Dont know how to initialize a object of type YourObject"
>
> With some meta programming you can get error messages like:
>
> "Dont know how to initialize a object of type YourObject
> Available constructors:
> this(int, int)
> this(float)
> this(void*)"
>
> Kind Regards
> Benjamin Thaut

I just need to call the destructor of the class since the memory of the allocators is released at the end of the application.

        // Pre allocate 1GB.
        auto pMemory = GC.malloc(1_048_576 * 1000, GC.BlkAttr.NONE);

        // Allocate a linear allocator of 10MB.
        auto pLinearAllocator = new LinearAllocator(1_048_576 * 10, pMemory);

        // Allocates a pool allocator of 50MB.
        auto pMemoryBlock = pMemory + 1_048_576 * 10;
        auto pPoolAllocator = new PoolAllocator!MyComponent(1_048_576 * 50, pMemory + 1_048_576 * 10);

        // Game loop, etc.
        // ..... (When a object is called to release, it won't release its memory rather than cache the entry and call the object destructor. Releasing the object from GC

        // end of game
        exit() // Allocators are released here, because GC will not find any reference to it, and will call any object destructor left.

1 2
Next ›   Last »