Imports Mercury.Mobile.Collections.Concurrent
Imports System.Threading

Namespace Threading

    ''' <summary>
    ''' Provides a single-threaded synchronization context.
    ''' </summary>
    ''' <remarks></remarks>
    Public Class SingleThreadSynchronizationContext
        Inherits ThreadSynchronizationContext

        Private ReadOnly _queue As BlockingQueue(Of KeyValuePair(Of ContextSendOrPostCallback, Object)) = New BlockingQueue(Of KeyValuePair(Of ContextSendOrPostCallback, Object))()
        Private ReadOnly _thread As Thread = Thread.CurrentThread

        ''' <summary>
        ''' Dispatches an asynchronous message to a synchronization context.
        ''' </summary>
        ''' <param name="d">The delegate to call.</param>
        ''' <param name="state">The object passed to the delegate.</param>
        ''' <remarks></remarks>
        Public Overrides Sub Post(d As ContextSendOrPostCallback, state As Object)
            If d Is Nothing Then _
                Throw New ArgumentNullException("d")
            Me._queue.Enqueue(New KeyValuePair(Of ContextSendOrPostCallback, Object)(d, state))
        End Sub

        ''' <summary>
        ''' Dispatches a synchronous message to a synchronization context.
        ''' </summary>
        ''' <param name="d">The delegate to call.</param>
        ''' <param name="state">The object passed to the delegate.</param>
        ''' <remarks></remarks>
        Public Overrides Sub Send(ByVal d As ContextSendOrPostCallback, ByVal state As Object)
            Throw New NotSupportedException("Synchronous send operations are not supported.")
        End Sub

        ''' <summary>
        ''' Processes all queued work on the current thread.
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub RunOnCurrentThread()
            For Each workItem In Me._queue.GetConsumingEnumerable()
                workItem.Key.Invoke(workItem.Value)
                'workItem.Key.BeginInvoke(workItem.Value, AddressOf _EndInvoke, workItem.Key)
            Next
        End Sub

        Private Shared Sub _EndInvoke(ByVal ar As IAsyncResult)
            Dim casted = TryCast(ar.AsyncState, ContextSendOrPostCallback)
            casted.EndInvoke(ar)
        End Sub

    End Class

End Namespace