Suggestion for allocators and D integration for them

foobar foo at bar.com
Fri Jul 16 12:08:23 PDT 2010


Recently Andrei asked for a design for allocators and there was also a discussion about removing "delete" and maybe even "new". 

Here's my design ideas:

1. we define some Allocator interface, e.g.
//shamelessly copied from Andrei and put into an interface :)
Interface Allocator {
    T* create(T, Args...)(Args args) if (!is(T == class) && !isDynamicArray!T);
    T create(T, Args...)(Args args) if (is(T == class) || isDynamicArray!T);
    void destroy(T)(ref T obj);
    // add other functions?
}

The GC will need to implement the interface. 

2. we remove placement new.
3. we allow to define a regular (virtual) member-function called "new" that has an argument of type Allocator in its argument list
4.  Constructors can become virtual

The semantics would be that "new" contains logic for allocation and "this" contains logic for initialization

here's an example:
interface Pizza {
    @override @property double price();
}

class MushroomPizza : Pizza {
private: 
    int size;

public:
    @property double price() { return 5.5; }    
    this(int a) { size = a; }
}

class DeluxePizza : Pizza {
private: 
    int size;

public:
    @property double price() { return 7.5; }
    A this(int a) { size = a; }
}

class HawaiianPizza : Pizza {
    // only personal pizzas
    @property double price() { return 12.5; }
}

// built in the language factory design pattern :)
class PizzaFactory {
    Pizza new(Allocator allocator, string type, int size = 1) { 
        if (type == "Mushroom")
            return allocator.create! MushroomPizza(size);
        else if (type == "Deluxe")
            return allocator.create!DeluxePizza(size);
        else if (type == "Hawaiian")
            return allocator.create!HawaiianPizza();
    }
}

we can do a simple trick in order to preserve current syntax to use the above:

auto p1 = new(FooAlloc) PizaaFactory("Hawaiian");
Pizza p2 = new PizaaFactory("Deluxe", 4);

where the compiler rewrites it to:
auto p1 = PizaaFactory.new(FooAlloc, "Hawaiian");
Pizza p2 = PizaaFactory.new(GC, "Deluxe", 4); // defaults to GC for classes

D would provide compatible GC Allocator for reference types and a StackAllocator for value types.

For example, to allocate a struct on the heap you'd call:
auto value = new(GC) Struct(arg1, arg2);

we can require empty parens after new to force new default behavior, 
e.g. 
// current semantics that the compiler can warn about
auto pizza = new HawaiianPizza(4); 

// new semantics: "new" is called with GC as allocator
auto pizza = new() HawaiianPizza(4); 

What do you think?


More information about the Digitalmars-d mailing list