1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
// --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- //
// Check what's going on with the temp allocator:
// Is it really the responsible for these paths?
// It seems that the next beta (after 0.1.055b) compiler allows us to check this pretty easily.
//
//
// An example that uses several different allocators, then asks them all
// who owns which memory.
//
// Note that this is probably not the kind of thing you want to do at runtime
// in the steady state, as it may not be very fast, but it could be a very helpful
// debugging facility.
//
#import "Basic";
#import "Pool";
#import "Flat_Pool";
#import "rpmalloc";
main :: () {
pool: Pool;
flat: Flat_Pool;
a := context.default_allocator;
b := Allocator.{pool_allocator_proc, *pool};
c := Allocator.{flat_pool_allocator_proc, *flat};
d := Allocator.{rpmalloc_allocator_proc, null};
d.proc(.STARTUP, 0, 0, null, null); // rpmalloc needs explicit init right now, but others don't.
ma := alloc(1000, allocator=a);
mb := alloc(1000, allocator=b);
mc := alloc(1000, allocator=c);
md := alloc(1000, allocator=d);
report_who_owns(ma, a, b, c, d);
report_who_owns(mb, a, b, c, d);
report_who_owns(mc, a, b, c, d);
report_who_owns(md, a, b, c, d);
}
report_who_owns :: (memory: *void, allocators: .. Allocator) {
someone_owns_this := false;
print("Querying all allocators for address: %\n", memory);
for allocators {
caps, name := get_capabilities(it);
assert((caps & .IS_THIS_YOURS) != 0); // It had better be claiming to support this!
yours := cast(bool) it.proc(.IS_THIS_YOURS, 0, 0, memory, it.data);
print("[%] says \"%\"\n", yours, name);
someone_owns_this ||= yours;
}
assert(someone_owns_this);
}
// --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- //
checked_add :: (a: $T, b: T) -> result: T, overflow: bool
#modify {
if T.type == .INTEGER return;
T = null;
}
{
overflow: bool;
result: T = a + b;
info := type_info(T);
if info.signed {
// (+A) + (+B) = −C
// (−A) + (−B) = +C
if ((a > 0) && (b > 0) && (result < 0)) || ((a < 0) && (b < 0) && (result > 0)) {
overflow = true;
}
} else {
if result < a {
overflow = true;
}
}
return result, overflow;
}
checked_sub :: (a: $T, b: T) -> result: T, overflow: bool
#modify {
if T.type == .INTEGER return;
T = null;
}
{
overflow: bool;
result: T = a - b;
info := type_info(T);
if info.signed {
// (+A) − (−B) = −C
// (−A) − (+B) = +C
if ((a > 0) && (b < 0) && (result < 0)) || ((a < 0) && (b > 0) && (result > 0)) {
overflow = true;
}
} else {
if result > a {
overflow = true;
}
}
return result, overflow;
}
|