Skip to content
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

Add CollectionsMarshal.SetCount(list, count) #77794

Closed
wants to merge 2 commits into from
Closed

Conversation

layomia
Copy link
Contributor

@layomia layomia commented Nov 2, 2022

Fixes #55217.

@dotnet-issue-labeler
Copy link

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.


list._version++;

if (count < list._size)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a use case for setting a value smaller than the current count? That's already possible with RemoveRange.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having the API not support it would certainly be unexpected.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it? Trying to set Capacity to less than Count throws. How is this different? And what's the use case where you'd call this to shrink rather than grow? I'm not against it if it's useful, I'm trying to understand the use.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be useful in cases where you don't know whether the count will be smaller or bigger than the list size.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's an example of that?

Copy link
Contributor

@DaZombieKiller DaZombieKiller Nov 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In which case I'm not sure why we're clearing. If this is about an advanced developer using this unsafe API to do something that requires them to know what they're doing, why are we forcing additional costs upon the operation when we have no idea what the intent is?

I agree. While I don't expect it to be even remotely close to the "common" use case for the API, I can think of scenarios where not having the clearing behavior for reference types could be potentially beneficial.

For example, using a List<T> as a temporary buffer for several operations that may resize it, and then at the end you can SetCount(Capacity) followed by Clear to ensure objects aren't held onto afterwards, rather than potentially having multiple instances of zeroing inside the actual operation.

But the counterpoint is that this makes the API prone to memory leaks when T is a reference type... I'd argue that's grounds to mark the API with [UnsafeCallersOnly] if that existed, but at present I think this is a question of "how unsafe is too unsafe for CollectionsMarshal".

I personally think that if it's appropriately documented, it should be fine to not have the clearing behavior (and as mentioned, it's expected that callers would understand how the API behaves before using it).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and then at the end you can SetCount(Capacity) followed by Clear to ensure objects aren't held onto afterwards

Sure. But that's just RemoveRange.

I'd argue that's grounds to mark the API with [UnsafeCallersOnly] if that existed

I expect pretty much everything on Unsafe, Marshal, MemoryMarshal, and CollectionsMarshal would be UnsafeCallersOnly if it ever exists.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the name of making forward progress here, let's finish this PR with the behavior of supporting shrinking and clearing, and then we can have a follow-up conversation about whether to change the behavior prior to shipping. Along with this, it'd be good to structure the method in a way that optimizes for the expected case of calling this to increase the count.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This API should be optimized for the cases that do not require buffer resizing, with increasing being the main target. Operations that require a resize could potentially be moved into a separate non inlineable local method.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right.

@layomia layomia requested a review from krwq November 17, 2022 18:06
@ghost
Copy link

ghost commented Dec 17, 2022

Draft Pull Request was automatically closed for 30 days of inactivity. Please let us know if you'd like to reopen it.

@ghost ghost locked as resolved and limited conversation to collaborators Jan 17, 2023
@dotnet dotnet unlocked this conversation Jan 19, 2023
@MichalPetryka
Copy link
Contributor

@layomia Is there any progress with this?

@MichalPetryka
Copy link
Contributor

@eiriktsarpalis Since @layomia seems to be inactive, would it be fine for me to open a new PR in place of this one?

@layomia
Copy link
Contributor Author

layomia commented Feb 13, 2023

would it be fine for me to open a new PR in place of this one?

@MichalPetryka, go for it. Thanks.

@layomia layomia closed this Feb 13, 2023
MichalPetryka added a commit to MichalPetryka/runtime that referenced this pull request Feb 15, 2023
Adds the ability to resize lists, exposed in
CollectionsMarshal due to potentially risky
behaviour caused by the lack of element initialization.

Supersedes dotnet#77794.

Fixes dotnet#55217.
@ghost ghost locked as resolved and limited conversation to collaborators Mar 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add CollectionsMarshal.SetCount API for List<T>
6 participants