18

I need an array with volatile items, and can't find a way to do that.

private volatile T[] _arr;

This means that the _arr reference is volatile, however it does not guarantee anything about the items inside the _arr object itself.

Is there any way to mark the _arr's Items as volatile?

Thanks.

EDIT:

The following code built according to binarycoder's answer. Is this code thread-safe to use?

public class VolatileArray<T>
{
    private T[] _arr;

    public VolatileArray(int length)
    {
        _arr = new T[length];
    }

    public VolatileArray(T[] arr)
    {
        _arr = arr;
    }

    public T this[int index]
    {
        get
        {
            T value = _arr[index];
            Thread.MemoryBarrier();
            return value;
        }

        set
        {
            Thread.MemoryBarrier();
            _arr[index] = value;
        }
    }

    public int Length
    {
        get { return _arr.Length; }
    }
}
DxCK
  • 4,402
  • 7
  • 50
  • 89

4 Answers4

11

Since it is possible to pass array elements by reference, you can use Thread.VolatileRead and Thread.VolatileWrite.

It is useful to understand that the volatile keyword works behind the scenes by using Thread.MemoryBarrier. You could write:

// Read
x = _arr[i];
Thread.MemoryBarrier();

// Write
Thread.MemoryBarrier();
_arr[i] = x;

Note that volatile and MemoryBarrier are advanced techniques that are both easy to get wrong. For example, see How do I Understand Read Memory Barriers and Volatile. Usually you are better off with higher level constructs such as lock, Monitor, ReaderWriterLockSlim, and others.

Community
  • 1
  • 1
Jason Kresowaty
  • 16,105
  • 9
  • 57
  • 84
  • 1
    IIRC, then strictly, the `volatile` keyword entails only a read or write barrier as appropriate, while `Thread.MemoryBarrier()` has a full barrier. The above therefore is slightly heavier than the equivalent use of `volatile` even before we consider that it involves a method call. It is still the best we can do (and as you say, the current implementation of `VolatileRead()` and `VolatileWrite()`). – Jon Hanna Nov 08 '11 at 20:29
6

Use Volatile.Read(ref array[index]) and Volatile.Write(ref array[index], value).

Class Volatile is available since .NET 4.5. It allows to read/write from/to fields, array elements, ref parameters, pointers.

OmariO
  • 506
  • 4
  • 11
3

I made a little struct that helps keep things clean and OO

struct VolatileBoolean {
    public volatile Boolean Value;
}

VolatileBoolean[] arrayOfVolatileBooleans;
public void SomeMethod() {
    if (arrayOfVolatileBooleans[4].Value)
        DoSomething();
}
Nick Strupat
  • 4,928
  • 4
  • 44
  • 56
2

I don't think that you can

You can't, volatile is defined as a field-modifier (ECMA 334).

And I don't think it will accomplish what you want either.
Consider:

 private T[] _arr;

 volatile T v;
 ....  v = _arr[x];
 ....  _arr[x] = v;
H H
  • 263,252
  • 30
  • 330
  • 514