Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 4250764
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 21, 20262026-05-21T04:34:19+00:00 2026-05-21T04:34:19+00:00

I have a bit of my game which looks like this: public static float

  • 0

I have a bit of my game which looks like this:

public static float Time;

float someValue = 123;
Interlocked.Exchange(ref Time, someValue);

I want to change Time to be a Uint32; however, when I try to use UInt32 instead of float for the values, it protests that the type must be a reference type. Float is not a reference type, so I know it’s technically possible to do this with non-reference types. Is there any practical way to make this work with UInt32?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-21T04:34:19+00:00Added an answer on May 21, 2026 at 4:34 am

    Although ugly, it is actually possible to perform an atomic Exchange or CompareExchange on an enum or other blittable value type of 64 bits or less using unsafe C# code:

    enum MyEnum { A, B, C };
    
    MyEnum m_e = MyEnum.B;
    
    unsafe void example()
    {
        MyEnum e = m_e;
        fixed (MyEnum* ps = &m_e)
            if (Interlocked.CompareExchange(ref *(int*)ps, (int)(e | MyEnum.C), (int)e) == (int)e)
            {
                /// change accepted, m_e == B | C
            }
            else
            {
                /// change rejected
            }
    }
    

    The counterintuitive part is that the ref expression on the dereferenced pointer does actually penetrate through the cast to the address of the enum. I think the compiler would have been within its rights to have generated an invisible temporary variable on the stack instead, in which case this wouldn’t work. Use at your own risk.

    [edit: for the specific type requested by the OP]

    static unsafe uint CompareExchange(ref uint target, uint v, uint cmp)
    {
        fixed (uint* p = &target)
            return (uint)Interlocked.CompareExchange(ref *(int*)p, (int)v, (int)cmp);
    }
    

    [edit: and 64-bit unsigned long]

    static unsafe ulong CompareExchange(ref ulong target, ulong v, ulong cmp)
    {
        fixed (ulong* p = &target)
            return (ulong)Interlocked.CompareExchange(ref *(long*)p, (long)v, (long)cmp);
    }
    

    (I also tried using the undocumented C# keyword __makeref to achieve this, but this doesn’t work because you can’t use ref on a dreferenced __refvalue. It’s too bad, because the CLR maps the InterlockedExchange functions to a private internal function that operates on TypedReference [comment mooted by JIT interception, see below])


    [edit: July 2018] You can now do this more efficiently using the System.Runtime.CompilerServices.​Unsafe library package. Your method can use Unsafe.As<TFrom,TTo>() to directly reinterpret the type referenced by the target managed reference, avoiding the dual expenses of both pinning and transitioning to unsafe mode:

    static uint CompareExchange(ref uint target, uint value, uint expected) =>
        (uint)Interlocked.CompareExchange(
                                ref Unsafe.As<uint, int>(ref target),
                                (int)value,
                                (int)expected);
    
    static ulong CompareExchange(ref ulong target, ulong value, ulong expected) =>
        (ulong)Interlocked.CompareExchange(
                                ref Unsafe.As<ulong, long>(ref target),
                                (long)value,
                                (long)expected);
    

    Of course this works for Interlocked.Exchange as well. Here are those helpers for the 4- and 8-byte unsigned types.

    static uint Exchange(ref uint target, uint value) =>
        (uint)Interlocked.Exchange(ref Unsafe.As<uint, int>(ref target), (int)value);
    
    static ulong Exchange(ref ulong target, ulong value) =>
        (ulong)Interlocked.Exchange(ref Unsafe.As<ulong, long>(ref target), (long)value);
    

    This works for enumeration types also–but only so long as their underlying primitive integer is exactly four or eight bytes. In other words, int (32-bit) or long (64-bit) sized. The limitation is that these are the only two bit-widths found among the Interlocked.CompareExchange overloads. By default, enum uses int when no underlying type is specified, so MyEnum (from above) works fine.

    static MyEnum CompareExchange(ref MyEnum target, MyEnum value, MyEnum expected) =>
        (MyEnum)Interlocked.CompareExchange(
                                ref Unsafe.As<MyEnum, int>(ref target),
                                (int)value,
                                (int)expected);
    
    static MyEnum Exchange(ref MyEnum target, MyEnum value) =>
        (MyEnum)Interlocked.Exchange(ref Unsafe.As<MyEnum, int>(ref target), (int)value);
    

    I’m not sure whether the 4-byte minimum is a fundamental to .NET, but as far as I can tell it leaves no means of atomically swapping (values of) the smaller 8- or 16-bit primitive types (byte, sbyte, char, ushort, short) without risking collateral damage to adjacent byte(s). In the following example, BadEnum explicitly specifies a size that is too small to be atomically swapped without possibly affecting up to three neighboring bytes.

    enum BadEnum : byte { };    // can't swap less than 4 bytes on .NET?
    

    If you’re not constrained by interop-dictated (or otherwise fixed) layouts, a workaround would be to ensure that the memory layout of such enums is always padded to the 4-byte minimum to allow for atomic swapping (as int). It seems likely, however, that doing so would defeat whatever purpose there might have been for specifying the smaller width in the first place.


    [edit: April 2017] I recently learned that when .NET is running in 32-bit mode (or, i.e. in the WOW subsystem), the 64-bit Interlocked operations are not guaranteed to be atomic with respect to non-Interlocked, "external" views of the same memory locations. In 32-bit mode, the atomic guarantee only applies globablly across QWORD accesses which use the Interlocked (and perhaps Volatile.*, or Thread.Volatile*, TBD?) functions.

    In other words, to obtain 64-bit atomic operations in 32-bit mode, all accesses to those QWORD locations, including reads, must occur through Interlocked/Volatile in order to preserve the guarantees, so you can’t get cute assuming (e.g.) that direct (i.e., non-Interlocked/Volatile) reads are protected just because you always use Interlocked/Volatile functions for writing.

    Finally, note that the Interlocked functions in the CLR are specially recognized by, and receive special treatment in, the .NET JIT compiler. See here and here This fact may help explain the counter-intuitiveness I mentioned earlier.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have to make a flash game like this: There is a board with
I have an app (a game) which saves data: game state, high scores, achievements,
I am working on a small game using webgl. Within this game I have
I'm relatively(read: stupid newbie) familiar with disassembly but this bit stumped me: I have
I am writing a scriptable game engine, for which I have a large number
I have a bit of HTML code that I would like to change based
I have game application (cocos2d) in which, a ball is to be shooted from
I have a Rails 2.3.5 app which is serving a card game. I've been
So i have this file of 10,000+ lines of messages from a game server,
I have a quiz-like javascript game and it is supposed to be fast-paced. The

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.