On Saturday, 18 February 2017 at 23:08:52 UTC, Seb wrote:
Yes. The event loop is the oldest part of tanya. At the time I
began to work on it, eventcore was very young and got very seldom
updates. I only heard it is the new fast and native event loop
for the new generation of vibe.d. There was libasync aswell which
was written as a native replacement for libevent, but was never
adopted more than just as an option; instead eventcore was
written from the ground up. Botan suffered an even worse fate. So
I wasn't sure what direction eventcore would take. No of the
event loops, I was aware of, had IOCP support on Windows. For me
windows wasn't that important, but I implemented it to ensure
that the same API can work with both, Posix-style events and the
asynchronous Windows completion ports; and I could really fix
some design flaws implementing IOCP. I don't know if I really
want to have such an abstraction included in phobos, since there
are bindings for C event loops and a few native ones, and maybe
they will continue to exist, regardless whether there is
something in Phobos or not. But yes, if Phobos would have
something for asynchronous programming, I would take a look into
Do you know about eventcore  (event loop abstraction)?
I hope that this will soon be submitted to Phobos as everyone
seems to be brewing their own solution and I am _not_ looking
forward to manage to find a way to run five event loops when I
want to use fix different libraries.
However I would be very interested in hearing your reasons for
not using it.
Keep in mind that std.experimental.allocator is supposed to be
a general purpose library exactly to avoid everyone writing
their own, incompatible Allocators ;-)
So please raise your voice as long as it's still in
Thanks for the question. I had to describe it from the beginning
or in the README, but didn't want to blow my message up.
BDE allocators implement an interface, other allocators normally
not. It is the main point. It is not about a concrete interface.
Phobos allocators are structs, they can't implement anything and
there is a CAllocatorImpl, that implements IAllocator and wraps
other allocators, so structs can behave as if they would
implement IAllocator too. But these structs can be used directly
without CallocatorImpl in the templated code.
So if you have a container, you can do:
auto arr = Array!(int, Mallocator)(Mallocator.instance);
EMSIContainers do that and it is the way Phobos allocators and
containers will go.
If you don't want to template your code or you use phobos default
allocator, you do the following (because theAllocator should have
theAllocator = allocatorObject(Mallocator.instance);
Contras of my allocators:
1) they are slower (because of virtual function calls)
2) If the allocator is passed as template parameter, functions
that rely on the allocator can infer the attributes like @safe,
@nogc, pure (yes, there was a discussion to make malloc pure).
1) "is-a" relation. Mallocator "is-a" allocator, MmapAllocator
"is-a" allocator. In your code if you use allocators as a
template parameter (the faster way), you can't rely that the
allocator implements some method. So your code will look like:
static if (allocator has method "expand")
if (allocator.expand(arr, 8))
2) Less code bloat. With phobos allocators you would make as much
as possible to templates.
3) I see absolute no reason, why Array!(int, Mallocator) and
Array!(int, GCAllocator) has different types. Do you want a
function that accepts an array:
void myFunc(Array!int arr);
you have to make a template function from it (with a long "if
check" that ensures that an Array!int is passed). Code bloat.
4) It just works everywhere. Phobos allocators are structs but
there is still IAllocator interface, because the model isn't
5) I started by implementing IAllocator and the reason I dropped
it then, is IAllocator.expand. If you have an array of type A
where A is a struct with a postblit constructor, you can't just
call realloc() to resize the array. realloc() can move memory and
if an object of type A has references to other objects in the
array, the objects will be corrupted. "A" should be a POD-type.
Otherwise you have to allocate new memory, initialize it, copy
the objects by one and deallocate the old memory. Now there is
IAllocator.expand(). If IAllocator.expand() can expand the memory
in place, everything is fine, you haven't to copy the objects
because the addresses don't change. But libc realloc for example
doesn't guarantee that the address doesn't change if you shrink
the memory. But IAllocator doesn't have a shrink() method.
And anyway I find this separation expand/shrink or
expandArray/shrinkArray inconvenient; I had to check everywhere
if the new size is larger or smaller than the old one, then call
expandArray or shrinkArray with a delta size (maybe it was only
my use case). Therefore I replaced it reallocateInPlace.