' *
' * The project site is at: http://sourceforge.jp/projects/fishbornas/
' *
' * First author tiritomato 2012.
' *
' * Distributed under the FishbornArchiveShelf License (See
' *  file "Licenses/License.txt" contained in a project, or the following link.
' *  http://sourceforge.jp/projects/fishbornas/scm/svn/blobs/head/trunk/Licenses/License.txt)
' *
' * 2012.06.07 Initial Revision (tiritomato)
' *

Partial Public Class Logic
    Partial Public Class Threading

        Public Delegate Sub SubDelegate()
        Public Delegate Function SignalHandler() As Boolean

        Public Shared Function CreateOrWaitMutex(ByVal Name As String, Optional ByVal WaitLimitMSec As Integer = -1) As System.Threading.Mutex

            Dim isCreate As Boolean
            CreateOrWaitMutex = New System.Threading.Mutex(True, Name, isCreate)
            If CreateOrWaitMutex IsNot Nothing And isCreate = False Then CreateOrWaitMutex.WaitOne(System.Math.Max(-1, WaitLimitMSec))

        End Function

        Public Shared Function PallingWaitMutexExist(ByVal MutexName As String, Optional ByVal tmSleepUnit As Integer = -1, Optional ByVal ctSleepTry As Integer = -1, Optional ByVal EmergencyBreakSignal As SignalHandler = Nothing) As System.Threading.Mutex

            PallingWaitMutexExist = Nothing
            Dim ctTry As UInt64 = 0
            Dim ctSleepScale As Integer = 0
            Dim tmNextSleep As Integer = 0
            Do
                If EmergencyBreakSignal IsNot Nothing AndAlso EmergencyBreakSignal() Then Exit Do

                Try
                    PallingWaitMutexExist = System.Threading.Mutex.OpenExisting(MutexName)
                    Exit Do
                Catch ex As System.Threading.WaitHandleCannotBeOpenedException
                    ' kill exception. retry wait and get sometime
                Catch
                    Throw
                End Try

                If 0 <= tmSleepUnit Then
                    Dim regPri As System.Threading.ThreadPriority = System.Threading.Thread.CurrentThread.Priority
                    System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Lowest
                    If tmSleepUnit < 100 Then
                        If 8 <= ctSleepScale Then
                            ctSleepScale = 0
                            tmNextSleep = tmSleepUnit
                        End If
                        System.Threading.Thread.CurrentThread.Join(tmNextSleep)
                        tmNextSleep += tmNextSleep
                        ctSleepScale += 1
                    Else
                        System.Threading.Thread.CurrentThread.Join(tmSleepUnit)
                    End If
                    System.Threading.Thread.CurrentThread.Priority = regPri
                End If

                If 0 <= ctSleepTry Then
                    ctTry += 1
                    If ctSleepTry <= ctTry Then Exit Do
                End If

            Loop

        End Function

    End Class
End Class

