Skip to content

Conversation

danielcweber
Copy link
Collaborator

No description provided.

Copy link
Collaborator

@akarnokd akarnokd left a comment

Choose a reason for hiding this comment

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

Some changes would be great!

}

// Atomically swap in the new value and get back the old.
var b = Interlocked.CompareExchange(ref fieldRef, value, old);
Copy link
Collaborator

Choose a reason for hiding this comment

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

The problem with this sentinel technique is that if there are a lots of concurrent SetMultiple, threads may keep retrying on ever so state values. Having old read fresh inside the loop can change the window to a favorable thread-thread interaction.

http://cs.oswego.edu/pipermail/concurrency-interest/2016-September/015339.html

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It's currently just the existing stuff copy and pasted. I would not like to change the actual implementation in this PR.

/// Gets or sets the underlying disposable. After disposal, the result of getting this property is undefined.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown if the resource has already been assigned to.</exception>
internal static void SetSingle(ref IDisposable fieldRef, IDisposable value)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I found it sometimes valuable to have this method return true on success and false on an already disposed state.

value?.Dispose();
}

internal static void SetMultiple(ref IDisposable fieldRef, IDisposable value)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Return bool true for success, false for disposed state?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Can be done.

}
}

internal static void SetSerial(ref IDisposable fieldRef, IDisposable value)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Return bool true for success, false for disposed state?


internal static void Dispose(ref IDisposable fieldRef)
{
Interlocked.Exchange(ref fieldRef, BooleanDisposable.True)?.Dispose();
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd advise bias this against multiple dispose calls by doing a volatile read on fieldRef and checking if not already disposed. Dispose calls fly around pretty frequently in Rx.NET and I'm not sure generally those are at most 1-2 per target.

Also returning bool true if the current thread managed to dispose the contents could be valuable.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't know what is more performant. A volatile read isn't free either.

/// <summary>
/// Gets or sets the underlying disposable. After disposal, the result of getting this property is undefined.
/// </summary>
internal static IDisposable Get(ref IDisposable fieldRef, bool returnDefaultWhenDisposed)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd split this into two, one guarding against the leak, the others not. Saving a branch on cases where there is no worry about leaking the reference would be beneficial.

@danielcweber
Copy link
Collaborator Author

@akarnokd Good to go like this?

/// </summary>
internal static IDisposable GetValue(ref IDisposable fieldRef)
{
var current = Volatile.Read(ref fieldRef);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just return this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

?

Copy link
Collaborator

@akarnokd akarnokd May 29, 2018

Choose a reason for hiding this comment

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

Returning null when the contents are disposed is misleading. Maybe there is no need for this method after all since I can just do a Volatile.Read(ref field) when I need the exact result.

Copy link
Collaborator Author

@danielcweber danielcweber May 29, 2018

Choose a reason for hiding this comment

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

I want the not-leaking-the-sentinel part there

@danielcweber danielcweber merged commit 1a5e9ba into dotnet:master May 29, 2018
@danielcweber danielcweber deleted the DRYinDisposables branch May 29, 2018 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants