An open API service indexing awesome lists of open source software.

https://github.com/peter-barrow/shared-memory-zig

Unified interface to shared memory on Linux, macOS and Windows
https://github.com/peter-barrow/shared-memory-zig

shared-memory zig zig-package

Last synced: 8 days ago
JSON representation

Unified interface to shared memory on Linux, macOS and Windows

Awesome Lists containing this project

README

          

# Shared Memory Zig

**Overview**

This library implements a unified interface to shared memory on Linux, macOS and Windows

## Features

- Cross-platform support (Linux, FreeBSD, Windows)
- Multiple implementation strategies (memfd, POSIX shm, Windows file mapping)
- Type-safe shared memory segments
- Automatic memory layout management with headers
- Built-in existence checking

## Installation
Add the following to you `build.zig.zon`, replacing the url with the latest archive, for example `https://github.com/Peter-Barrow/shared-memory-zig/archive/699c748fbb143733183760cc7e83ded098eac6d1.zip` and then replacing the hash with the latest commit hash.
``` zig
.{
.name = "my-project",
.version = "0.0.0",
.dependencies = .{
.shared_memory = .{
.url = "",
.hash = "",
},
},
}
```
Or alternatively run:
``` shell
zig fetch --save git+https://github.com/Peter-Barrow/shared-memory-zig.git
```

Add the following to your `build.zig`
``` zig
const shared_memory = b.dependency("shared_memory", .{}).module("shared_memory");
const exe = b.addExecutable(...);
// This adds the shared-memory-zig module to the executable which can then be imported with `@import("shared-memory-zig")`
exe.root_module.addImport("shared-memory-zig", shared_memory);
```

## Dependencies
For compatibility with Windows this requires [zigwin32](https://github.com/marlersoft/zigwin32)
This codebase also uses the [known-folders](https://github.com/ziglibs/known-folders/tree/master) library to get the runtime directory on Linux and FreeBSD when using the `memfd` backend.

## Example
### Create a shared struct
``` zig
const shm = @import("shared_memory");

const TestStruct = struct {
x: i32,
y: f64,
};
const SharedStruct = SharedMemory(TestStruct);

const shm_name = "test_single_struct";

var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();

const alloca = std.testing.allocator;
const io = std.testing.io;

var b: shm.DefaultBackend = .{};
const backend = b.backend();

var shm: SharedStruct = try shm.SharedStruct.create(
shm_name,
tmp.dir,
backend,
io,
alloca,
);
defer shm.close();

shm.data.* = .{ .x = 42, .y = 3.14 };

// Open the shared memory in another "process"
var shm2 = try SharedStruct.open(
shm_name,
tmp.dir,
backend,
);
defer shm2.close();

try std.testing.expectEqual(@as(i32, 42), shm2.data.x);
try std.testing.expectApproxEqAbs(@as(f64, 3.14), shm2.data.y, 0.001);
```

### Create a shared array of comptime known length
``` zig
const shm = @import("shared_memory");

const array_size = 20;
var expected = [_]i32{0} ** array_size;
for (0..array_size) |i| {
expected[i] = @intCast(i * 2);
}

const alloca = std.testing.allocator;
var io_threaded: std.Io.Threaded = .init(alloca, .{});
const io = io_threaded.io();

const shm_name = "test_array_fixed_length";

var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();

var b: shm.DefaultBackend = .{};
const backend = b.backend();

const SharedI32 = shm.SharedMemory([array_size]i32);

var shm: SharedI32 = try SharedI32.create(
shm_name,
tmp.dir,
backend,
io,
alloca,
);
defer shm.close();

for (shm.data, 0..) |*item, i| {
item.* = @intCast(i * 2);
}

// Open the shared memory in another "process"
var shm2 = try SharedI32.open(shm_name, tmp.dir, backend);
defer shm2.close();

for (shm2.data, 0..) |item, i| {
try std.testing.expectEqual(@as(i32, @intCast(i * 2)), item);
}
try std.testing.expectEqualSlices(i32, &expected, shm2.data);
```

### Create an array with runtime known length
``` zig
const shm = @import("shared_memory");

const array_size = 20;
var expected = [_]i32{0} ** array_size;
for (0..array_size) |i| {
expected[i] = @intCast(i * 2);
}

const alloca = std.testing.allocator;
var io_threaded: std.Io.Threaded = .init(alloca, .{});
const io = io_threaded.io();

const shm_name = "test_array_runtime_length";

var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();

if (use_shm_funcs) posixForceClose(shm_name);

var b: shm.DefaultBackend = .{};
const backend = b.backend();

const SharedI32 = shm.SharedMemory([]i32);

var shm: SharedI32 = try SharedI32.createCapacity(
shm_name,
tmp.dir,
array_size,
backend,
io,
alloca,
);
defer shm.close();

for (shm.data, 0..) |*item, i| {
item.* = @intCast(i * 2);
}

// Open the shared memory in another "process"
var shm2 = try SharedI32.open(shm_name, tmp.dir, backend);
defer shm2.close();

//for (shm2.data, 0..) |item, i| {
for (0..array_size) |i| {
try std.testing.expectEqual(@as(i32, @intCast(i * 2)), shm2.data[i]);
}
try std.testing.expectEqualSlices(i32, &expected, shm2.data[0..array_size]);
```