Interlocked Exchange of a struct
Asked Answered
B

4

7

I want to use InterlockedExchange from the WinAPI to use a lock free synchronization of threads.
At the moment I have a class like this.

struct DataExchange
{
    volatile LONG m_value;
    void SetValue(LONG newVal)
    {
        InterlockedExchange(&m_value, newVal);
    }

    LONG GetValue()
    {
        LONG workVal=0;
        InterlockedExchange(&workVal, m_value);
        return workVal;
    }
};

One thread can set a new value and an other thread can read this value.
Now what I want to do is to change the LONG value to be a struct. Is there any way in the WinAPI how I can copy a struct lock free?

Blaise answered 24/5, 2011 at 11:40 Comment(6)
Using atomic access on the variable doesn't actually make it lock-free, because atomic access is also a very small critical section, albeit implemented at the CPU.Chrissie
If you want lock-free, fence-free maybe you should consider this URL: calvados.di.unipi.it/dokuwiki/doku.php?id=ffnamespace:aboutChrissie
Lockfree is really wrong in this context. But it is the fastest synchronization I can use on a windows machine. @Chrissie +1 for the nice link. I will have a look at as soon I have some timeBlaise
Raymond Chen (The Old New Thing) wrote quite a bit on this topic last month, e.g. Lock-free algorithms: The one-time initializationRotor
Not if the struct is larger than 32 bits. But what you can do is exchange a pointer to a struct.Sika
Note also that your GetValue implementation corrupts the value...Thunderstone
E
3

No there isn't unless you can fit your struct into 32 bits, in which case you can continue to use InterlockedExchange.

Expellant answered 24/5, 2011 at 11:43 Comment(0)
T
2

You can get an atomic operation on a 64-bit value using InterlockedExchange64 on 64-bit platforms and Windows Vista/7. That would be enough to fit two 32-bit int values in a struct.

Since the function is implemented with a complier instrinsic, it's basically calling a platform-dependent assembly instruction like CMPXCHG on x86. Since that instruction only works at a maximum (on 64-bit platforms) on a 64-bit register source operand, a 64-bit register or memory destination operand, and the RAX register, there is only a certain-size value you can perform an atomic operation on using single assembly instructions without incorporating some type of lock or semaphore to create a critical section.

Tad answered 24/5, 2011 at 12:20 Comment(0)
E
1

Only if the struct is exactly 32 bits.

An alternative is to use an InterlockedExchange on a pointer to a struct. The struct has to be immutable (or never change it). To update the struct, make a new one and then exchange the pointer. You have to be careful about destroying the struct to make sure it is only done once, and only if no one is using it.

Everhart answered 24/5, 2011 at 11:45 Comment(2)
@lou-franco: But using new and delete would be contrary to my goal to be as fast as possible in this case. Because the heap manager will also do some internal locking.Blaise
@mkaes: Have you measured? Don't ignore a potential method because it might exhibit certain behaviour - you should check. (I also suggested using a pointer in a comment to your question, and I think it's worth investigating for you.)Sika
O
1

The best you can do is to use InitializeCriticalSectionAndSpinCount function which will not wait for the lock if it is possible to take an ownership fast enough.

Oversleep answered 24/5, 2011 at 11:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.