Skip to content

Commit

Permalink
Extract
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchellh committed Feb 6, 2023
1 parent fdcbe00 commit 830f635
Show file tree
Hide file tree
Showing 23 changed files with 22,239 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
zig-cache/
zig-out/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "vendor/libuv"]
path = vendor/libuv
url = https://github.com/libuv/libuv.git
177 changes: 177 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
const std = @import("std");

/// Directories with our includes.
const root = thisDir() ++ "/vendor/libuv/";
const include_path = root ++ "include";

pub const pkg = std.build.Pkg{
.name = "libuv",
.source = .{ .path = thisDir() ++ "/src/main.zig" },
};

fn thisDir() []const u8 {
return std.fs.path.dirname(@src().file) orelse ".";
}

pub fn build(b: *std.build.Builder) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});

const tests = b.addTest(.{
.name = "pixman-test",
.kind = .test_exe,
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
_ = try link(b, tests);
tests.install();

const test_step = b.step("test", "Run tests");
const tests_run = tests.run();
test_step.dependOn(&tests_run.step);
}

pub fn link(b: *std.build.Builder, step: *std.build.LibExeObjStep) !*std.build.LibExeObjStep {
const libuv = try buildLibuv(b, step);
step.linkLibrary(libuv);
step.addIncludePath(include_path);
return libuv;
}

pub fn buildLibuv(
b: *std.build.Builder,
step: *std.build.LibExeObjStep,
) !*std.build.LibExeObjStep {
const target = step.target;
const lib = b.addStaticLibrary(.{
.name = "uv",
.target = target,
.optimize = step.optimize,
});

// Include dirs
lib.addIncludePath(include_path);
lib.addIncludePath(root ++ "src");

// Links
if (target.isWindows()) {
lib.linkSystemLibrary("psapi");
lib.linkSystemLibrary("user32");
lib.linkSystemLibrary("advapi32");
lib.linkSystemLibrary("iphlpapi");
lib.linkSystemLibrary("userenv");
lib.linkSystemLibrary("ws2_32");
}
if (target.isLinux()) {
lib.linkSystemLibrary("pthread");
}
lib.linkLibC();

// Compilation
var flags = std.ArrayList([]const u8).init(b.allocator);
defer flags.deinit();
// try flags.appendSlice(&.{});

if (!target.isWindows()) {
try flags.appendSlice(&.{
"-D_FILE_OFFSET_BITS=64",
"-D_LARGEFILE_SOURCE",
});
}

if (target.isLinux()) {
try flags.appendSlice(&.{
"-D_GNU_SOURCE",
"-D_POSIX_C_SOURCE=200112",
});
}

if (target.isDarwin()) {
try flags.appendSlice(&.{
"-D_DARWIN_UNLIMITED_SELECT=1",
"-D_DARWIN_USE_64_BIT_INODE=1",
});
}

// C files common to all platforms
lib.addCSourceFiles(&.{
root ++ "src/fs-poll.c",
root ++ "src/idna.c",
root ++ "src/inet.c",
root ++ "src/random.c",
root ++ "src/strscpy.c",
root ++ "src/strtok.c",
root ++ "src/threadpool.c",
root ++ "src/timer.c",
root ++ "src/uv-common.c",
root ++ "src/uv-data-getter-setters.c",
root ++ "src/version.c",
}, flags.items);

if (!target.isWindows()) {
lib.addCSourceFiles(&.{
root ++ "src/unix/async.c",
root ++ "src/unix/core.c",
root ++ "src/unix/dl.c",
root ++ "src/unix/fs.c",
root ++ "src/unix/getaddrinfo.c",
root ++ "src/unix/getnameinfo.c",
root ++ "src/unix/loop-watcher.c",
root ++ "src/unix/loop.c",
root ++ "src/unix/pipe.c",
root ++ "src/unix/poll.c",
root ++ "src/unix/process.c",
root ++ "src/unix/random-devurandom.c",
root ++ "src/unix/signal.c",
root ++ "src/unix/stream.c",
root ++ "src/unix/tcp.c",
root ++ "src/unix/thread.c",
root ++ "src/unix/tty.c",
root ++ "src/unix/udp.c",
}, flags.items);
}

if (target.isLinux() or target.isDarwin()) {
lib.addCSourceFiles(&.{
root ++ "src/unix/proctitle.c",
}, flags.items);
}

if (target.isLinux()) {
lib.addCSourceFiles(&.{
root ++ "src/unix/linux.c",
root ++ "src/unix/procfs-exepath.c",
root ++ "src/unix/random-getrandom.c",
root ++ "src/unix/random-sysctl-linux.c",
}, flags.items);
}

if (target.isDarwin() or
target.isOpenBSD() or
target.isNetBSD() or
target.isFreeBSD() or
target.isDragonFlyBSD())
{
lib.addCSourceFiles(&.{
root ++ "src/unix/bsd-ifaddrs.c",
root ++ "src/unix/kqueue.c",
}, flags.items);
}

if (target.isDarwin() or target.isOpenBSD()) {
lib.addCSourceFiles(&.{
root ++ "src/unix/random-getentropy.c",
}, flags.items);
}

if (target.isDarwin()) {
lib.addCSourceFiles(&.{
root ++ "src/unix/darwin-proctitle.c",
root ++ "src/unix/darwin.c",
root ++ "src/unix/fsevents.c",
}, flags.items);
}

return lib;
}
54 changes: 54 additions & 0 deletions src/Async.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//! Async handles allow the user to “wakeup” the event loop and get a callback
//! called from another thread.
const Async = @This();

const std = @import("std");
const Allocator = std.mem.Allocator;
const testing = std.testing;
const c = @import("c.zig");
const errors = @import("error.zig");
const Loop = @import("Loop.zig");
const Handle = @import("handle.zig").Handle;

handle: *c.uv_async_t,

pub usingnamespace Handle(Async);

pub fn init(alloc: Allocator, loop: Loop, comptime cb: fn (*Async) void) !Async {
var handle = try alloc.create(c.uv_async_t);
errdefer alloc.destroy(handle);

const Wrapper = struct {
pub fn callback(arg: [*c]c.uv_async_t) callconv(.C) void {
var newSelf: Async = .{ .handle = arg };
@call(.always_inline, cb, .{&newSelf});
}
};

try errors.convertError(c.uv_async_init(loop.loop, handle, Wrapper.callback));
return Async{ .handle = handle };
}

pub fn deinit(self: *Async, alloc: Allocator) void {
alloc.destroy(self.handle);
self.* = undefined;
}

/// Wake up the event loop and call the async handle’s callback.
pub fn send(self: Async) !void {
try errors.convertError(c.uv_async_send(self.handle));
}

test "Async" {
var loop = try Loop.init(testing.allocator);
defer loop.deinit(testing.allocator);
var h = try init(testing.allocator, loop, (struct {
fn callback(v: *Async) void {
v.close(null);
}
}).callback);
defer h.deinit(testing.allocator);

try h.send();
_ = try loop.run(.default);
}
44 changes: 44 additions & 0 deletions src/Cond.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//! Condition variables implemented via libuv.
const Cond = @This();

const std = @import("std");
const Allocator = std.mem.Allocator;
const testing = std.testing;
const c = @import("c.zig");
const errors = @import("error.zig");
const Mutex = @import("Mutex.zig");

cond: *c.uv_cond_t,

pub fn init(alloc: Allocator) !Cond {
const cond = try alloc.create(c.uv_cond_t);
try errors.convertError(c.uv_cond_init(cond));
return Cond{ .cond = cond };
}

pub fn deinit(self: *Cond, alloc: Allocator) void {
c.uv_cond_destroy(self.cond);
alloc.destroy(self.cond);
self.* = undefined;
}

pub fn signal(self: Cond) void {
c.uv_cond_signal(self.cond);
}

pub fn broadcast(self: Cond) void {
c.uv_cond_broadcast(self.cond);
}

pub fn wait(self: Cond, mutex: Mutex) void {
c.uv_cond_wait(self.cond, mutex.mutex);
}

pub fn timedwait(self: Cond, mutex: Mutex, timeout: u64) c_int {
return c.uv_cond_timedwait(self.cond, mutex.mutex, timeout);
}

test {
var cond = try init(testing.allocator);
defer cond.deinit(testing.allocator);
}
66 changes: 66 additions & 0 deletions src/Idle.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//! Idle handles will run the given callback once per loop iteration, right
//! before the uv_prepare_t handles.
const Idle = @This();

const std = @import("std");
const Allocator = std.mem.Allocator;
const testing = std.testing;
const c = @import("c.zig");
const errors = @import("error.zig");
const Loop = @import("Loop.zig");
const Handle = @import("handle.zig").Handle;

handle: *c.uv_idle_t,

pub usingnamespace Handle(Idle);

pub fn init(alloc: Allocator, loop: Loop) !Idle {
var handle = try alloc.create(c.uv_idle_t);
errdefer alloc.destroy(handle);

try errors.convertError(c.uv_idle_init(loop.loop, handle));
return Idle{ .handle = handle };
}

pub fn deinit(self: *Idle, alloc: Allocator) void {
alloc.destroy(self.handle);
self.* = undefined;
}

/// Start the handle with the given callback. This function always succeeds,
/// except when cb is NULL.
pub fn start(self: Idle, comptime cb: fn (*Idle) void) !void {
const Wrapper = struct {
pub fn callback(arg: [*c]c.uv_idle_t) callconv(.C) void {
var newSelf: Idle = .{ .handle = arg };
@call(.always_inline, cb, .{&newSelf});
}
};

try errors.convertError(c.uv_idle_start(self.handle, Wrapper.callback));
}

/// Stop the handle, the callback will no longer be called.
pub fn stop(self: Idle) !void {
try errors.convertError(c.uv_idle_stop(self.handle));
}

test "Idle" {
var loop = try Loop.init(testing.allocator);
defer loop.deinit(testing.allocator);
var h = try init(testing.allocator, loop);
defer h.deinit(testing.allocator);

var called: bool = false;
h.setData(&called);
try h.start((struct {
fn callback(t: *Idle) void {
t.getData(bool).?.* = true;
t.close(null);
}
}).callback);

_ = try loop.run(.default);

try testing.expect(called);
}
Loading

0 comments on commit 830f635

Please sign in to comment.