Skip to content

Proposal: Hide Thread.VolatileRead and Thread.VolatileWrite #27997

Closed
dotnet/roslyn-analyzers
#7043

Description

@carlreinke

Rationale

Thread.VolatileRead and Thread.VolatileWrite delegate to Volatile.Read and Volatile.Write, but it is an incomplete delegation in that Volatile has support for bool whereas Thread does not.

I always reach for Thread.VolatileRead before Volatile.Read. Hiding it would help break this habit.

Proposal

 namespace System.Threading
 {
     public sealed class Thread : CriticalFinalizerObject
     {
         ...
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static byte VolatileRead(ref byte address) => Volatile.Read(ref address);
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static double VolatileRead(ref double address) => Volatile.Read(ref address);
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static short VolatileRead(ref short address) => Volatile.Read(ref address);
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static int VolatileRead(ref int address) => Volatile.Read(ref address);
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static long VolatileRead(ref long address) => Volatile.Read(ref address);
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static IntPtr VolatileRead(ref IntPtr address) => Volatile.Read(ref address);
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static object VolatileRead(ref object address) => Volatile.Read(ref address);
         [CLSCompliant(false)]
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static sbyte VolatileRead(ref sbyte address) => Volatile.Read(ref address);
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static float VolatileRead(ref float address) => Volatile.Read(ref address);
         [CLSCompliant(false)]
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static ushort VolatileRead(ref ushort address) => Volatile.Read(ref address);
         [CLSCompliant(false)]
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static uint VolatileRead(ref uint address) => Volatile.Read(ref address);
         [CLSCompliant(false)]
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static ulong VolatileRead(ref ulong address) => Volatile.Read(ref address);
         [CLSCompliant(false)]
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static UIntPtr VolatileRead(ref UIntPtr address) => Volatile.Read(ref address);
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static void VolatileWrite(ref byte address, byte value) => Volatile.Write(ref address, value);
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static void VolatileWrite(ref double address, double value) => Volatile.Write(ref address, value);
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static void VolatileWrite(ref short address, short value) => Volatile.Write(ref address, value);
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static void VolatileWrite(ref int address, int value) => Volatile.Write(ref address, value);
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static void VolatileWrite(ref long address, long value) => Volatile.Write(ref address, value);
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static void VolatileWrite(ref IntPtr address, IntPtr value) => Volatile.Write(ref address, value);
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static void VolatileWrite(ref object address, object value) => Volatile.Write(ref address, value);
         [CLSCompliant(false)]
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static void VolatileWrite(ref sbyte address, sbyte value) => Volatile.Write(ref address, value);
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static void VolatileWrite(ref float address, float value) => Volatile.Write(ref address, value);
         [CLSCompliant(false)]
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static void VolatileWrite(ref ushort address, ushort value) => Volatile.Write(ref address, value);
         [CLSCompliant(false)]
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static void VolatileWrite(ref uint address, uint value) => Volatile.Write(ref address, value);
         [CLSCompliant(false)]
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static void VolatileWrite(ref ulong address, ulong value) => Volatile.Write(ref address, value);
         [CLSCompliant(false)]
+        [EditorBrowsable(EditorBrowsableState.Never)]
         public static void VolatileWrite(ref UIntPtr address, UIntPtr value) => Volatile.Write(ref address, value);
         ...
     }
 }

