2 // ChannelListenerBase.cs
4 // Author: Atsushi Enomoto (atsushi@ximian.com)
6 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
8 // Permission is hereby granted, free of charge, to any person obtaining
9 // a copy of this software and associated documentation files (the
10 // "Software"), to deal in the Software without restriction, including
11 // without limitation the rights to use, copy, modify, merge, publish,
12 // distribute, sublicense, and/or sell copies of the Software, and to
13 // permit persons to whom the Software is furnished to do so, subject to
14 // the following conditions:
16 // The above copyright notice and this permission notice shall be
17 // included in all copies or substantial portions of the Software.
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 using System.Collections.Generic;
29 using System.ServiceModel;
30 using System.Threading;
32 namespace System.ServiceModel.Channels
34 internal abstract class InternalChannelListenerBase<TChannel>
35 : ChannelListenerBase<TChannel>
36 where TChannel : class, IChannel
38 protected InternalChannelListenerBase ()
43 protected InternalChannelListenerBase (IDefaultCommunicationTimeouts timeouts)
48 Func<TimeSpan,TChannel> accept_channel_delegate;
49 Func<TimeSpan,bool> wait_delegate;
50 Action<TimeSpan> open_delegate, close_delegate;
52 protected Thread CurrentAsyncThread { get; private set; }
53 protected IAsyncResult CurrentAsyncResult { get; private set; }
55 protected override void OnAbort ()
57 if (CurrentAsyncThread != null)
58 CurrentAsyncThread.Abort (); // it is not beautiful but there is no other way to stop it.
61 protected override void OnClose (TimeSpan timeout)
63 if (CurrentAsyncThread != null)
64 if (!CancelAsync (timeout))
65 if (CurrentAsyncThread != null) // being careful
66 CurrentAsyncThread.Abort (); // it is not beautiful but there is no other way to stop it.
69 // cancel ongoing async operations and return if it was
70 // completed successfully. If not, it will abort.
71 public virtual bool CancelAsync (TimeSpan timeout)
73 return CurrentAsyncResult == null || CurrentAsyncResult.AsyncWaitHandle.WaitOne (timeout);
76 protected override IAsyncResult OnBeginAcceptChannel (
77 TimeSpan timeout, AsyncCallback callback,
80 //if (CurrentAsyncResult != null)
81 // throw new InvalidOperationException ("Another AcceptChannel operation is in progress");
83 ManualResetEvent wait = new ManualResetEvent (false);
85 if (accept_channel_delegate == null)
86 accept_channel_delegate = new Func<TimeSpan,TChannel> (delegate (TimeSpan tout) {
87 wait.WaitOne (); // make sure that CurrentAsyncResult is set.
88 CurrentAsyncThread = Thread.CurrentThread;
91 return OnAcceptChannel (tout);
93 CurrentAsyncThread = null;
94 CurrentAsyncResult = null;
98 CurrentAsyncResult = accept_channel_delegate.BeginInvoke (timeout, callback, asyncState);
100 return CurrentAsyncResult;
103 protected override TChannel OnEndAcceptChannel (IAsyncResult result)
105 if (accept_channel_delegate == null)
106 throw new InvalidOperationException ("Async AcceptChannel operation has not started");
107 // FIXME: what's wrong with this?
108 //if (CurrentAsyncResult == null)
109 // throw new InvalidOperationException ("Async AcceptChannel operation has not started. Argument result was: " + result);
110 return accept_channel_delegate.EndInvoke (result);
113 protected override IAsyncResult OnBeginWaitForChannel (
114 TimeSpan timeout, AsyncCallback callback, object state)
116 if (wait_delegate == null)
117 wait_delegate = new Func<TimeSpan,bool> (OnWaitForChannel);
118 return wait_delegate.BeginInvoke (timeout, callback, state);
121 protected override bool OnEndWaitForChannel (IAsyncResult result)
123 if (wait_delegate == null)
124 throw new InvalidOperationException ("Async WaitForChannel operation has not started");
125 return wait_delegate.EndInvoke (result);
128 protected override IAsyncResult OnBeginOpen (TimeSpan timeout,
129 AsyncCallback callback, object state)
131 if (open_delegate == null)
132 open_delegate = new Action<TimeSpan> (OnOpen);
133 return open_delegate.BeginInvoke (timeout, callback, state);
136 protected override void OnEndOpen (IAsyncResult result)
138 if (open_delegate == null)
139 throw new InvalidOperationException ("Async Open operation has not started");
140 open_delegate.EndInvoke (result);
143 protected override IAsyncResult OnBeginClose (TimeSpan timeout,
144 AsyncCallback callback, object state)
146 if (close_delegate == null)
147 close_delegate = new Action<TimeSpan> (OnClose);
148 return close_delegate.BeginInvoke (timeout, callback, state);
151 protected override void OnEndClose (IAsyncResult result)
153 if (close_delegate == null)
154 throw new InvalidOperationException ("Async Close operation has not started");
155 close_delegate.EndInvoke (result);
159 public abstract class ChannelListenerBase<TChannel>
160 : ChannelListenerBase, IChannelListener<TChannel>,
161 IChannelListener, ICommunicationObject
162 where TChannel : class, IChannel
164 IDefaultCommunicationTimeouts timeouts;
166 protected ChannelListenerBase ()
167 : this (DefaultCommunicationTimeouts.Instance)
171 protected ChannelListenerBase (
172 IDefaultCommunicationTimeouts timeouts)
174 if (timeouts == null)
175 throw new ArgumentNullException ("timeouts");
176 this.timeouts = timeouts;
179 public TChannel AcceptChannel ()
181 return AcceptChannel (timeouts.ReceiveTimeout);
184 public TChannel AcceptChannel (TimeSpan timeout)
186 ThrowIfDisposedOrNotOpen ();
187 return OnAcceptChannel (timeout);
190 public IAsyncResult BeginAcceptChannel (
191 AsyncCallback callback, object asyncState)
193 return BeginAcceptChannel (
194 timeouts.ReceiveTimeout, callback, asyncState);
197 public IAsyncResult BeginAcceptChannel (TimeSpan timeout,
198 AsyncCallback callback, object asyncState)
200 return OnBeginAcceptChannel (timeout, callback, asyncState);
203 public TChannel EndAcceptChannel (IAsyncResult result)
205 return OnEndAcceptChannel (result);
208 protected abstract TChannel OnAcceptChannel (TimeSpan timeout);
210 protected abstract IAsyncResult OnBeginAcceptChannel (TimeSpan timeout,
211 AsyncCallback callback, object asyncState);
213 protected abstract TChannel OnEndAcceptChannel (IAsyncResult result);