Created
July 4, 2009 11:25
-
-
Save DanielKeep/140531 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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