Fix issue #51; begin work on atomic types

This commit is contained in:
Ginger Bill
2017-04-28 11:01:46 +01:00
parent b78e970698
commit 99125dc743
12 changed files with 232 additions and 135 deletions
+1
View File
@@ -50,6 +50,7 @@ Type_Info :: union {
Pointer{
elem: ^Type_Info, // nil -> rawptr
},
Atomic{elem: ^Type_Info},
Procedure{
params: ^Type_Info, // Type_Info.Tuple
results: ^Type_Info, // Type_Info.Tuple
-100
View File
@@ -1,100 +0,0 @@
// TODO(bill): Use assembly instead here to implement atomics
// Inline vs external file?
#import win32 "sys/windows.odin" when ODIN_OS == "windows";
_ := compile_assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version
yield_thread :: proc() { win32.mm_pause(); }
mfence :: proc() { win32.ReadWriteBarrier(); }
sfence :: proc() { win32.WriteBarrier(); }
lfence :: proc() { win32.ReadBarrier(); }
load :: proc(a: ^i32) -> i32 {
return a^;
}
store :: proc(a: ^i32, value: i32) {
a^ = value;
}
compare_exchange :: proc(a: ^i32, expected, desired: i32) -> i32 {
return win32.InterlockedCompareExchange(a, desired, expected);
}
exchanged :: proc(a: ^i32, desired: i32) -> i32 {
return win32.InterlockedExchange(a, desired);
}
fetch_add :: proc(a: ^i32, operand: i32) -> i32 {
return win32.InterlockedExchangeAdd(a, operand);
}
fetch_and :: proc(a: ^i32, operand: i32) -> i32 {
return win32.InterlockedAnd(a, operand);
}
fetch_or :: proc(a: ^i32, operand: i32) -> i32 {
return win32.InterlockedOr(a, operand);
}
spin_lock :: proc(a: ^i32, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
old_value := compare_exchange(a, 1, 0);
counter := 0;
for old_value != 0 && (time_out < 0 || counter < time_out) {
counter++;
yield_thread();
old_value = compare_exchange(a, 1, 0);
mfence();
}
return old_value == 0;
}
spin_unlock :: proc(a: ^i32) {
store(a, 0);
mfence();
}
try_acquire_lock :: proc(a: ^i32) -> bool {
yield_thread();
old_value := compare_exchange(a, 1, 0);
mfence();
return old_value == 0;
}
load :: proc(a: ^i64) -> i64 {
return a^;
}
store :: proc(a: ^i64, value: i64) {
a^ = value;
}
compare_exchange :: proc(a: ^i64, expected, desired: i64) -> i64 {
return win32.InterlockedCompareExchange64(a, desired, expected);
}
exchanged :: proc(a: ^i64, desired: i64) -> i64 {
return win32.InterlockedExchange64(a, desired);
}
fetch_add :: proc(a: ^i64, operand: i64) -> i64 {
return win32.InterlockedExchangeAdd64(a, operand);
}
fetch_and :: proc(a: ^i64, operand: i64) -> i64 {
return win32.InterlockedAnd64(a, operand);
}
fetch_or :: proc(a: ^i64, operand: i64) -> i64 {
return win32.InterlockedOr64(a, operand);
}
spin_lock :: proc(a: ^i64, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
old_value := compare_exchange(a, 1, 0);
counter := 0;
for old_value != 0 && (time_out < 0 || counter < time_out) {
counter++;
yield_thread();
old_value = compare_exchange(a, 1, 0);
mfence();
}
return old_value == 0;
}
spin_unlock :: proc(a: ^i64) {
store(a, 0);
mfence();
}
try_acquire_lock :: proc(a: ^i64) -> bool {
yield_thread();
old_value := compare_exchange(a, 1, 0);
mfence();
return old_value == 0;
}
+7
View File
@@ -212,6 +212,10 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
}
case String: write_string(buf, "string");
case Boolean: write_string(buf, "bool");
case Atomic:
write_string(buf, "atomic ");
write_type(buf, info.elem);
case Pointer:
if info.elem == nil {
write_string(buf, "rawptr");
@@ -813,6 +817,9 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
fmt_pointer(fi, (cast(^rawptr)v.data)^, verb);
}
case Atomic:
fmt_arg(fi, any{v.data, info.elem}, verb);
case Array:
if verb != 'v' {
fmt_bad_verb(fi, verb);