zig-memutils
所属分类:编程语言基础
开发工具:Zig
文件大小:0KB
下载次数:0
上传日期:2023-07-23 17:31:32
上 传 者:
sh-1993
说明: Zig编程语言的内存实用程序,包括引用计数指针,
(Memory utilities for the Zig programming language, including a reference counted pointer,)
文件列表:
LICENSE (16725, 2023-11-26)
build.zig (767, 2023-11-26)
build.zig.zon (178, 2023-11-26)
src/ (0, 2023-11-26)
src/memutils.zig (1740, 2023-11-26)
src/meta.zig (935, 2023-11-26)
src/rc.zig (4658, 2023-11-26)
# zig-memutils
Memory utilities for the Zig programming language, including a reference counted pointer
This repository contains a few usable patterns for memory management
in Zig.
## Owner and Borrower
Owners and Borrowers allow you to specify the ownership of data
(usually a pointer or a structure with `deinit`). As in Zig there are
no in language semantics to make this clear. For example the
`std.StringHashMap` does not own its keys.
In Owner-Borrower memory model would signatures of some functions look
like this:
```zig
// instead of
fn put(self: *Self, key: []const u8, value: V) !void
// this
fn put(self: *Self, key: Borrower([]const u8), value: V) !void
```
To get most of the features of this model, one should always pair an
`Owner` instance with its respective `deinit()`
```zig
var owner: Owner(usize) = .{ .data = 0 };
defer owner.deinit();
some_fn_borrowing(owner.borrow());
some_fn_owning(owner.give());
// this is an error, as ownership was already transfered
// some_fn_owning(owner.give());
```
`Borrower` instances are only informative about the API, they do not
themselves need to be deinitialized and do not perform any checks
about their validity.
## Rc the reference counted pointer
Rc allows to hold multiple references to a place in memory when there
is no easy way to make sure that that memory isn't pointed to from
anywhere else. It's a very standard datastructure in many programming
languages. But this implementation provides a few interesting
properties.
Unless a slice is provided, one should pass the type that the memory
location should have __not the pointer to that memory!__
```zig
var rc = Rc(usize).init(0, std.testing.allocator);
defer rc.drop();
const raw_ptr: *usize = rc.get();
```
If the type has a `fn deinit(*T)` or a `fn deinit(*T,
std.mem.Allocator)` member function, the `Rc` will automatically call
this function before destroying it's memory location.
A custom deinit function can also be provided with `init_w_deinit_fn`,
and must have the `*const fn (*T, std.mem.Allocator)` type signature.
For a propper usage, `Rc` should never be "copy assigned", but that is
currently unenforcable in Zig.
```zig
var rc = Rc(usize).init(0, std.testing.allocator);
defer rc.drop();
// never do this
var rc2 = rc;
// instead do this
var rc3 = rc.borrow();
defer rc3.drop();
```
### Rc with a slice
If one wishes to use `Rc` with a slice, the semantics are a bit
different. The biggest difference is that `Rc` now expects the slice
as it's argument instead of the item's type.
```zig
var rc = Rc([]u8).init_dupe("string", std.testing.allocator);
defer rc.drop();
var rc2 = Rc([]u8).init(6, std.testing.allocator);
defer rc2.drop();
@memcpy(rc2.get(), "string");
```
Otherwise `Rc` behaves the same. However slices usually provide a way
to subslice, but simply doing `rc.get()[0..3]` would not increase the
reference count. For this `Rc` implements `fn subslice(from, to)`.
This does not copy memory, only creates a new `Rc` that still works
with the same memory location, will potentially free the whole memory
if no references to the memory exist, but returns a different slice when
calling `get`.
```zig
var rc = Rc([]u8).init_dupe("test", std.testing.allocator);
defer rc.drop();
var rc2 = rc.subslice(0, 3);
defer rc2.drop();
```
### Rc in multithreaded environments
Rc can be also used in multithreaded environments in a way that does
not introduce a cost in single threaded environments. To convert `Rc`
into an multithreading friendly one, simply call `fn atomic()`. The
type signature stays the same and all functions have the same
behavior, but `borrow` and `drop` are now thread-safe.
> Note that this operation can only be performed once.
```zig
var rc = Rc(usize).init(0, std.testing.allocator);
defer rc.drop();
rc.atomic();
// from now on, rc is thread-safe, even the previous borrows
```
近期下载者:
相关文件:
收藏者: