Skip to content

Commit

Permalink
Merge pull request #14 from Aandreba/release-unwrap
Browse files Browse the repository at this point in the history
Deprecate `releaseWithFn` in favor of `releaseUnwrap`
  • Loading branch information
Aandreba authored Sep 3, 2024
2 parents 6d9c545 + 9b9c57b commit cc47722
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 89 deletions.
1 change: 1 addition & 0 deletions Justfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
coverage: clean
rm -rf kcov-out
zig build test -Doptimize=Debug
kcov --include-pattern=src/root.zig,src/tests.zig kcov-out zig-cache/o/**/test

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ test "example" {
std.debug.print("Heap align: {}\n\n", .{Arc.innerAlign()});
var value = try Arc.init(std.testing.allocator, .{});
errdefer value.releaseWithFn(Data.deinit, .{});
errdefer if (value.releaseUnwrap()) |val| val.deinit();
var handles: [THREADS]Thread = undefined;
var i: usize = 0;
while (i < THREADS) {
const this_value = value.retain();
errdefer this_value.releaseWithFn(Data.deinit, .{});
errdefer if (this_value.releaseUnwrap()) |val| val.deinit();
handles[i] = try Thread.spawn(.{}, thread_exec, .{this_value});
i += 1;
}
Expand All @@ -86,7 +86,7 @@ test "example" {
}
fn thread_exec(data: Arc) !void {
defer data.releaseWithFn(Data.deinit, .{});
defer if (data.releaseUnwrap()) |val| val.deinit();
var rng = std.rand.DefaultPrng.init(@as(u64, @bitCast(@as(i64, @truncate(std.time.nanoTimestamp())))));
Expand Down
49 changes: 0 additions & 49 deletions build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,56 +1,7 @@
.{
.name = "zigrc",
// This is a [Semantic Version](https://semver.org/).
// In a future version of Zig it will be used for package deduplication.
.version = "0.5.0",

// This field is optional.
// This is currently advisory only; Zig does not yet do anything
// with this value.
.minimum_zig_version = "0.12.0",

// This field is optional.
// Each dependency must either provide a `url` and `hash`, or a `path`.
// `zig build --fetch` can be used to fetch all dependencies of a package, recursively.
// Once all dependencies are fetched, `zig build` no longer requires
// internet connectivity.
.dependencies = .{
// See `zig fetch --save <url>` for a command-line interface for adding dependencies.
//.example = .{
// // When updating this field to a new URL, be sure to delete the corresponding
// // `hash`, otherwise you are communicating that you expect to find the old hash at
// // the new URL.
// .url = "https://example.com/foo.tar.gz",
//
// // This is computed from the file contents of the directory of files that is
// // obtained after fetching `url` and applying the inclusion rules given by
// // `paths`.
// //
// // This field is the source of truth; packages do not come from a `url`; they
// // come from a `hash`. `url` is just one of many possible mirrors for how to
// // obtain a package matching this `hash`.
// //
// // Uses the [multihash](https://multiformats.io/multihash/) format.
// .hash = "...",
//
// // When this is provided, the package is found in a directory relative to the
// // build root. In this case the package's hash is irrelevant and therefore not
// // computed. This field and `url` are mutually exclusive.
// .path = "foo",

// // When this is set to `true`, a package is declared to be lazily
// // fetched. This makes the dependency only get fetched if it is
// // actually used.
// .lazy = false,
//},
},

// Specifies the set of files and directories that are included in this package.
// Only files and directories listed here are included in the `hash` that
// is computed for this package.
// Paths are relative to the build root. Use the empty string (`""`) to refer to
// the build root itself.
// A directory listed here means that all files within, recursively, are included.
.paths = .{
"build.zig",
"build.zig.zon",
Expand Down
79 changes: 44 additions & 35 deletions src/root.zig
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,11 @@ pub fn RcAligned(comptime T: type, comptime alignment: ?u29) type {
return self.asUnmanaged().release(self.alloc);
}

/// Decrements the reference count, deallocating the weak count reaches zero,
/// and executing `f` if the strong count reaches zero.
/// The `f` function has a signature of `fn(*T, ...args)` or `fn(T, ...args)`.
/// The continued use of the pointer after calling `release` is undefined behaviour.
pub fn releaseWithFn(self: Self, comptime f: anytype, args: anytype) void {
return self.asUnmanaged().releaseWithFn(self.alloc, f, args);
/// Decrements the reference count, deallocating if the weak count reaches zero,
/// and returning the underlying value if the strong count reaches zero.
/// The continued use of the pointer after calling this method is undefined behaviour.
pub fn releaseUnwrap(self: Self) ?T {
return self.asUnmanaged().releaseUnwrap(self.alloc);
}

/// Returns the inner value, if the `Rc` has exactly one strong reference.
Expand All @@ -99,6 +98,11 @@ pub fn RcAligned(comptime T: type, comptime alignment: ?u29) type {
return self.asUnmanaged().tryUnwrap(self.alloc);
}

/// DEPRECATED: Use `releaseUnwrap` instead. Will be removed in the next major release.
pub fn releaseWithFn(self: Self, comptime f: anytype, args: anytype) void {
self.asUnmanaged().releaseWithFn(self.alloc, f, args);
}

/// Total size (in bytes) of the reference counted value on the heap.
/// This value accounts for the extra memory required to count the references.
pub fn innerSize() comptime_int {
Expand Down Expand Up @@ -289,12 +293,16 @@ pub fn ArcAligned(comptime T: type, comptime alignment: ?u29) type {
return self.asUnmanaged().release(self.alloc);
}

/// Decrements the reference count, deallocating the weak count reaches zero,
/// and executing `f` if the strong count reaches zero.
/// The `f` function has a signature of `fn(*T, ...args)` or `fn(T, ...args)`.
/// The continued use of the pointer after calling `release` is undefined behaviour.
/// Decrements the reference count, deallocating if the weak count reaches zero,
/// and returning the underlying value if the strong count reaches zero.
/// The continued use of the pointer after calling this method is undefined behaviour.
pub fn releaseUnwrap(self: Self) ?T {
return self.asUnmanaged().releaseUnwrap(self.alloc);
}

/// DEPRECATED: Use `releaseUnwrap` instead. Will be removed in the next major release.
pub fn releaseWithFn(self: Self, comptime f: anytype, args: anytype) void {
return self.asUnmanaged().releaseWithFn(self.alloc, f, args);
self.asUnmanaged().releaseWithFn(self.alloc, f, args);
}

/// Returns the inner value, if the `Arc` has exactly one strong reference.
Expand Down Expand Up @@ -517,26 +525,28 @@ pub fn RcAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) type {
}
}

/// Decrements the reference count, deallocating the weak count reaches zero,
/// and executing `f` if the strong count reaches zero.
/// The `f` function has a signature of `fn(*T, ...args)` or `fn(T, ...args)`.
/// The continued use of the pointer after calling `release` is undefined behaviour.
pub fn releaseWithFn(self: Self, allocator: Allocator, comptime f: anytype, args: anytype) void {
/// Decrements the reference count, deallocating if the weak count reaches zero,
/// and returning the underlying value if the strong count reaches zero.
/// The continued use of the pointer after calling this method is undefined behaviour.
pub fn releaseUnwrap(self: Self, allocator: Allocator) ?T {
const ptr = self.innerPtr();

ptr.strong -= 1;
if (ptr.strong == 0) {
if (comptime @typeInfo(@TypeOf(f)).Fn.params[0].type == T) {
@call(.auto, f, .{self.value.*} ++ args);
} else {
@call(.auto, f, .{self.value} ++ args);
}

const value = self.value.*;
ptr.weak -= 1;
if (ptr.weak == 0) {
allocator.destroy(ptr);
}
return value;
}

return null;
}

/// DEPRECATED: Use `releaseUnwrap` instead. Will be removed in the next major release.
pub fn releaseWithFn(_: Self, _: Allocator, comptime _: anytype, _: anytype) void {
@compileError("DEPRECATED: Use `releaseUnwrap` instead. Will be removed in the next major release.");
}

/// Returns the inner value, if the `Rc` has exactly one strong reference.
Expand Down Expand Up @@ -757,32 +767,31 @@ pub fn ArcAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) type {
/// The continued use of the pointer after calling `release` is undefined behaviour.
pub fn release(self: Self, allocator: Allocator) void {
const ptr = self.innerPtr();

if (@atomicRmw(usize, &ptr.strong, .Sub, 1, .acq_rel) == 1) {
if (@atomicRmw(usize, &ptr.weak, .Sub, 1, .acq_rel) == 1) {
allocator.destroy(ptr);
}
}
}

/// Decrements the reference count, deallocating the weak count reaches zero,
/// and executing `f` if the strong count reaches zero.
/// The `f` function has a signature of `fn(*T, ...args)` or `fn(T, ...args)`.
/// The continued use of the pointer after calling `release` is undefined behaviour.
pub fn releaseWithFn(self: Self, allocator: Allocator, comptime f: anytype, args: anytype) void {
/// Decrements the reference count, deallocating if the weak count reaches zero,
/// and returning the underlying value if the strong count reaches zero.
/// The continued use of the pointer after calling this method is undefined behaviour.
pub fn releaseUnwrap(self: Self, allocator: Allocator) ?T {
const ptr = self.innerPtr();

if (@atomicRmw(usize, &ptr.strong, .Sub, 1, .acq_rel) == 1) {
if (comptime @typeInfo(@TypeOf(f)).Fn.params[0].type == T) {
@call(.auto, f, .{self.value.*} ++ args);
} else {
@call(.auto, f, .{self.value} ++ args);
}

const value = self.value.*;
if (@atomicRmw(usize, &ptr.weak, .Sub, 1, .acq_rel) == 1) {
allocator.destroy(ptr);
}
return value;
}
return null;
}

/// DEPRECATED: Use `releaseUnwrap` instead. Will be removed in the next major release.
pub fn releaseWithFn(_: Self, _: Allocator, comptime _: anytype, _: anytype) void {
@compileError("DEPRECATED: Use `releaseUnwrap` instead. Will be removed in the next major release.");
}

/// Returns the inner value, if the `Arc` has exactly one strong reference.
Expand Down
4 changes: 2 additions & 2 deletions src/tests.zig
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ test "cyclic" {
};

var gadget = try Gadget.init(alloc);
defer gadget.releaseWithFn(Gadget.deinit, .{});
defer if (gadget.releaseUnwrap()) |val| val.deinit();

try expect(gadget.strongCount() == 1);
try expect(gadget.weakCount() == 1);
Expand Down Expand Up @@ -166,7 +166,7 @@ test "cyclic atomic" {
};

var gadget = try Gadget.init(alloc);
defer gadget.releaseWithFn(Gadget.deinit, .{});
defer if (gadget.releaseUnwrap()) |val| val.deinit();

try expect(gadget.strongCount() == 1);
try expect(gadget.weakCount() == 1);
Expand Down

0 comments on commit cc47722

Please sign in to comment.