Imports System.Threading

Namespace Threading

    ''' <summary>
    ''' A default synchronization context for a thread.
    ''' </summary>
    ''' <remarks></remarks>
    Public Class ThreadSynchronizationContext
        Implements ISynchronizationContext

        ''' <summary>
        ''' Gets the synchronization context for the current thread.
        ''' </summary>
        ''' <returns>A <see cref="ThreadSynchronizationContext"/> representing the current synchronization context.</returns>
        ''' <remarks></remarks>
        Public Shared ReadOnly Property Current() As ThreadSynchronizationContext
            Get
                Dim slot = Thread.GetNamedDataSlot(ThreadSynchronizationContext.ContextDataSlotName)
                If (Thread.GetData(slot) Is Nothing) Then
                    ThreadSynchronizationContext.SetSynchronizationContextInternal(New ThreadSynchronizationContext())
                End If
                Return TryCast(Thread.GetData(slot), ThreadSynchronizationContext)
            End Get
        End Property

        ''' <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 Overridable Sub Post(ByVal d As ContextSendOrPostCallback, ByVal state As Object) Implements ISynchronizationContext.Post
            ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf d.Invoke), 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 Overridable Sub Send(ByVal d As ContextSendOrPostCallback, ByVal state As Object) Implements ISynchronizationContext.Send
            d(state)
        End Sub

        ''' <summary>
        ''' Sets the current synchronization context.
        ''' </summary>
        ''' <param name="syncContext">The <see cref="ThreadSynchronizationContext"/> object to be set.</param>
        ''' <remarks></remarks>
        Public Shared Sub SetSynchronizationContext(ByVal syncContext As ThreadSynchronizationContext)
            ThreadSynchronizationContext.SetSynchronizationContextInternal(syncContext)
        End Sub

        Friend Shared Sub SetSynchronizationContextInternal(ByVal syncContext As ThreadSynchronizationContext)
            Dim slot As LocalDataStoreSlot = Nothing
            slot = Thread.GetNamedDataSlot(ThreadSynchronizationContext.ContextDataSlotName)
            Thread.SetData(slot, syncContext)
        End Sub

        Friend Shared ReadOnly ContextDataSlotName As String = "__mercury_threadcontext"

    End Class

End Namespace