Activity

  1. carlreinke commented on Dec 7, 2018

    @carlreinke
    ContributorAuthor
  2. carlreinke commented on Feb 5, 2019

    @carlreinke
    ContributorAuthor

    Is there something I need to do to get someone to take a look at this? It ought to be a simple thumbs up or down.

  3. danmoseley commented on Feb 5, 2019

    @danmoseley
    Contributor

    Cc @kouvel

    This does not seem a compelling reason on the face of it. It can cause more confusion eg if you are used to using these methods and no longer see them in Intellisense. I doubt we would change this. You might consider a Roslyn analyzer or simple grep script.

  4. carlreinke commented on Feb 5, 2019

    @carlreinke
    ContributorAuthor

    Would a proposal to add Thread.VolatileRead and Thread.VolatileWrite overloads for bool be more acceptable?

    If a developer discovers Thread.VolatileRead/Thread.VolatileWrite before the Volatile class then they're going to conclude that volatile operations can't be performed on bool, as was the case for a long time in Framework.

  5. kouvel commented on Feb 5, 2019

    @kouvel
    Contributor

    I would prefer to deprecate the Thread versions over adding new overloads there. They are effectively deprecated APIs. @stephentoub, what is the proper way to deprecate APIs in .NET Core? Hiding them in the editor seems reasonable to me since we would like people to switch over to the Volatile versions.

  6. stephentoub commented on Feb 7, 2019

    @stephentoub
    Member

    We generally don't Obsolete things; there are a variety of problems with that.

    @terrajobst has been exploring an alternate analyzer-based mechanism; he can provide more details.

  7. carlreinke commented on Mar 12, 2019

    @carlreinke
    ContributorAuthor

    Can this be ready-for-review or does something else need to happen first?

  8. terrajobst commented on Nov 12, 2019

    @terrajobst
    Contributor

    Video

    • This seems like a good candidate for a code fixer that replaces the call site.
    • Usage of these APIs is low.
    • We should consider this API in our plan for obsoletion.
    • Hiding these APIs seems fine.
  9. sharwell commented on Nov 12, 2019

    @sharwell
    Contributor

    I would love to see a volatile read with in parameters. I don't think either Thread or Volatile offers these today.

  10. stephentoub commented on Nov 12, 2019

    @stephentoub
    Member

    I don't see the benefit of hiding these. Why is it valuable, @terrajobst?

  11. sharwell commented on Nov 12, 2019

    @sharwell
    Contributor

    I also lean against hiding these. It would be preferable to allow someone to reference them, followed by a diagnostic analyzer reporting the alternative and providing a code fix for it.

  12. danmoseley commented on Nov 12, 2019

    @danmoseley
    Contributor

    Why not just add the bool overloads? Is it a simple oversight that there are all the others?

  13. paulomorgado commented on Jan 14, 2020

    @paulomorgado
    Contributor

    @sharwell, I would mix both. The obsolete attribute could have an overload with the replacement API and a generic analyzer/fixer for this attribute would offer the proper fix.

  14. transferred this issue fromdotnet/corefxon Jan 31, 2020
  15. added this to the 5.0 milestone on Jan 31, 2020
  16. 23 remaining items

  17. modified the milestones: Future, 6.0.0 on Feb 4, 2021
  18. Youssef1313 commented on Feb 20, 2021

    @Youssef1313
    Member

    Per #27997 (comment), this was approved to be marked as Obsolete. However, the labels says "code-analyzer" and "code-fixer". Are the labels incorrect?

  19. carlreinke commented on Feb 20, 2021

    @carlreinke
    ContributorAuthor

    @Youssef1313 The approval is contingent on the implementation of an analyzer and fixer.

  20. stephentoub commented on Feb 21, 2021

    @stephentoub
    Member

    The approval is contingent on the implementation of an analyzer and fixer.

    I expect we'd just need a fixer for whatever diagnostic ID is included as part of the obsoletion attribute.

  21. modified the milestones: 6.0.0, 7.0.0 on Jul 26, 2021
  22. modified the milestones: 7.0.0, 8.0.0 on Jul 6, 2022
  23. modified the milestones: 8.0.0, Future on Jun 23, 2023
  24. CollinAlpert commented on Nov 30, 2023

    @CollinAlpert
    Contributor

    I have implemented the fixer and now need to settle on a diagnostic ID. Can I confirm the ID "SYSLIB0054" for this obsoletion?

  25. locked and limited conversation to collaborators on Apr 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-approvedAPI was approved in API review, it can be implementedarea-System.Threadingcode-analyzerMarks an issue that suggests a Roslyn analyzercode-fixerMarks an issue that suggests a Roslyn code fixerhelp wanted[up-for-grabs] Good issue for external contributors

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions