Skip to content

Instantly share code, notes, and snippets.

@DanielKeep
Created July 4, 2009 11:25
Show Gist options
  • Save DanielKeep/140531 to your computer and use it in GitHub Desktop.
Save DanielKeep/140531 to your computer and use it in GitHub Desktop.
/**
* Copyright: © 2009, Daniel Keep.
* License: MIT <http://www.opensource.org/licenses/mit-license.php>
*/
module etc.mem.util;
private
struct Align
{
ubyte a;
void* b;
}
private
const PTR_ALIGN = Align.tupleof[1].alignof;
version( X86 )
const MEM_ALIGN = 8u;
else
static assert(false, "Unknown memory alignment for this platform.");
private
template AlignPad(size_t base, size_t aligned)
{
static if( aligned == 0 )
const AlignPad = base;
else
const AlignPad = ((base+PTR_ALIGN-1)/PTR_ALIGN)*PTR_ALIGN
+ aligned;
}
template InstanceSize(T)
{
static if( is( T == Object ) )
const InstanceSize = 2*(void*).sizeof;
else
const InstanceSize = Max!(
AlignPad!(
InstanceSize!(Super!(T)),
InterfaceCount!(T)*(void*).sizeof),
AlignPad!(
InstanceSizeImpl!(T, 0),
+ InterfaceCount!(T)*(void*).sizeof));
}
private
template Super(T)
{
static if( is( T S == super ) )
alias First!(S) Super;
else
static assert(false, "Can't get super of "~T.mangleof);
}
private
template First(T)
{
alias T First;
}
private
template First(T, Ts...)
{
alias T First;
}
private
template InstanceSizeImpl(T, size_t i)
{
static if( i < T.tupleof.length )
const InstanceSizeImpl = Max!(
T.tupleof[i].offsetof + T.tupleof[i].sizeof,
InstanceSizeImpl!(T, i+1));
else
// This is necessary to account for classes without member
// variables.
const InstanceSizeImpl = 2*(void*).sizeof;
}
private
template Max(size_t a, size_t b)
{
static if( a > b )
const Max = a;
else
const Max = b;
}
template InstanceSizeAligned(T, size_t alignment=MEM_ALIGN)
{
static if( alignment == 0 )
const InstanceSizeAligned = InstanceSize!(T);
else
const uint InstanceSizeAligned
= InstanceSizeAlignImpl!(T, alignment).result;
}
private
template InstanceSizeAlignedImpl(T, size_t alignment)
{
private const base_size = InstanceSize!(T);
const result = ((base_size+alignment-1)/alignment)*alignment;
}
private
template InterfaceCount(T)
{
static if( is( T == Object ) )
const InterfaceCount = 0u;
else static if( is( T S == super ) )
const InterfaceCount = InterfaceCountImpl!(S);
}
private
template InterfaceCountImpl(TBase, TInterfaces...)
{
const InterfaceCountImpl = TInterfaces.length;
}
version( etc_mem_util_main )
{
import std.stdio;
interface I1 { }
interface I2 { }
interface I3 : I2 { }
class A { }
class B : A, I1 { }
class C : B { ubyte x; real y; }
class D : C, I3 { }
class E : D, I3 { }
template SuperTuple(T)
{
static if( is( T S == super ) )
alias S SuperTuple;
}
void main()
{
writefln("A: %s; %d, %d", typeid(SuperTuple!(A)),
A.classinfo.init.length, InstanceSize!(A));
writefln("B: %s; %d, %d", typeid(SuperTuple!(B)),
B.classinfo.init.length, InstanceSize!(B));
writefln("C: %s; %d, %d", typeid(SuperTuple!(C)),
C.classinfo.init.length, InstanceSize!(C));
writefln("D: %s; %d, %d", typeid(SuperTuple!(D)),
D.classinfo.init.length, InstanceSize!(D));
writefln("E: %s; %d, %d", typeid(SuperTuple!(E)),
E.classinfo.init.length, InstanceSize!(E));
writefln("InterfaceCount!(E) == %d", InterfaceCount!(E));
writefln("ptr alignment: %d", Align.tupleof[1].alignof);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment