189 lines
5.5 KiB
C#
189 lines
5.5 KiB
C#
|
//------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//------------------------------------------------------------
|
||
|
|
||
|
namespace System.ServiceModel.Channels
|
||
|
{
|
||
|
using System.Collections.Generic;
|
||
|
using System.Runtime;
|
||
|
using System.ServiceModel.Diagnostics;
|
||
|
|
||
|
abstract class InputQueueChannel<TDisposable> : ChannelBase
|
||
|
where TDisposable : class, IDisposable
|
||
|
{
|
||
|
InputQueue<TDisposable> inputQueue;
|
||
|
|
||
|
protected InputQueueChannel(ChannelManagerBase channelManager)
|
||
|
: base(channelManager)
|
||
|
{
|
||
|
this.inputQueue = TraceUtility.CreateInputQueue<TDisposable>();
|
||
|
}
|
||
|
|
||
|
public int InternalPendingItems
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.inputQueue.PendingCount;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public int PendingItems
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
ThrowIfDisposedOrNotOpen();
|
||
|
return InternalPendingItems;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void EnqueueAndDispatch(TDisposable item)
|
||
|
{
|
||
|
EnqueueAndDispatch(item, null);
|
||
|
}
|
||
|
|
||
|
public void EnqueueAndDispatch(TDisposable item, Action dequeuedCallback, bool canDispatchOnThisThread)
|
||
|
{
|
||
|
OnEnqueueItem(item);
|
||
|
|
||
|
// NOTE: don't need to check IsDisposed here: InputQueue will handle dispose
|
||
|
inputQueue.EnqueueAndDispatch(item, dequeuedCallback, canDispatchOnThisThread);
|
||
|
}
|
||
|
|
||
|
public void EnqueueAndDispatch(Exception exception, Action dequeuedCallback, bool canDispatchOnThisThread)
|
||
|
{
|
||
|
// NOTE: don't need to check IsDisposed here: InputQueue will handle dispose
|
||
|
inputQueue.EnqueueAndDispatch(exception, dequeuedCallback, canDispatchOnThisThread);
|
||
|
}
|
||
|
|
||
|
public void EnqueueAndDispatch(TDisposable item, Action dequeuedCallback)
|
||
|
{
|
||
|
OnEnqueueItem(item);
|
||
|
|
||
|
// NOTE: don't need to check IsDisposed here: InputQueue will handle dispose
|
||
|
inputQueue.EnqueueAndDispatch(item, dequeuedCallback);
|
||
|
}
|
||
|
|
||
|
public bool EnqueueWithoutDispatch(Exception exception, Action dequeuedCallback)
|
||
|
{
|
||
|
// NOTE: don't need to check IsDisposed here: InputQueue will handle dispose
|
||
|
return inputQueue.EnqueueWithoutDispatch(exception, dequeuedCallback);
|
||
|
}
|
||
|
|
||
|
public bool EnqueueWithoutDispatch(TDisposable item, Action dequeuedCallback)
|
||
|
{
|
||
|
OnEnqueueItem(item);
|
||
|
|
||
|
// NOTE: don't need to check IsDisposed here: InputQueue will handle dispose
|
||
|
return inputQueue.EnqueueWithoutDispatch(item, dequeuedCallback);
|
||
|
}
|
||
|
|
||
|
public void Dispatch()
|
||
|
{
|
||
|
// NOTE: don't need to check IsDisposed here: InputQueue will handle dispose
|
||
|
inputQueue.Dispatch();
|
||
|
}
|
||
|
|
||
|
public void Shutdown()
|
||
|
{
|
||
|
inputQueue.Shutdown();
|
||
|
}
|
||
|
|
||
|
protected override void OnFaulted()
|
||
|
{
|
||
|
base.OnFaulted();
|
||
|
inputQueue.Shutdown(() => this.GetPendingException());
|
||
|
}
|
||
|
|
||
|
protected virtual void OnEnqueueItem(TDisposable item)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected IAsyncResult BeginDequeue(TimeSpan timeout, AsyncCallback callback, object state)
|
||
|
{
|
||
|
this.ThrowIfNotOpened();
|
||
|
return inputQueue.BeginDequeue(timeout, callback, state);
|
||
|
}
|
||
|
|
||
|
protected bool EndDequeue(IAsyncResult result, out TDisposable item)
|
||
|
{
|
||
|
bool dequeued = inputQueue.EndDequeue(result, out item);
|
||
|
|
||
|
if (item == null)
|
||
|
{
|
||
|
this.ThrowIfFaulted();
|
||
|
this.ThrowIfAborted();
|
||
|
}
|
||
|
|
||
|
return dequeued;
|
||
|
}
|
||
|
|
||
|
protected bool Dequeue(TimeSpan timeout, out TDisposable item)
|
||
|
{
|
||
|
this.ThrowIfNotOpened();
|
||
|
bool dequeued = inputQueue.Dequeue(timeout, out item);
|
||
|
|
||
|
if (item == null)
|
||
|
{
|
||
|
this.ThrowIfFaulted();
|
||
|
this.ThrowIfAborted();
|
||
|
}
|
||
|
|
||
|
return dequeued;
|
||
|
}
|
||
|
|
||
|
protected bool WaitForItem(TimeSpan timeout)
|
||
|
{
|
||
|
this.ThrowIfNotOpened();
|
||
|
bool dequeued = inputQueue.WaitForItem(timeout);
|
||
|
|
||
|
this.ThrowIfFaulted();
|
||
|
this.ThrowIfAborted();
|
||
|
|
||
|
return dequeued;
|
||
|
}
|
||
|
|
||
|
protected IAsyncResult BeginWaitForItem(TimeSpan timeout, AsyncCallback callback, object state)
|
||
|
{
|
||
|
this.ThrowIfNotOpened();
|
||
|
return inputQueue.BeginWaitForItem(timeout, callback, state);
|
||
|
}
|
||
|
|
||
|
protected bool EndWaitForItem(IAsyncResult result)
|
||
|
{
|
||
|
bool dequeued = inputQueue.EndWaitForItem(result);
|
||
|
|
||
|
this.ThrowIfFaulted();
|
||
|
this.ThrowIfAborted();
|
||
|
|
||
|
return dequeued;
|
||
|
}
|
||
|
|
||
|
protected override void OnClosing()
|
||
|
{
|
||
|
base.OnClosing();
|
||
|
inputQueue.Shutdown(() => this.GetPendingException());
|
||
|
}
|
||
|
|
||
|
protected override void OnAbort()
|
||
|
{
|
||
|
inputQueue.Close();
|
||
|
}
|
||
|
|
||
|
protected override void OnClose(TimeSpan timeout)
|
||
|
{
|
||
|
inputQueue.Close();
|
||
|
}
|
||
|
|
||
|
protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
|
||
|
{
|
||
|
inputQueue.Close();
|
||
|
return new CompletedAsyncResult(callback, state);
|
||
|
}
|
||
|
|
||
|
protected override void OnEndClose(IAsyncResult result)
|
||
|
{
|
||
|
CompletedAsyncResult.End(result);
|
||
|
}
|
||
|
}
|
||
|
}
|