Skip to content

Commit

Permalink
finish wait
Browse files Browse the repository at this point in the history
  • Loading branch information
Hanaasagi committed Jun 16, 2023
1 parent 751289c commit 101b920
Showing 1 changed file with 42 additions and 38 deletions.
80 changes: 42 additions & 38 deletions src/multithread.zig
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub fn Lazy(comptime T: type, comptime f: fn () T) type {
const Self = @This();

pub fn init() Self {
return Self{ .cell = OnceCell(T).init() };
return Self{ .cell = OnceCell(T).empty() };
}

pub fn get(self: *Self) *T {
Expand All @@ -34,22 +34,23 @@ pub fn OnceCell(comptime T: type) type {

cell: T,
mutex: std.Thread.Mutex,
done: std.atomic.Atomic(bool),
done: std.atomic.Atomic(u32),
const Self = @This();

pub fn init() Self {
pub fn empty() Self {
return Self{
.cell = undefined,
.mutex = std.Thread.Mutex{},
.done = std.atomic.Atomic(bool).init(false),
.done = std.atomic.Atomic(u32).init(0b00),
};
}

/// Creates a new initialized cell.
pub fn initWithValue(value: T) Self {
pub fn withValue(value: T) Self {
return Self{
.cell = value,
.done = true,
.mutex = std.Thread.Mutex{},
.done = std.atomic.Atomic(u32).init(0b01),
};
}

Expand Down Expand Up @@ -89,7 +90,7 @@ pub fn OnceCell(comptime T: type) type {
/// Takes the value out of this OnceCell, moving it back to an uninitialized state.
pub fn take(self: *Self) ?T {
if (self.isInitialize()) {
defer self.done.store(false, .Release);
defer self.done.store(0b00, .Release);

var cell = self.cell;
self.cell = undefined;
Expand All @@ -99,22 +100,24 @@ pub fn OnceCell(comptime T: type) type {
}

/// Gets the reference to the underlying value, blocking the current thread until it is set.
// pub fn wait(self: *Self) *T {
// if (self.done.load(.Monotonic) == false) {
// std.Thread.Futex.wait(&self.done, false);
// }
pub fn wait(self: *Self) *T {
while (self.done.load(.Monotonic) == 0b00) {
std.Thread.Futex.wait(&self.done, 0b00);
}

// while (self.done.swap(0b00, .Acquire) != 0b01) {
// std.Thread.Futex.wait(&self.done, 0b00);
// }

// while (self.done.swap(false, .Acquire) != true) {
// std.Thread.Futex.wait(&self.done, false);
// }
// }
return self.getUnchecked();
}

// --------------------------------------------------------------------------------
// Core API
// --------------------------------------------------------------------------------

fn isInitialize(self: Self) bool {
return self.done.load(.Acquire);
return self.done.load(.Acquire) == 0b01;
}

fn initialize(self: *Self, comptime f: fn () T) void {
Expand All @@ -124,9 +127,10 @@ pub fn OnceCell(comptime T: type) type {
defer self.mutex.unlock();

// The first thread to acquire the mutex gets to run the initializer
if (!self.done.loadUnchecked()) {
if (self.done.loadUnchecked() == 0b00) {
self.cell = f();
defer self.done.store(true, .Release);
defer self.done.store(0b01, .Release);
std.Thread.Futex.wake(&self.done, 1000);
}
}
};
Expand All @@ -151,7 +155,7 @@ fn returnMap() std.StringHashMap(i32) {
return map;
}

var globalMap = OnceCell(std.StringHashMap(i32)).init();
var globalMap = OnceCell(std.StringHashMap(i32)).empty();

test "test global map" {
_ = globalMap.getOrInit(returnMap);
Expand All @@ -171,7 +175,7 @@ test "test global map" {
defer r2.*.deinit();
}

var globalMap2 = OnceCell(std.StringHashMap(i32)).init();
var globalMap2 = OnceCell(std.StringHashMap(i32)).empty();

test "test global map take" {
_ = globalMap2.getOrInit(returnMap);
Expand All @@ -193,7 +197,7 @@ test "test global map take" {
}

test "test assume init" {
var cell1 = OnceCell(i32).init();
var cell1 = OnceCell(i32).empty();
const r1 = cell1.getOrInit(return_1);
const r2 = cell1.getUnchecked();

Expand All @@ -202,8 +206,8 @@ test "test assume init" {
}

test "test cell multi init" {
var cell1 = OnceCell(i32).init();
var cell2 = OnceCell(i32).init();
var cell1 = OnceCell(i32).empty();
var cell2 = OnceCell(i32).empty();

const r1 = cell1.getOrInit(return_1);
const r2 = cell1.getOrInit(return_1);
Expand All @@ -229,7 +233,7 @@ fn incrShared() i32 {
return shared;
}

var cell3 = OnceCell(i32).init();
var cell3 = OnceCell(i32).empty();

test "test multithread shared value" {
var threads: [10]std.Thread = undefined;
Expand All @@ -247,23 +251,23 @@ test "test multithread shared value" {
try testing.expectEqual(@as(i32, 1), shared);
}

// var cell4 = OnceCell(i32).init();
var cell4 = OnceCell(i32).empty();

// test "test wait" {
// var threads: [10]std.Thread = undefined;
// defer for (threads) |handle| handle.join();
test "test wait" {
var threads: [10]std.Thread = undefined;
defer for (threads) |handle| handle.join();

// for (&threads) |*handle| {
// handle.* = try std.Thread.spawn(.{}, struct {
// fn thread_fn(x: u8) void {
// _ = x;
// _ = cell4.wait();
// }
// }.thread_fn, .{0});
// }
for (&threads) |*handle| {
handle.* = try std.Thread.spawn(.{}, struct {
fn thread_fn(x: u8) void {
_ = x;
_ = cell4.wait();
}
}.thread_fn, .{0});
}

// _ = cell4.getOrInit(return_1);
// }
_ = cell4.getOrInit(return_1);
}

var LazyMap = Lazy(std.StringHashMap(i32), returnMap).init();

Expand Down

0 comments on commit 101b920

Please sign in to comment.