www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Suggestion for allocators and D integration for them

reply foobar <foo bar.com> writes:
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?
Jul 16 2010
parent Petr Janda <janda.petr gmail.com> writes:
I would be interested to see what other think about this.

Sounds pretty cool for me!

Thanks,
Petr
Jul 19 2010