pseudo spin-lock design help

  • Thread starter Thread starter mpaine
  • Start date Start date
M

mpaine

Hi everyone,

I wrote some code and it seems ok to me but since it is going into a
high-use production environment, I wanted some peer-review if possible.
Basically, I wanted a way to know if an object is being "reset" and
only allow one thread to reset it at any one time. This is what I came
up with:

Private _lockResetSync As Object = New Object()
Private _lockResetWaitEvent As ManualResetEvent = New
ManualResetEvent(False)
Private _IsResetting As Boolean = False
Public Sub Reset(ByVal cmd As Object)
Dim _ThisThreadIsResetting As Boolean = False
While Not _ThisThreadIsResetting ' pseudo-spin-lock for
thread safety
If _IsResetting Then
_lockResetWaitEvent.WaitOne()
Exit Sub
End If
SyncLock _lockResetSync
If Not _IsResetting Then
_lockResetWaitEvent.Reset()
_IsResetting = True
_ThisThreadIsResetting = True
End If
End SyncLock
End While
Try
' !! Do time-consuming thread-safe stuff here
Finally
_IsResetting = False
_lockResetWaitEvent.Set()
End Try
End Sub
Public ReadOnly Property IsResetting() As Boolean
Get
Return _IsResetting
End Get
End Property

I feel if two threads came into Reset() at the same clock-tick (hehe),
this would still work correctly. Also, external objects would know
what is going on. Will this work and if not, what is a better way to
do this?

Thank you,
Michael
 
I wrote some code and it seems ok to me but since it is going into a
high-use production environment, I wanted some peer-review if possible.

I found your code tortuous to follow. If you want peer-review you'll
need to document it! i.e. write at the top what the specification is
for your code.

Anyway, here's my attempt at a simpler alternative. The specification
is: we have a global variable called "state", which is normally 0
(unset) or 1 (set). It also has a special state 1 (resetting). Only
one thread is allowed to be resetting at any one time, and the
resetting process may be lengthy.

Private state As Integer = 1

Public Sub reset()
While Interlocked.CompareExchange(state, 2, 1) <> 1
End While
' ...
Interlocked.CompareExchange(state, 0, 2)
End Sub

Nots on the code: the initial While loop will keep going until we
succeed in being the unique thread who shifts it from 1 to 2. Then the
"..." body proceeds. Within this body, we are guaranteed that we are
the only thread running this body while in state 2. (note: this
guarantee depends on the fact that no one changes the state except
through our own carefully controlled methods). Finally we complete our
resetting by putting it back to 0. This final CompareExchange is
guaranteed to succeed. That's because no one else was able to shift
from state 2 to anything. (but we should probably but a Debug.Assert
there).

Note: it's possible to put a Wait inside the initial while loop, but
not needed. Could even use a Sleep.
 
Your "_IsResetting" boolean, is going to cause you major, major, major
trouble. It needs to be marked as volatile (which VB.Net doesn't support,
IIRC) or you need to access it using either the Interlocked operations, the
Thread.VolatileRead/VolatileWrite constructs, or with (don't do this!) a
MemoryBarrier. I didn't really look through the code in any more depth than
that.

Looking through your code, I would strongly suggest you go pull down Jeff
Richter's Power Threading library from the Wintellect site, and use his
threading constructs. They're already debugged, well documented, and easy to
use.

Writing this level of complexity yourself, when you're not an expert (and
your use of the boolean member says you're not yet an expert), is going to
be an excercise in frustration. It's also going to always (!!) have subtle
bugs in it. These bugs are also a nightmare to track down and debug.

For an example of the type of debugging you'll be stuck doing:
http://www.coversant.net/Default.aspx?tabid=88&EntryID=28
 
Back
Top