www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Mallocator

reply Erik Smith <erik cruiserhouse.com> writes:
Just a question on Mallocator and shared.  My code does a lot of 
non-GC heap allocation (malloc) for buffers, so I reached for 
Mallocator as a starting point. I propagate an Allocator type 
generically through my structs, but it is defaulted to Mallocator.

After checking with the docs & TDPL, I'm still a bit confused on 
how to deal with the shared functions in Mallocator and what the 
effect of shared functions is in this context (see code below). I 
get the error "allocate is not callable using a non-shared 
object" and I'm not sure how to resolve it.  I'm not sure if I 
should cast shared away (or how to make that work).  The docs say 
malloc/free is thread safe as far as D is concerned, so 
synchronized doesn't seem to be the answer. Forking Mallocator 
without shared solved the issue temporarily.

Also Allocators are, in general, not copyable so I should 
propagate them around as references (or pointers in struct 
members), correct?

struct Mallocator{
...
      trusted  nogc nothrow
     void[] allocate(size_t bytes) shared
     {
         import core.stdc.stdlib : malloc;
         if (!bytes) return null;
         auto p = malloc(bytes);
         return p ? p[0 .. bytes] : null;
     }

      system  nogc nothrow
     bool deallocate(void[] b) shared
     {
         import core.stdc.stdlib : free;
         free(b.ptr);
         return true;
     }
...
}
Mar 03 2016
parent reply Brian Schott <briancschott gmail.com> writes:
On Thursday, 3 March 2016 at 19:01:52 UTC, Erik Smith wrote:
 I get the error "allocate is not callable using a non-shared 
 object" and I'm not sure how to resolve it.
Are you calling `Mallocator.allocate()` or `Mallocator.instance.allocate()`?
Mar 03 2016
parent reply Erik Smith <erik cruiserhouse.com> writes:
On Thursday, 3 March 2016 at 19:32:40 UTC, Brian Schott wrote:
 On Thursday, 3 March 2016 at 19:01:52 UTC, Erik Smith wrote:
 I get the error "allocate is not callable using a non-shared 
 object" and I'm not sure how to resolve it.
Are you calling `Mallocator.allocate()` or `Mallocator.instance.allocate()`?
The later works and qualifying the allocator member variable shared seems to solve the issue. Example: struct A(T) { alias Allocator = T; shared Allocator allocator; this(string url="") { allocator = Allocator(); void *p1 = cast(void*)(allocator.allocate(1024)); //void p2[] = allocator.allocate(1024); // ICE } } A!Mallocator a; However, this seems bad because it assumes that all allocators are shared. It appears, however that the qualifier can be attached to the type so maybe there is some meta-programming tricks that can be used: alias Allocator = shared T; I'm not sure if I'm on the right track. Note also the ICE in the example above. erik
Mar 03 2016
parent reply Meta <jared771 gmail.com> writes:
On Thursday, 3 March 2016 at 20:16:55 UTC, Erik Smith wrote:
 The later works and qualifying the allocator member variable 
 shared seems to solve the issue.  Example:

 struct A(T) {
     alias Allocator = T;
     shared Allocator allocator;
     this(string url="") {
         allocator = Allocator();
         void *p1 = cast(void*)(allocator.allocate(1024));
         //void p2[] = allocator.allocate(1024); // ICE
     }
 }
Does this still ICE when you write it as `void[] p2 = allocator.allocate(1024)`?
Mar 03 2016
parent Erik Smith <erik cruiserhouse.com> writes:
On Thursday, 3 March 2016 at 20:31:47 UTC, Meta wrote:
 On Thursday, 3 March 2016 at 20:16:55 UTC, Erik Smith wrote:
 The later works and qualifying the allocator member variable 
 shared seems to solve the issue.  Example:

 struct A(T) {
     alias Allocator = T;
     shared Allocator allocator;
     this(string url="") {
         allocator = Allocator();
         void *p1 = cast(void*)(allocator.allocate(1024));
         //void p2[] = allocator.allocate(1024); // ICE
     }
 }
Does this still ICE when you write it as `void[] p2 = allocator.allocate(1024)`?
No. :)
Mar 03 2016