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