std.experimental.allocator and @nogc

rikki cattermole via Digitalmars-d digitalmars-d at puremagic.com
Mon May 9 05:37:24 PDT 2016


On 10/05/2016 12:33 AM, ZombineDev wrote:
> On Monday, 9 May 2016 at 12:02:19 UTC, rikki cattermole wrote:
>> On 09/05/2016 11:56 PM, ZombineDev wrote:
>>> On Monday, 9 May 2016 at 11:20:00 UTC, rikki cattermole wrote:
>>>> On 09/05/2016 11:12 PM, ZombineDev wrote:
>>>>> On Monday, 9 May 2016 at 10:33:27 UTC, rikki cattermole wrote:
>>>>>> I've done windowing and image libraries before.
>>>>>> You are correct, you do not need OOP.
>>>>>>
>>>>>> But if you want to keep implementation nicely separated out from
>>>>>> usage, you really do. Which is a major part of my requirements.
>>>>>
>>>>> Well, in my example above, everything is nicely separated, easy to
>>>>> use,
>>>>> yet quite flexible. And still there is no Java-style OOP. Do you have
>>>>> any examples, where the use of classic OOP would provide a strictly
>>>>> superior design?
>>>>
>>>> You're using templates. While this might be ok for image library.
>>>> I cannot use this for the windowing library. The implementation may
>>>> not be known and must be plugable at runtime.
>>>> The reality is, just because you say you know about something at
>>>> compile time doesn't mean the system that runs a program does.
>>>
>>> I'm still not convinced. You have a fixed at CT number of
>>> implementations. Even if you don't know at CT the actual platform that
>>> will be used, you can still choose at RT the correct template. Example:
>>
>> You do not.
>> Shared libraries remember them?
>
> You will statically link the windowing library and it will dynamically
> load the necessary shared/dynamic libaries of the platform at runtime.
> What's the problem? E.g. Derelict* does the same.
>
>>> // platform name can be "X11", "mir", "Wayland", etc.
>>> auto getPlatformWindow(CTArgs...)(string platformNameRTArg)
>>> {
>>>     switch (platformNameRTArg.toLower)
>>>     {
>>>         default:
>>>              enforce(false, "Unknown platform: " ~ platformNameRTArg);
>>>
>>>         foreach (platform; EnumMembers!Platform)
>>>             case name.stringof:
>>>                  // Use std.experiment.typecons.Wrap if you need a
>>> common type.
>>>                  return getWindow!(name, CTArgs);
>>>     }
>>>     assert (0);
>>> }
>>
>> Platform is undefined, did you mean IPlatform?
>
> Platform obviously an enum. The return type can be a plain struct, a
> Variant, or a std.experimental.typecons.wrap, depending on your needs.
>
>>> But that's besides the point. Even with OOP, your return type can be an
>>> interface that has template parameters like allocators, policies, etc.
>>> You're providing some the arguments at CT and the rest of the return
>>> type is dynamically polymorphic. E.g.:
>>>
>>> interface Window(Allocator, Policy);
>>> Window!(Allocator, Policy) getWindow(alias allocator,
>>> Policy)(RunTimeArgs);
>>
>> Sure you can, but now you have added another layer of indirection
>> between implementation and usage because you can't use templated types
>> in between.
>
> There's no indirection (besides the interface, which would also be the
> case with your approach) and you **should** use templated types :)
>
>>> My point is that there's no need for IAllocator, even if you want to use
>>> OOP so badly.
>>> But in most cases you will either write different code for different
>>> platforms, making interfaces unnecessary, or you would be able to hide
>>> the differences behind a struct.
>>>
>>> And when the allocator and the other policies are template parameters
>>> you will know at CT that your code is @nogc.
>>
>> Again, no templates. You cannot initialize them at runtime, and since
>> you won't know all implementations until it executes, well, you've got
>> a problem.
>> Its a many to many problem. I faced this with Cmsed as well.
>
> As I demonstrated, it's not a problem. You just need to choose the
> template at runtime. You have a fixed number of implementations which
> are all statically linked. Only the one chosen at runtime will be
> initialized and at the moment of initialization it can do the necessary
> dynamic loading.
>
> In the example above:
>
>>> interface Window(Allocator, Policy);
>>> Window!(Allocator, Policy) getWindow(alias allocator,
>>> Policy)(RunTimeArgs);
>
> Since you don't need to switch Allocator implementations at run-time
> (and if you switch them you will most certainly get silent memory
> corruption), you can leverage the fact that some stuff are known at CT
> and leave the rest to RT.

At this point, all I'm going to say is, prove me wrong.
Give me all the power I have now and do it the way you want to.

PR's welcome. https://github.com/rikkimax/alphaPhobos/

FYI, I'll be streaming in a minute https://www.livecoding.tv/alphaglosined/


More information about the Digitalmars-d mailing list