std.allocator needs your help

Chad Joan chadjoan at gmail.com
Mon Sep 23 21:53:24 PDT 2013


On Monday, 23 September 2013 at 03:58:51 UTC, Walter Bright wrote:
> On 9/22/2013 4:49 PM, Andrei Alexandrescu wrote:
>> Destroy!
>
> It should be compatible with:
>
> http://wiki.dlang.org/DIP46
>
> or the DIP should be adaptable to work with std.allocator.

It seems to me like DIP46 attempts to address Manu's concerns, 
and is (mostly) orthogonal to Andrei's designs.

I would wish the current GC to be defined according to Andrei's 
new API.  It should be the one that handles all allocations by 
default at program start.

I have a desire for region based allocation, and in this context 
I want to be able to push the thread's default allocator onto a 
"thread allocator stack" and thus make all D allocations (new's, 
string concats, etc) use the region allocator.  So I pretty much 
want DIP46, except I want "pushAllocator(...)" and 
"popAllocator()" instead of "gc_push()" and "gc_pop()".  The 
region allocator would also be defined according to Andrei's API.

By default, the region allocator should request giant chunks of 
memory from the GC (or whatever is past it in the thread's 
allocator stack).  This should be manually adjustable so that I 
can point it at a malloc-forwarding allocator (Mallocator).

The allocator stack at program start should probably look like 
this:

[GCAllocator] <- current
[Mallocator]
<system>

My server might look like this:

// ----------------------
module main;
import core.thread;
import thread_main;

void main(string[] args)
{
	... initialization/finalization (thanks scope(exit)!) ...

	while ( true )
	{
		if ( !handshake(connection, ...) )
			continue;

		auto worker = new Thread(&threadMain);
		worker.start();
	}
}

// ----------------------
module thread_main;

import std.allocator;

void threadMain()
{
	// Construct a region allocator that uses the nearest
	// Mallocator to allocate regions.
	auto regionAllocator = new RegionAllocator(getMallocator());

	// Use it by default for all of this thread's allocations.
	pushAllocator( regionAllocator );

	scope(exit)
	{
		// Free 'foo' and everything still allocated by
		// the call to doStuff().
		regionAllocator.deallocateAll();

		// Return control to the GC.
		popAllocator();
	}

	auto foo = ubyte[40]; // Region allocated.

	doStuff();
}

/// Gets the nearest Mallocator in the allocator stack, if it's
/// available.  Returns the allocator stack's front if there is
/// none.
Mallocator getMallocator()
{
	auto allocatorStackCopy = allocatorStack.save;
	auto result = allocatorStackCopy.front;
	while ( !allocatorStackCopy.empty )
	{
		// I just realized that allocators should be a class
		//   type and not a struct type, otherwise this function
		//   doesn't work!
		// <failure>
		// if (is(typeof(allocatorStackCopy.front) == Mallocator))
		// </failure>
		
		auto mallocator =
			cast(Mallocator)allocatorStackCopy.front;
		
		if ( mallocator !is null )
			result = mallocator;
	}

	return result;
}

// ----------------------

Now, once inside doStuff(), the allocator stack looks like so:

[RegionaAllocator] -.  <- Current
[GCAllocator]       |
[Mallocator] <------'
<system>

// ----------------------

I think I might have managed to demonstrate that Manu's concerns 
(and DIP46) have possible implications for Andrei's design: 
allocators need dynamic dispatch to be reassignable at runtime, 
and classes with inheritance seem like a natural choice for this. 
  I like my no-cost abstractions though, so I hate to admit the 
dynamic nature of this.  Is there a better way?

I definitely don't want 3rd parties to, at compile-time 
(link-time?), avoid my custom allocators by default.

Small aside: I don't like that statelessOp has to be nothrow.  Is 
there a reason that we can't pre-allocate a fixed amount of 
memory for exception objects, including at least one "can't 
allocate proper exception" fatal exception, and then throw the 
pre-allocated NoMemoryForException exception if we don't have 
enough memory to handle the throw's that may occur?


More information about the Digitalmars-d mailing list