std.experimental.allocator and @nogc

ZombineDev via Digitalmars-d digitalmars-d at puremagic.com
Mon May 9 03:28:04 PDT 2016


On Monday, 9 May 2016 at 06:35:36 UTC, rikki cattermole wrote:
> On 09/05/2016 6:22 PM, Hildigard Sandyman wrote:
>> It's true but... why do you bother with IAllocator ? 
>> Everything can be
>> set a compile time with a template parameter. As long as the 
>> param is a
>> struct with allocate/deallocate/reallocate it's OK. you can 
>> use already
>> a good part of the package content in a @nogc fashion.
>>
>> Do you have an example where IAllocator must be used and 
>> where, for
>> example, Mallocator can't be passed ?!
>
> The moment where you need to use OOP, you most definitely need 
> IAllocator.
> I cannot make a windowing library without the use of IAllocator.
>
> You can't always template functions with the type that is the 
> allocator.
> Its just not possible or reasonable.

You don't need OOP for neither windowing, nor image abstraction. 
None of the OS APIs require it. I haven't considered using 
classes for my projects for more than a year, because D offers 
much better ways to solve most problems and cuz programming in a 
Java-like way just sucks.
Functions that require memory allocation should take alias 
allocator template parameters. And everything should be templated 
for maximum flexibility!

For example, instead writing Image interfaces/classes or even 
structs, just offer a couple of free functions that convert from 
.bmp/.png/.jpg/ etc. to ndslice and back.

For example:

/**
  * Automatically determines the image format and reads the
  * image in memory by converting each pixel to `ColorType`.
  * Internally calls readImage!(ImageFormat.png) /
  * readImage!(ImageFormat.bmp / etc. depending on
  * the deduced image format.
  *
  * If the underlying `allocator` is `MmapAllocator`, it maps
  * the file into memory, instead of copying it.
  *
  * Parameters:
  *     file_path = string input range specifying location
  *                 of the image to be read
  *
  * Returns:
  *    `Slice!(N, RandAccessR!ColorType)` where `N` is >= 2.
  *    (All images are conceptually two dimensional, but may
  *    be internally divided into blocks).
  */
auto readImage(ColorType, alias allocator = GCAllocator.instance, 
R)(R file_path)
     if (isStringRange!R && isColor!ColorType &&
         is(typeof(allocatorInstance!allocator)));

// example 1 - image manipulation
unittest
{
     auto tinyAlloc = StackAllocator!256();
     auto imgAlloc = ScopedAllocator!MmapAllocator;
     alias C = Color!(ColorFormat.RGBA8);

     auto images =
         ["./img1.jpg", "../images/img2.png", "./mask.bmp"]
         .map!(path => path.readImage!(C, imgAlloc))
         .array!tinyAlloc; // force eager evaluation

     auto result = makeSlice!C(imgAlloc, image[0].shape);

     auto xyzo_slice = lockstep(aliasSeqOf!images, result);

     xyzo_slice.each!((in ref x, in ref y, in ref y, ref o) =>
                o = (x + y) * z)();

     result.writeImage!(ImageFormat.png)("./output.png");

     // All allocated memory is freed at the end of the scope.
}

// example 2 - image viewer
void main(string[] args)
{
     enforce(args.length == 2, "Usage: imgshow <image-path>");
     enforce(exists(args[1], "%s doesn't exist".format(args[1]));

     auto imgAllocator = ScopedAllocator!MmapAllocator;
     auto uiAllocator = ScopedAllocator!Mallocator;
     alias C = Color!(ColorFormat.RGBA8);
     auto img = readImage!(C, imgAllocator)(args[1]);

     // I don't think you need heap allocations for basic stuff
     // with Win32 but still I'm not familiar with every API out 
there.
     // `window` is RAII struct that should manage GUI resources
     // as needed.
     auto window = createWindowWithImage!uiAllocator(img);
     bool running = true;

     window.show.enterEventLoop!(
         (QuitEvent q) { running = false; },
         (ResizeEvent r) => false /* do not allow resizing */
         (MouseClick m) /* color picker */
             { writefln("pixel at [%s, %s] is %s",
                   m.coords.expand, img[m.coords]); }
         /* ignore other events */
     )(&running);
}

See, no classes or interfaces were harmed during the making of 
those examples :D






More information about the Digitalmars-d mailing list