diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2018-08-04 15:19:03 -0400 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2018-08-04 15:19:03 -0400 |
| commit | b48948d6e805cdee7f33243098af9a862c152df1 (patch) | |
| tree | 8b1b4b37670f7444e8fe12748a8db99ac7498cce /std | |
| parent | f804310d9f953c9d78a4271ba8d75133341840e6 (diff) | |
| parent | 9bd8b01650f9cf21e601117951711b21aa5fd216 (diff) | |
| download | zig-b48948d6e805cdee7f33243098af9a862c152df1.tar.gz zig-b48948d6e805cdee7f33243098af9a862c152df1.zip | |
Merge branch 'master' into llvm7
Diffstat (limited to 'std')
| -rw-r--r-- | std/event/channel.zig | 8 | ||||
| -rw-r--r-- | std/event/future.zig | 12 | ||||
| -rw-r--r-- | std/event/group.zig | 4 | ||||
| -rw-r--r-- | std/event/lock.zig | 35 | ||||
| -rw-r--r-- | std/event/loop.zig | 14 | ||||
| -rw-r--r-- | std/event/tcp.zig | 8 | ||||
| -rw-r--r-- | std/fmt/index.zig | 9 | ||||
| -rw-r--r-- | std/os/index.zig | 26 | ||||
| -rw-r--r-- | std/os/linux/index.zig | 2 | ||||
| -rw-r--r-- | std/os/linux/test.zig | 4 | ||||
| -rw-r--r-- | std/os/windows/advapi32.zig | 5 | ||||
| -rw-r--r-- | std/os/windows/util.zig | 2 | ||||
| -rw-r--r-- | std/rand/index.zig | 9 | ||||
| -rw-r--r-- | std/zig/ast.zig | 12 | ||||
| -rw-r--r-- | std/zig/parse.zig | 33 | ||||
| -rw-r--r-- | std/zig/parser_test.zig | 8 | ||||
| -rw-r--r-- | std/zig/render.zig | 16 |
17 files changed, 86 insertions, 121 deletions
diff --git a/std/event/channel.zig b/std/event/channel.zig index 03a036042b..71e97f6e78 100644 --- a/std/event/channel.zig +++ b/std/event/channel.zig @@ -71,10 +71,10 @@ pub fn Channel(comptime T: type) type { /// puts a data item in the channel. The promise completes when the value has been added to the /// buffer, or in the case of a zero size buffer, when the item has been retrieved by a getter. pub async fn put(self: *SelfChannel, data: T) void { - suspend |handle| { + suspend { var my_tick_node = Loop.NextTickNode{ .next = undefined, - .data = handle, + .data = @handle(), }; var queue_node = std.atomic.Queue(PutNode).Node{ .data = PutNode{ @@ -96,10 +96,10 @@ pub fn Channel(comptime T: type) type { // TODO integrate this function with named return values // so we can get rid of this extra result copy var result: T = undefined; - suspend |handle| { + suspend { var my_tick_node = Loop.NextTickNode{ .next = undefined, - .data = handle, + .data = @handle(), }; var queue_node = std.atomic.Queue(GetNode).Node{ .data = GetNode{ diff --git a/std/event/future.zig b/std/event/future.zig index f5d14d1ca6..8abdce7d02 100644 --- a/std/event/future.zig +++ b/std/event/future.zig @@ -100,8 +100,8 @@ test "std.event.Future" { } async fn testFuture(loop: *Loop) void { - suspend |p| { - resume p; + suspend { + resume @handle(); } var future = Future(i32).init(loop); @@ -115,15 +115,15 @@ async fn testFuture(loop: *Loop) void { } async fn waitOnFuture(future: *Future(i32)) i32 { - suspend |p| { - resume p; + suspend { + resume @handle(); } return (await (async future.get() catch @panic("memory"))).*; } async fn resolveFuture(future: *Future(i32)) void { - suspend |p| { - resume p; + suspend { + resume @handle(); } future.data = 6; future.resolve(); diff --git a/std/event/group.zig b/std/event/group.zig index 26c098399e..6c7fc63699 100644 --- a/std/event/group.zig +++ b/std/event/group.zig @@ -54,10 +54,10 @@ pub fn Group(comptime ReturnType: type) type { const S = struct { async fn asyncFunc(node: **Stack.Node, args2: ...) ReturnType { // TODO this is a hack to make the memory following be inside the coro frame - suspend |p| { + suspend { var my_node: Stack.Node = undefined; node.* = &my_node; - resume p; + resume @handle(); } // TODO this allocation elision should be guaranteed because we await it in diff --git a/std/event/lock.zig b/std/event/lock.zig index 2013b5595f..c4cb1a3f0e 100644 --- a/std/event/lock.zig +++ b/std/event/lock.zig @@ -90,10 +90,10 @@ pub const Lock = struct { } pub async fn acquire(self: *Lock) Held { - suspend |handle| { + suspend { // TODO explicitly put this memory in the coroutine frame #1194 var my_tick_node = Loop.NextTickNode{ - .data = handle, + .data = @handle(), .next = undefined, }; @@ -106,35 +106,12 @@ pub const Lock = struct { // will attempt to grab the lock. _ = @atomicRmw(u8, &self.queue_empty_bit, AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst); - while (true) { - const old_bit = @atomicRmw(u8, &self.shared_bit, AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst); - if (old_bit != 0) { - // We did not obtain the lock. Trust that our queue entry will resume us, and allow - // suspend to complete. - break; - } - // We got the lock. However we might have already been resumed from the queue. + const old_bit = @atomicRmw(u8, &self.shared_bit, AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst); + if (old_bit == 0) { if (self.queue.get()) |node| { // Whether this node is us or someone else, we tail resume it. resume node.data; - break; - } else { - // We already got resumed, and there are none left in the queue, which means that - // we aren't even supposed to hold the lock right now. - _ = @atomicRmw(u8, &self.queue_empty_bit, AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst); - _ = @atomicRmw(u8, &self.shared_bit, AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst); - - // There might be a queue item. If we know the queue is empty, we can be done, - // because the other actor will try to obtain the lock. - // But if there's a queue item, we are the actor which must loop and attempt - // to grab the lock again. - if (@atomicLoad(u8, &self.queue_empty_bit, AtomicOrder.SeqCst) == 1) { - break; - } else { - continue; - } } - unreachable; } } @@ -164,8 +141,8 @@ test "std.event.Lock" { async fn testLock(loop: *Loop, lock: *Lock) void { // TODO explicitly put next tick node memory in the coroutine frame #1194 - suspend |p| { - resume p; + suspend { + resume @handle(); } const handle1 = async lockRunner(lock) catch @panic("out of memory"); var tick_node1 = Loop.NextTickNode{ diff --git a/std/event/loop.zig b/std/event/loop.zig index 4e219653be..8b1b2e53db 100644 --- a/std/event/loop.zig +++ b/std/event/loop.zig @@ -331,11 +331,11 @@ pub const Loop = struct { pub async fn waitFd(self: *Loop, fd: i32) !void { defer self.removeFd(fd); - suspend |p| { + suspend { // TODO explicitly put this memory in the coroutine frame #1194 var resume_node = ResumeNode{ .id = ResumeNode.Id.Basic, - .handle = p, + .handle = @handle(), }; try self.addFd(fd, &resume_node); } @@ -417,11 +417,11 @@ pub const Loop = struct { pub fn call(self: *Loop, comptime func: var, args: ...) !(promise->@typeOf(func).ReturnType) { const S = struct { async fn asyncFunc(loop: *Loop, handle: *promise->@typeOf(func).ReturnType, args2: ...) @typeOf(func).ReturnType { - suspend |p| { - handle.* = p; + suspend { + handle.* = @handle(); var my_tick_node = Loop.NextTickNode{ .next = undefined, - .data = p, + .data = @handle(), }; loop.onNextTick(&my_tick_node); } @@ -439,10 +439,10 @@ pub const Loop = struct { /// CPU bound tasks would be waiting in the event loop but never get started because no async I/O /// is performed. pub async fn yield(self: *Loop) void { - suspend |p| { + suspend { var my_tick_node = Loop.NextTickNode{ .next = undefined, - .data = p, + .data = @handle(), }; self.onNextTick(&my_tick_node); } diff --git a/std/event/tcp.zig b/std/event/tcp.zig index 416a8c07dc..ea803a9322 100644 --- a/std/event/tcp.zig +++ b/std/event/tcp.zig @@ -88,8 +88,8 @@ pub const Server = struct { }, error.ProcessFdQuotaExceeded => { errdefer std.os.emfile_promise_queue.remove(&self.waiting_for_emfile_node); - suspend |p| { - self.waiting_for_emfile_node = PromiseNode.init(p); + suspend { + self.waiting_for_emfile_node = PromiseNode.init( @handle() ); std.os.emfile_promise_queue.append(&self.waiting_for_emfile_node); } continue; @@ -141,8 +141,8 @@ test "listen on a port, send bytes, receive bytes" { (await next_handler) catch |err| { std.debug.panic("unable to handle connection: {}\n", err); }; - suspend |p| { - cancel p; + suspend { + cancel @handle(); } } async fn errorableHandler(self: *Self, _addr: *const std.net.Address, _socket: *const std.os.File) !void { diff --git a/std/fmt/index.zig b/std/fmt/index.zig index 8daec50f17..f4f9efee37 100644 --- a/std/fmt/index.zig +++ b/std/fmt/index.zig @@ -248,6 +248,11 @@ pub fn formatIntValue( return formatAsciiChar(value, context, Errors, output); } }, + 'b' => { + radix = 2; + uppercase = false; + width = 0; + }, 'd' => { radix = 10; uppercase = false; @@ -875,6 +880,10 @@ test "fmt.format" { try testFmt("u8: a\n", "u8: {c}\n", value); } { + const value: u8 = 0b1100; + try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", value); + } + { const value: [3]u8 = "abc"; try testFmt("array: abc\n", "array: {}\n", value); try testFmt("array: abc\n", "array: {}\n", &value); diff --git a/std/os/index.zig b/std/os/index.zig index 77fd2a78ad..425a900a71 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -130,16 +130,10 @@ pub fn getRandomBytes(buf: []u8) !void { try posixRead(fd, buf); }, Os.windows => { - var hCryptProv: windows.HCRYPTPROV = undefined; - if (windows.CryptAcquireContextA(&hCryptProv, null, null, windows.PROV_RSA_FULL, 0) == 0) { - const err = windows.GetLastError(); - return switch (err) { - else => unexpectedErrorWindows(err), - }; - } - defer _ = windows.CryptReleaseContext(hCryptProv, 0); - - if (windows.CryptGenRandom(hCryptProv, @intCast(windows.DWORD, buf.len), buf.ptr) == 0) { + // Call RtlGenRandom() instead of CryptGetRandom() on Windows + // https://github.com/rust-lang-nursery/rand/issues/111 + // https://bugzilla.mozilla.org/show_bug.cgi?id=504270 + if (windows.RtlGenRandom(buf.ptr, buf.len) == 0) { const err = windows.GetLastError(); return switch (err) { else => unexpectedErrorWindows(err), @@ -159,8 +153,14 @@ pub fn getRandomBytes(buf: []u8) !void { } test "os.getRandomBytes" { - var buf: [50]u8 = undefined; - try getRandomBytes(buf[0..]); + var buf_a: [50]u8 = undefined; + var buf_b: [50]u8 = undefined; + // Call Twice + try getRandomBytes(buf_a[0..]); + try getRandomBytes(buf_b[0..]); + + // Check if random (not 100% conclusive) + assert( !mem.eql(u8, buf_a, buf_b) ); } /// Raises a signal in the current kernel thread, ending its execution. @@ -2790,7 +2790,7 @@ pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize { builtin.Os.macosx => { var count: c_int = undefined; var count_len: usize = @sizeOf(c_int); - const rc = posix.sysctlbyname(c"hw.ncpu", @ptrCast(*c_void, &count), &count_len, null, 0); + const rc = posix.sysctlbyname(c"hw.logicalcpu", @ptrCast(*c_void, &count), &count_len, null, 0); const err = posix.getErrno(rc); switch (err) { 0 => return @intCast(usize, count), diff --git a/std/os/linux/index.zig b/std/os/linux/index.zig index 69bc30bad0..15607ea6c0 100644 --- a/std/os/linux/index.zig +++ b/std/os/linux/index.zig @@ -944,7 +944,7 @@ pub fn setgroups(size: usize, list: *const u32) usize { } pub fn getpid() i32 { - return @bitCast(i32, u32(syscall0(SYS_getpid))); + return @bitCast(i32, @truncate(u32, syscall0(SYS_getpid))); } pub fn sigprocmask(flags: u32, noalias set: *const sigset_t, noalias oldset: ?*sigset_t) usize { diff --git a/std/os/linux/test.zig b/std/os/linux/test.zig index e7dae3a584..4de26012c7 100644 --- a/std/os/linux/test.zig +++ b/std/os/linux/test.zig @@ -3,6 +3,10 @@ const builtin = @import("builtin"); const linux = std.os.linux; const assert = std.debug.assert; +test "getpid" { + assert(linux.getpid() != 0); +} + test "timer" { const epoll_fd = linux.epoll_create(); var err = linux.getErrno(epoll_fd); diff --git a/std/os/windows/advapi32.zig b/std/os/windows/advapi32.zig index dcb5a636ea..2f3195475c 100644 --- a/std/os/windows/advapi32.zig +++ b/std/os/windows/advapi32.zig @@ -28,3 +28,8 @@ pub extern "advapi32" stdcallcc fn RegOpenKeyExW(hKey: HKEY, lpSubKey: LPCWSTR, pub extern "advapi32" stdcallcc fn RegQueryValueExW(hKey: HKEY, lpValueName: LPCWSTR, lpReserved: LPDWORD, lpType: LPDWORD, lpData: LPBYTE, lpcbData: LPDWORD,) LSTATUS; + +// RtlGenRandom is known as SystemFunction036 under advapi32 +// http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx */ +pub extern "advapi32" stdcallcc fn SystemFunction036(output: [*]u8, length: usize) BOOL; +pub const RtlGenRandom = SystemFunction036; diff --git a/std/os/windows/util.zig b/std/os/windows/util.zig index dda9ce7a8b..c9d2c3c3e6 100644 --- a/std/os/windows/util.zig +++ b/std/os/windows/util.zig @@ -166,7 +166,7 @@ pub fn windowsUnloadDll(hModule: windows.HMODULE) void { } test "InvalidDll" { - if (builtin.os != builtin.Os.windows) return; + if (builtin.os != builtin.Os.windows) return error.SkipZigTest; const DllName = "asdf.dll"; const allocator = std.debug.global_allocator; diff --git a/std/rand/index.zig b/std/rand/index.zig index 7daa558f13..2cbff049ea 100644 --- a/std/rand/index.zig +++ b/std/rand/index.zig @@ -30,7 +30,7 @@ pub const DefaultCsprng = Isaac64; pub const Random = struct { fillFn: fn (r: *Random, buf: []u8) void, - /// Read random bytes into the specified buffer until fill. + /// Read random bytes into the specified buffer until full. pub fn bytes(r: *Random, buf: []u8) void { r.fillFn(r, buf); } @@ -48,10 +48,10 @@ pub const Random = struct { } } - /// Get a random unsigned integer with even distribution between `start` - /// inclusive and `end` exclusive. + /// Return a random integer with even distribution between `start` + /// inclusive and `end` exclusive. `start` must be less than `end`. pub fn range(r: *Random, comptime T: type, start: T, end: T) T { - assert(start <= end); + assert(start < end); if (T.is_signed) { const uint = @IntType(false, T.bit_count); if (start >= 0 and end >= 0) { @@ -664,6 +664,7 @@ test "Random range" { testRange(&prng.random, -4, 3); testRange(&prng.random, -4, -1); testRange(&prng.random, 10, 14); + // TODO: test that prng.random.range(1, 1) causes an assertion error } fn testRange(r: *Random, start: i32, end: i32) void { diff --git a/std/zig/ast.zig b/std/zig/ast.zig index 004f9278b9..95e899fb92 100644 --- a/std/zig/ast.zig +++ b/std/zig/ast.zig @@ -1778,19 +1778,12 @@ pub const Node = struct { pub const Suspend = struct { base: Node, - label: ?TokenIndex, suspend_token: TokenIndex, - payload: ?*Node, body: ?*Node, pub fn iterate(self: *Suspend, index: usize) ?*Node { var i = index; - if (self.payload) |payload| { - if (i < 1) return payload; - i -= 1; - } - if (self.body) |body| { if (i < 1) return body; i -= 1; @@ -1800,7 +1793,6 @@ pub const Node = struct { } pub fn firstToken(self: *Suspend) TokenIndex { - if (self.label) |label| return label; return self.suspend_token; } @@ -1809,10 +1801,6 @@ pub const Node = struct { return body.lastToken(); } - if (self.payload) |payload| { - return payload.lastToken(); - } - return self.suspend_token; } }; diff --git a/std/zig/parse.zig b/std/zig/parse.zig index 73d51e7870..fb49d2a2ba 100644 --- a/std/zig/parse.zig +++ b/std/zig/parse.zig @@ -852,19 +852,6 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { }) catch unreachable; continue; }, - Token.Id.Keyword_suspend => { - const node = try arena.create(ast.Node.Suspend{ - .base = ast.Node{ .id = ast.Node.Id.Suspend }, - .label = ctx.label, - .suspend_token = token_index, - .payload = null, - .body = null, - }); - ctx.opt_ctx.store(&node.base); - stack.append(State{ .SuspendBody = node }) catch unreachable; - try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.payload } }); - continue; - }, Token.Id.Keyword_inline => { stack.append(State{ .Inline = InlineCtx{ @@ -1415,10 +1402,21 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree { }, State.SuspendBody => |suspend_node| { - if (suspend_node.payload != null) { - try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .RequiredNull = &suspend_node.body } }); + const token = nextToken(&tok_it, &tree); + switch (token.ptr.id) { + Token.Id.Semicolon => { + prevToken(&tok_it, &tree); + continue; + }, + Token.Id.LBrace => { + prevToken(&tok_it, &tree); + try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .RequiredNull = &suspend_node.body } }); + continue; + }, + else => { + ((try tree.errors.addOne())).* = Error{ .InvalidToken = Error.InvalidToken{ .token = token.index } }; + }, } - continue; }, State.AsyncAllocator => |async_node| { if (eatToken(&tok_it, &tree, Token.Id.AngleBracketLeft) == null) { @@ -3086,15 +3084,12 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: *con Token.Id.Keyword_suspend => { const node = try arena.create(ast.Node.Suspend{ .base = ast.Node{ .id = ast.Node.Id.Suspend }, - .label = null, .suspend_token = token_index, - .payload = null, .body = null, }); ctx.store(&node.base); stack.append(State{ .SuspendBody = node }) catch unreachable; - try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.payload } }); return true; }, Token.Id.Keyword_if => { diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 21259bec3c..582bffdf3d 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -898,11 +898,11 @@ test "zig fmt: union(enum(u32)) with assigned enum values" { ); } -test "zig fmt: labeled suspend" { +test "zig fmt: resume from suspend block" { try testCanonical( \\fn foo() void { - \\ s: suspend |p| { - \\ break :s; + \\ suspend { + \\ resume @handle(); \\ } \\} \\ @@ -1784,7 +1784,7 @@ test "zig fmt: coroutines" { \\ x += 1; \\ suspend; \\ x += 1; - \\ suspend |p| {} + \\ suspend; \\ const p: promise->void = async simpleAsyncFn() catch unreachable; \\ await p; \\} diff --git a/std/zig/render.zig b/std/zig/render.zig index bc45768fa3..868902a0d1 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -323,21 +323,7 @@ fn renderExpression( ast.Node.Id.Suspend => { const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base); - if (suspend_node.label) |label| { - try renderToken(tree, stream, label, indent, start_col, Space.None); - try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space); - } - - if (suspend_node.payload) |payload| { - if (suspend_node.body) |body| { - try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space); - try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space); - return renderExpression(allocator, stream, tree, indent, start_col, body, space); - } else { - try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space); - return renderExpression(allocator, stream, tree, indent, start_col, payload, space); - } - } else if (suspend_node.body) |body| { + if (suspend_node.body) |body| { try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space); return renderExpression(allocator, stream, tree, indent, start_col, body, space); } else { |
