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 6131621
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 23, 20262026-05-23T16:59:53+00:00 2026-05-23T16:59:53+00:00

I am going to create a long (Int64) surrogate which has to be atomic,

  • 0

I am going to create a “long” (Int64) surrogate which has to be atomic, so its copy in a concurrent application will be inherently safe. I cannot use an Int32 because it spans too short as range.

I know that the atomicity should be guarantee as long the involved data can fit in a double-word (32 bits). No matter whether the OS is 32 or 64 bits.

Now, consider the following “long” surrogate…

NOTE: I’ve omitted several methods because I don’t need them. In this case I need only the basic conversion to/from a real long.

public struct SafeLong
    : IConvertible
{
    public SafeLong(long value)
    {
        unchecked
        {
            var arg = (ulong)value;
            this._data = new byte[]
            {
                (byte)arg,
                (byte)(arg >> 8),
                (byte)(arg >> 16),
                (byte)(arg >> 24),
                (byte)(arg >> 32),
                (byte)(arg >> 40),
                (byte)(arg >> 48),
                (byte)(arg >> 56),
            };
        }
    }



    private byte[] _data;



    private long Value
    {
        get
        {
            unchecked
            {
                var lo =
                    this._data[0] |
                    this._data[1] << 8 |
                    this._data[2] << 16 |
                    this._data[3] << 24;

                var hi = 
                    this._data[4] |
                    this._data[5] << 8 |
                    this._data[6] << 16 |
                    this._data[7] << 24;

                return (long)((uint)lo | (ulong)(uint)hi << 32);
            }
        }
    }



    public static implicit operator long(SafeLong value)
    {
        return value.Value;  // implicit conversion
    }



    public static explicit operator SafeLong(long value)
    {
        return new SafeLong(value);  // explicit conversion
    }


    #region IConvertible implementation

    public TypeCode GetTypeCode()
    {
        return Type.GetTypeCode(typeof(SafeLong));
    }

    public object ToType(Type conversionType, IFormatProvider provider)
    {
        return Convert.ChangeType(this.Value, conversionType);
    }

    public long ToInt64(IFormatProvider provider)
    {
        return this.Value;
    }

    // ... OMISSIS (not implemented) ...

    #endregion
}

Well, it seems working perfectly as I expect.

Here is a small test:

class Program
{
    static void Main(string[] args)
    {
        var sla = (SafeLong)12345678987654321L;
        var la = (long)sla;
        Console.WriteLine(la);

        var slb = (SafeLong)(-998877665544332211L);
        var lb = (long)slb;
        Console.WriteLine(lb);

        Console.WriteLine(Marshal.SizeOf(typeof(SafeLong)));
        Console.WriteLine(Marshal.SizeOf(sla));
        Console.WriteLine(Marshal.SizeOf(slb));

        long lc = new SafeLong(556677);
        var slc = slb;
        Console.WriteLine(slc);
        slc = (SafeLong)lc;
        Console.WriteLine(slc);
        Console.WriteLine(slb);

        Console.Write("Press any key...");
        Console.ReadKey();
    }
}

The SizeOf function yields always 4 bytes as the size of my surrogate. Does this value guarantees the atomicity of a copy SafeLong-to-SafeLong, or the 4 bytes should be interpreted as “real physical double-word”?

No matter the NON-atomicity of the long <–> SafeLong: it will be enclosed in a safe context.

Thanks a lot in advance.

  • 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-23T16:59:53+00:00Added an answer on May 23, 2026 at 4:59 pm

    You’re right in that this is atomic, but holy goodness is this ever a complicated solution to a simple problem. If you want a struct that has the value of a long but uses references to be atomic, just box the long! In fact, if you do that then you can make an atomic version of any struct type, so let’s do that:

    public struct SafeThing<T> where T : struct
    {
        private object boxedThing;
    
        public SafeThing(T value)
        {
            boxedThing = value;
        }
    
        public T Value { get { return boxedThing == null ? default(T) : (T)boxedThing; } }
    
        public static implicit operator T(SafeThing<T> value)
        {
            return value.Value; 
        }
    
        public static implicit operator SafeThing<T>(T value)
        {
            return new SafeThing(value); 
        }
    }
    

    And you’re done. Why are you doing all this messing around with an array?

    Also, I note that in your implementation you’ve got your explicit/implicit conversions backwards. A conversion should only be implicit if it is lossless and does not throw. Your implicit conversion from SafeLong to long can throw, so it should not be implicit. Your explicit conversion from long to SafeLong cannot throw and is lossless, so it could be implicit if you wanted it to be. As you can see, I’ve solved the problem in my implementation by making both directions lossless and non-throwing, so they are both implicit.

    Notice that this struct is essentially a strongly-typed wrapper around a boxed value; if generic types had been available in the first version of the CLR, undoubtedly boxed value types would be implemented using some sort of type like this, just as nullable value types are similarly implemented by a special generic type.

    The SizeOf function yields always 4 bytes as the size of my surrogate. Does this value guarantees the atomicity of a copy SafeLong-to-SafeLong?

    Well, yes and no.

    First off, the “SizeOf” method does not give the size of a struct in memory; it gives the size of the struct when it is persisted across a managed/unmanaged boundary. That’s not necessarily the same as the size of a struct in managed memory; it often is the same, but it is not guaranteed to be the same. If you want to know the size of a struct in managed memory then you need to turn on “unsafe” mode and use the “sizeof” operator.

    As a practical matter, a copy of a struct of size four is always going to be atomic, provided that it is copied to a location aligned on a four byte boundary. The language specification does not guarantee that any four-byte struct will be copied atomically, though in fact that is true in our implementation.

    In your particular case, those four bytes are a reference to an array; the language specification does guarantee that a reference is always copied atomically.

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

Sidebar

Related Questions

I'm going to create widget which needs to update its content every minute (it
I am going to create a typical business application that will be used by
I have a long php array which I loop through and create a form
I want to create a simple long polling server in node.js where communication will
that's going to be a long question so bear with me :) My Application
I want to create wayfinder/pathfinder mobile application. it will route visitors in our buildings.
I am going to create a script that sends out an email. I am
I am going to create an XML element in JavaScript to exchange data with
We are going to create Jar Store the way like App Store works, but
Here is an example of what I've got going on: CREATE TABLE Parent (id

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.