Douglas Douglas -4 years ago 79
C# Question

Why does Volatile.Read take ref parameter?

The implementation of

Volatile.Read
merely inserts a memory barrier after the read:

public static int Read(ref int location)
{
var value = location;
Thread.MemoryBarrier();
return value;
}


Thus, usage of the method like so...

return Volatile.Read(ref _a) + Volatile.Read(ref _b);


...would be equivalent to:

var a = _a;
Thread.MemoryBarrier();
var b = _b;
Thread.MemoryBarrier();
return a + b;


Given the above, wouldn't the resulting behavior be identical if the parameter was not a
ref
?

public static int Read(int value)
{
Thread.MemoryBarrier();
return value;
}


I guess that the
ref
parameter was used simply to prevent programmers from passing things other than variables, such as
Volatile.Read(2 + 3)
. Can anyone see any other reason for the
ref
when variables are passed in?

Answer Source

That is not what the real code looks like after the jitter is done with it. Volatile.Read() is an intrinsic. An expensive word that means that the jitter will not compile the method at all but substitutes it with a processor-specific version of the machine code. The code you found is just a place-holder that could serve as a fallback on a machine without a decent jitter. Theoretically.

You can see what you get on your machine with Debug > Windows > Disassembly. You have to switch to the Release build and use Tools > Options > Debugging > General > untick "Suppress JIT optimization". Most programmers will be happy with what they see:

04CF0450  mov         ecx,dword ptr ds:[7C43ACh] 

Or in other words: nothing. Just a plain memory read without a barrier. Intel/AMD cores have a strong memory model that doesn't require a barrier. But, say, an ARM core does and will need the address of the variable. Itanium was also weak, but its jitter was discontinued.

Do note how, while you could be happy, that this is also rather bad news. You basically can't rely on testing your program on your dev machine and conclude it is good enough. Or in other words, no way to tell that you should have used Volatile but you forgot. Only running your program on the device is going to give you a hint that you got it wrong. It does take a lot of courage to skip lock :)

Several more intrinsics around like that, Math.Sqrt() for example. Most processors have it as a built-in machine code instruction.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download