Need help with communication between multiple threads
Chad J
gamerChad at _spamIsBad_gmail.com
Tue Feb 20 18:56:40 PST 2007
Sean Kelly wrote:
> Chad J wrote:
>
>> kris wrote:
>>
>>>
>>> Basicially, you need to protect the value from contention between two
>>> threads. There are a number of ways to do this:
>>>
>>> 1) using native D facilities via the synchronized keyword: expose a
>>> getter and setter method, and have them both synch on the same
>>> object/lock. This is a fairly heavyweight resolution, but it would work.
>>>
>>
>> So would something like this do the trick?
>>
>> class Mutex
>> {
>> uint pointlessVariable;
>> }
>> Mutex mutex;
>>
>> uint m_value = 42; // The thing to be protected.
>> uint value() // getter
>> {
>> synchronized(mutex)
>> return m_value;
>> }
>> uint value(uint newbie) // setter
>> {
>> synchronized(mutex)
>> m_value = newbie;
>>
>> return newbie;
>> }
>>
>> Or am I supposed to do something else like put m_value inside the
>> mutex class?
>
>
> You could use synchronized with no arguments and everything will work
> file. The default behavior for free functions is to synchronize on a
> hidden global object. Alternately:
>
> Object valueLock = new Object;
>
> uint m_value = 42; // The thing to be protected.
>
> uint value() // getter
> {
> synchronized(valueLock)
> return m_value;
> }
>
> uint value(uint newbie) // setter
> {
> synchronized(valueLock)
> m_value = newbie;
> return newbie;
> }
>
> This works if you want to synch only specific functions with respect to
> one anohther.
>
>>> 3) use CPU-specific instructions to ensure value access is atomic.
>>> This is what Sean has exposed in the Atomic module within Tango. It
>>> is a lightweight and low-overhead solution, and works by locking the
>>> bus for the duration of the read/write access.
>>
>>
>> This sounds cool, but I don't quite understand how to use the Atomic
>> module - what is msync and which value of it do I pick to make things
>> work? I made a post about this in the Tango forum incase it's more
>> appropriate to discuss there.
>
>
> The Tango forums are probably more appropriate, but I can give a quick
> summary here (I'm on my way out the door as I write this).
> tango.core.Atomic does essentially two things: it ensures that any
> operation it performs is atomic, and it provides methods to control
> memory ordering regarding such operations. The latter issue is somewhat
> complicated, but suffice to say that msync.seq is the safest option and
> should be used in most situations. So for the above:
>
> uint m_value = 42;
>
> uint value() // getter
> {
> return atomicLoad!(msync.seq)( m_value );
> }
>
> uint value(uint newbie) // setter
> {
> atomicStore!(msync.seq)( m_value, newbie );
> return newbie;
> }
>
> For data which will always be modified atomically, a wrapper struct is
> also provided:
>
> Atomic!(uint) m_value;
>
> // Atomic really needs a ctor, but this should work
> // for "fast" construction.
> m_value.store!(msync.raw)( 42 );
>
> uint value() // getter
> {
> return m_value.load!(msync.seq);
> }
>
> uint value(uint newbie) // setter
> {
> m_value.store!(msync.seq)( newbie );
> return newbie;
> }
>
> Please note that Atomic currently only supports x86, but if there's a
> demand for it then I may add support for other architectures. If this
> happens, it will probably under Posix (and not Win32), since I'm not
> entirely sure about out-of-the-box assembler support with DMD/Win32.
>
>> When I was porting Phobos to work on ARM-WinCE, it was very helpful to
>> be able to discard a module without breaking other parts of the lib,
>> namely in the case of that module requiring a broken language feature
>> or inline assembly (inline asm is not currently available with
>> arm-wince-pe-gdc, and I don't feel like learning ARM asm yet). That
>> said, Atomic looks like it will be very broken on ARM in its current
>> state. I also benchmarked synchronized reads vs atomic reads and
>> yeah, synchronized was much slower (I picked "whatever makes it
>> compile" values for msync). So I'll probably implement a version
>> using only synchronization and a version that uses Atomic instead
>> whenever possible.
>
>
> See above :-) Atomic won't work on ARM without additional code.
>
> By the way, it may also eventually be necessary to add a hardware
> instruction for ordering load operations on x86, since I'm becoming
> convinced that load reordering is actually allowed by the IA-32 spec
> (and it may actually be done on some AMD CPUs). I've been resisting
> this until now because it will slow down synchronized loads
> substantially for what may be only a small portion of the x86 hardware
> in production. So if you (or anyone) decides to use Atomic as-is and
> see weird behavior with atomicLoad using msync.acq or msync.hlb, please
> let me know.
>
>
> Sean
Cool thanks for the info and this handy low-overhead threading tool.
I didn't have any problems with msync.acq or msync.hlb so far, but when
loading using msync.seq I get a Win32 Exception. I created a ticket
about this.
More information about the Digitalmars-d-learn
mailing list