Binary data-structure serialization

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Wed Jun 2 12:57:42 PDT 2010


On 06/02/2010 02:49 PM, Steven Schveighoffer wrote:
> On Wed, 02 Jun 2010 15:34:32 -0400, Andrei Alexandrescu
> <SeeWebsiteForEmail at erdani.org> wrote:
>
>> On 06/02/2010 02:27 PM, Steven Schveighoffer wrote:
>>> On Wed, 02 Jun 2010 15:16:53 -0400, Andrei Alexandrescu
>>> <SeeWebsiteForEmail at erdani.org> wrote:
>>>
>>>> On 06/02/2010 02:04 PM, Steven Schveighoffer wrote:
>>>>> On Tue, 01 Jun 2010 21:59:20 -0400, Andrei Alexandrescu
>>>>> <SeeWebsiteForEmail at erdani.org> wrote:
>>>>>
>>>>>> On 06/01/2010 08:53 PM, bearophile wrote:
>>>>>>> Andrei Alexandrescu Wrote:
>>>>>>>> Walter and I agreed to let it go, but somehow forgot to
>>>>>>>> announce it.
>>>>>>>
>>>>>>> Are stack-allocated (scoped) classes too gone?
>>>>>>
>>>>>> De facto no, de jure yes.
>>>>>
>>>>> I don't really understand this. Are they going to be gone or not?
>>>>>
>>>>> In any case, can we at least keep them for unsafe D? Stack
>>>>> allocation is
>>>>> not easy to do via placement new, the compiler is much better
>>>>> suited for
>>>>> it, and stack allocating classes can be a huge performance gain. Until
>>>>> we get full escape analysis, scope classes are the only option.
>>>>
>>>> There's no need for a language feature. I am implementing stack
>>>> allocation for classes in library code; I'm just undecided on where to
>>>> put it.
>>>
>>> I think it belongs in druntime, since it's an allocation feature. How
>>> easy is it to use?
>>
>> The signature for non-class types is:
>>
>> T* emplace(T, Args...)(void * address, Args args);
>>
>> The function creates an object of type T at location address and
>> initializes it with args. Returns a pointer to the just-created value.
>> I needed this function for TightArray.
>>
>> I haven't yet defined the signature for class types, but probably it
>> would look like this:
>>
>> T emplace(T, Args...)(void * address, Args args);
>>
>> To obtain stack allocation, you may therefore write something like:
>>
>> auto obj = emplace(alloca(_traits(classInstanceSize, T)), stuff);
>>
>> Although it uses the obscure classInstanceSize, I think it's near the
>> desired balance between terseness and making the programmer sweat for
>> a dangerous achievement.
>
> This makes it better than scope classes for one reason -- it's an
> expression instead of a declaration. That means I can use it to create a
> temporary.
>
> But I have some qualms here -- when is the object's destructor called? I
> know it probably cannot be done any other way unless we had something
> like macros, but it's not easy for humans to parse this mess. Sure, it
> should be somewhat difficult for the developer to write, but what about
> the reader? I suppose there just isn't an easy way to do this.
>
> Also, wouldn't it have to be something like this:
>
> auto obj = emplace!T(alloca(_traits(classInstanceSize, T)), stuff);
>
> And finally, is there any possible way to write an emplace that uses an
> allocator alias instead of the actual memory location? i.e.
>
> T emplace2(T, alias alloc, Args...)(Args args)
> {
> return emplace!(T, Args)(alloc(_traits(classInstanceSize, T)), args);
> }
>
> Anything to avoid the double-specification of T would be nice. This of
> course would be impossible to use with alloca without macros.
>
> -Steve

Good points.

To ensure the destructor is called, I guess we need this:

@system struct StackAllocated(T)
{
     private ubyte buffer[__traits(classInstanceSize, T)] = void;
     @property T payload() { return cast(T) buffer.ptr; }
     alias payload this;
     @disable this(); // meh
     @disable this(this);
     this(Args...)(auto ref Args args)
     {
         emplace!T(buffer.ptr, buffer.length);
     }
     ~this()
     {
         clear(payload);
     }
}


Andrei


More information about the Digitalmars-d mailing list