Binary data-structure serialization

Steven Schveighoffer schveiguy at yahoo.com
Wed Jun 2 13:04:49 PDT 2010


On Wed, 02 Jun 2010 15:57:42 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> 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);
>      }
> }

Hm... is this valid usage then?

foo(StackAllocated!MyClass(a, b, c));

:)

-Steve


More information about the Digitalmars-d mailing list