' *
' * 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 Class TaskQueueingThread

            Public Delegate Sub TaskHandler(ByVal SenderIsStopRequested As SignalHandler)

            Public Interface ITask
                Sub Task(ByVal SenderIsStopRequested As SignalHandler)
            End Interface

            Public Property Priority As System.Threading.ThreadPriority
                Set(ByVal value As System.Threading.ThreadPriority)
                    SyncLock m_WorkQueue
                        If Not m_hThread Is Nothing Then m_hThread.Priority = value
                    End SyncLock
                End Set
                Get
                    SyncLock m_WorkQueue
                        Priority = System.Threading.ThreadPriority.Normal
                        If Not m_hThread Is Nothing Then Priority = m_hThread.Priority
                    End SyncLock
                End Get
            End Property

            Public ReadOnly Property IsWorkOut() As Boolean
                Get
                    SyncLock m_WorkQueue
                        IsWorkOut = (m_hThread Is Nothing OrElse m_hThread.IsAlive = False)
                    End SyncLock
                End Get
            End Property

            Public Function IsStopRequested() As Boolean
                SyncLock m_WorkQueue
                    IsStopRequested = m_IsStopRequested
                End SyncLock
            End Function

            Public Function StopRequest(Optional ByVal isWaitForExit As Boolean = False) As Boolean
                Dim hLocal As System.Threading.Thread = Nothing
                SyncLock m_WorkQueue
                    If m_IsExecuting And (m_hThread IsNot Nothing AndAlso m_hThread.IsAlive) Then m_IsStopRequested = True
                    StopRequest = m_IsStopRequested
                    If isWaitForExit Then
                        hLocal = m_hThread
                        m_hThread = Nothing
                    End If
                End SyncLock
                If hLocal IsNot Nothing Then hLocal.Join()
            End Function

            Public Sub Clear()
                SyncLock m_WorkQueue
                    m_WorkQueue.Clear()
                End SyncLock
            End Sub

            Public Sub Enqueue(ByVal item As TaskHandler)

                Dim hLocal As System.Threading.Thread = Nothing

                SyncLock m_WorkQueue

                    If item IsNot Nothing Then m_WorkQueue.Enqueue(item)

                    If 0 < m_WorkQueue.Count And m_IsExecuting = False Then
                        If m_hThread IsNot Nothing Then hLocal = m_hThread
                        m_IsStopRequested = False
                        m_IsExecuting = True
                        m_hThread = New System.Threading.Thread(AddressOf Execute)
                        m_hThread.Start()
                    End If

                End SyncLock

                If hLocal IsNot Nothing Then hLocal.Join()

            End Sub

            Public Sub Enqueue(ByVal item As ITask)
                If item IsNot Nothing Then Enqueue(AddressOf item.Task)
            End Sub

            Public Sub Enqueue(ByVal items As System.Collections.Generic.IEnumerable(Of ITask))
                Dim ary As New System.Collections.Generic.List(Of TaskHandler)

                Dim hLocal As System.Threading.Thread = Nothing

                SyncLock m_WorkQueue

                    If items IsNot Nothing Then
                        For Each item As ITask In items
                            If item IsNot Nothing Then m_WorkQueue.Enqueue(AddressOf item.Task)
                        Next
                    End If

                    If 0 < m_WorkQueue.Count And m_IsExecuting = False Then
                        If m_hThread IsNot Nothing Then hLocal = m_hThread
                        m_IsStopRequested = False
                        m_IsExecuting = True
                        m_hThread = New System.Threading.Thread(AddressOf Execute)
                        m_hThread.Start()
                    End If

                End SyncLock

                If hLocal IsNot Nothing Then hLocal.Join()

            End Sub

            Private m_hThread As System.Threading.Thread = Nothing
            Private m_IsExecuting As Boolean = False
            Private m_IsStopRequested As Boolean = False
            Private ReadOnly m_WorkQueue As New System.Collections.Generic.Queue(Of TaskHandler)

            Private Sub Execute() ' enqueued task execute loop

                Dim d As SignalHandler = AddressOf IsStopRequested
                Dim Item As TaskHandler = Nothing
                Do
                    SyncLock m_WorkQueue
                        If m_WorkQueue.Count <= 0 Or m_IsStopRequested Then
                            m_IsExecuting = False
                            Exit Do
                        Else
                            Item = m_WorkQueue.Dequeue
                        End If
                    End SyncLock
                    If Item IsNot Nothing Then Item(d)
                Loop

            End Sub

        End Class

    End Class
End Class
