-
-
Notifications
You must be signed in to change notification settings - Fork 892
Add AllocationTrackedMemoryManager and refactor allocators #3120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 11 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
523aacd
Add AllocationTrackedMemoryManager and refactor allocators
JimBobSquarePants 631b64e
Add AllocationTrackingState and refactor tracking
JimBobSquarePants 15fd941
Cleanup
JimBobSquarePants 214882f
Merge branch 'main' into js/optimize-allocation-tracking
JimBobSquarePants 2c0faf6
Merge branch 'main' into js/optimize-allocation-tracking
JimBobSquarePants 88acf75
Address feedback
JimBobSquarePants 2beb01b
Introduce ApplyOptions and use in allocators
JimBobSquarePants 66bd3ec
Merge branch 'main' into js/optimize-allocation-tracking
JimBobSquarePants 323289a
Propagate allocation tracking to lifetime guards
JimBobSquarePants afc97df
Address Copilot feedback
JimBobSquarePants 23b312c
Fix multi-buffer group tracking and enforce limits
JimBobSquarePants 04bac15
Potential fix for pull request finding
JimBobSquarePants 5e5b88c
Fix override accesibility
JimBobSquarePants File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
67 changes: 67 additions & 0 deletions
67
src/ImageSharp/Memory/AllocationTrackedMemoryManager{T}.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| // Copyright (c) Six Labors. | ||
| // Licensed under the Six Labors Split License. | ||
|
|
||
| using System.Buffers; | ||
|
|
||
| namespace SixLabors.ImageSharp.Memory; | ||
|
|
||
| /// <summary> | ||
| /// Provides the tracked memory-owner contract required by <see cref="MemoryAllocator"/>. | ||
| /// </summary> | ||
| /// <typeparam name="T">The element type.</typeparam> | ||
| /// <remarks> | ||
| /// Custom allocators implement <see cref="MemoryAllocator.AllocateCore{T}(int, AllocationOptions)"/> | ||
| /// and return a derived type. The base allocator attaches allocation tracking after the owner has been | ||
| /// created so custom implementations cannot forget, duplicate, or mismatch the reservation lifecycle. | ||
| /// </remarks> | ||
| public abstract class AllocationTrackedMemoryManager<T> : MemoryManager<T> | ||
| where T : struct | ||
| { | ||
| private AllocationTrackingState allocationTracking; | ||
|
|
||
| /// <summary> | ||
| /// Releases resources held by the concrete tracked owner. | ||
| /// </summary> | ||
| /// <param name="disposing"> | ||
| /// <see langword="true"/> when the owner is being disposed deterministically; | ||
| /// otherwise, <see langword="false"/>. | ||
| /// </param> | ||
| /// <remarks> | ||
| /// Implementations release their own resources here. Allocation tracking is released by the sealed base | ||
| /// dispose path after this method returns. | ||
| /// </remarks> | ||
| protected abstract void DisposeCore(bool disposing); | ||
|
|
||
| /// <inheritdoc /> | ||
| protected sealed override void Dispose(bool disposing) | ||
| { | ||
| try | ||
| { | ||
| this.DisposeCore(disposing); | ||
| } | ||
| finally | ||
| { | ||
| this.ReleaseAllocationTracking(); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Attaches allocation tracking to this owner after allocation has succeeded. | ||
| /// </summary> | ||
| /// <param name="allocator">The allocator that owns the reservation for this instance.</param> | ||
| /// <param name="lengthInBytes">The reserved allocation size, in bytes.</param> | ||
| /// <remarks> | ||
| /// <see cref="MemoryAllocator"/> calls this exactly once after <c>AllocateCore</c> returns. | ||
| /// Derived allocators should not call it themselves; they only construct the concrete owner. | ||
| /// </remarks> | ||
| internal virtual void AttachAllocationTracking(MemoryAllocator allocator, long lengthInBytes) | ||
| => this.allocationTracking.Attach(allocator, lengthInBytes); | ||
|
|
||
| /// <summary> | ||
| /// Releases any tracked allocation bytes associated with this instance. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// Calling this more than once is safe; only the first call after tracking has been attached releases bytes. | ||
| /// </remarks> | ||
| private void ReleaseAllocationTracking() => this.allocationTracking.Release(); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| // Copyright (c) Six Labors. | ||
| // Licensed under the Six Labors Split License. | ||
|
|
||
| namespace SixLabors.ImageSharp.Memory; | ||
|
|
||
| /// <summary> | ||
| /// Tracks a single allocator reservation and releases it exactly once. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// This type is intended to live as a mutable field on the owning object. It should not be copied | ||
| /// after tracking has been attached, because the owner relies on a single shared release state. | ||
| /// </remarks> | ||
| internal struct AllocationTrackingState | ||
| { | ||
| private MemoryAllocator? allocator; | ||
| private long lengthInBytes; | ||
| private int released; | ||
|
|
||
| /// <summary> | ||
| /// Attaches allocator reservation tracking to the current owner. | ||
| /// </summary> | ||
| /// <param name="allocator">The allocator that owns the reservation.</param> | ||
| /// <param name="lengthInBytes">The reserved allocation size, in bytes.</param> | ||
| /// <remarks> | ||
| /// Must complete-before the owning object's reference is observable to any other thread. | ||
| /// <see cref="MemoryAllocator"/> guarantees this by attaching synchronously on the allocating | ||
| /// thread before returning the owner; reference publication then provides the release fence | ||
| /// that makes these field writes visible to a subsequent <see cref="Release"/> on another thread. | ||
| /// </remarks> | ||
| internal void Attach(MemoryAllocator allocator, long lengthInBytes) | ||
| { | ||
| this.allocator = allocator; | ||
| this.lengthInBytes = lengthInBytes; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Releases the attached allocator reservation once. | ||
| /// </summary> | ||
| internal void Release() | ||
| { | ||
| if (Interlocked.Exchange(ref this.released, 1) == 0 && this.allocator != null) | ||
| { | ||
| this.allocator.ReleaseAccumulatedBytes(this.lengthInBytes); | ||
| this.allocator = null; | ||
| } | ||
| } | ||
| } |
14 changes: 12 additions & 2 deletions
14
src/ImageSharp/Memory/Allocators/AllocationOptionsExtensions.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,19 @@ | ||
| // Copyright (c) Six Labors. | ||
| // Copyright (c) Six Labors. | ||
| // Licensed under the Six Labors Split License. | ||
|
|
||
| namespace SixLabors.ImageSharp.Memory; | ||
|
|
||
| /// <summary> | ||
| /// Provides helper methods for working with <see cref="AllocationOptions"/>. | ||
| /// </summary> | ||
| internal static class AllocationOptionsExtensions | ||
| { | ||
| public static bool Has(this AllocationOptions options, AllocationOptions flag) => (options & flag) == flag; | ||
| /// <summary> | ||
| /// Returns a value indicating whether the specified flag is set on the allocation options. | ||
| /// </summary> | ||
| /// <param name="options">The allocation options to inspect.</param> | ||
| /// <param name="flag">The flag to test for.</param> | ||
| /// <returns><see langword="true"/> if <paramref name="flag"/> is set; otherwise, <see langword="false"/>.</returns> | ||
| public static bool Has(this AllocationOptions options, AllocationOptions flag) | ||
| => (options & flag) == flag; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.