Modified the Sweep method of WebSocketServiceManager class

This commit is contained in:
sta 2013-07-30 15:05:39 +09:00
parent 03e95638e3
commit ef17cabdd3
2 changed files with 166 additions and 141 deletions

View File

@ -64,6 +64,16 @@ namespace WebSocketSharp.Server {
#endregion #endregion
#region Internal Properties
internal WebSocket WebSocket {
get {
return _websocket;
}
}
#endregion
#region Protected Properties #region Protected Properties
/// <summary> /// <summary>

View File

@ -31,21 +31,21 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Timers; using System.Timers;
namespace WebSocketSharp.Server { namespace WebSocketSharp.Server
{
/// <summary> /// <summary>
/// Manages the collection of <see cref="WebSocketService"/> objects. /// Manages the collection of <see cref="WebSocketService"/> instances.
/// </summary> /// </summary>
public class WebSocketServiceManager { public class WebSocketServiceManager
{
#region Private Fields #region Private Fields
private object _forSweep; private object _forSweep;
private volatile bool _isStopped;
private volatile bool _isSweeping;
private Dictionary<string, WebSocketService> _services; private Dictionary<string, WebSocketService> _services;
private volatile bool _stopped;
private volatile bool _sweeping;
private Timer _sweepTimer; private Timer _sweepTimer;
private object _syncRoot; private object _sync;
#endregion #endregion
@ -54,10 +54,10 @@ namespace WebSocketSharp.Server {
internal WebSocketServiceManager () internal WebSocketServiceManager ()
{ {
_forSweep = new object (); _forSweep = new object ();
_isStopped = false;
_isSweeping = false;
_services = new Dictionary<string, WebSocketService> (); _services = new Dictionary<string, WebSocketService> ();
_syncRoot = new object(); _stopped = false;
_sweeping = false;
_sync = new object ();
setSweepTimer (); setSweepTimer ();
startSweepTimer (); startSweepTimer ();
@ -68,11 +68,12 @@ namespace WebSocketSharp.Server {
#region Public Properties #region Public Properties
/// <summary> /// <summary>
/// Gets the collection of IDs of active <see cref="WebSocketService"/> objects /// Gets the collection of IDs of active <see cref="WebSocketService"/> instances
/// managed by the <see cref="WebSocketServiceManager"/>. /// managed by the <see cref="WebSocketServiceManager"/>.
/// </summary> /// </summary>
/// <value> /// <value>
/// An IEnumerable&lt;string&gt; that contains the collection of IDs of active <see cref="WebSocketService"/> objects. /// An IEnumerable&lt;string&gt; that contains the collection of IDs
/// of active <see cref="WebSocketService"/> instances.
/// </value> /// </value>
public IEnumerable<string> ActiveIDs { public IEnumerable<string> ActiveIDs {
get { get {
@ -83,16 +84,16 @@ namespace WebSocketSharp.Server {
} }
/// <summary> /// <summary>
/// Gets the number of <see cref="WebSocketService"/> objects /// Gets the number of <see cref="WebSocketService"/> instances
/// managed by the <see cref="WebSocketServiceManager"/>. /// managed by the <see cref="WebSocketServiceManager"/>.
/// </summary> /// </summary>
/// <value> /// <value>
/// An <see cref="int"/> that contains the number of <see cref="WebSocketService"/> objects /// An <see cref="int"/> that contains the number of <see cref="WebSocketService"/> instances
/// managed by the <see cref="WebSocketServiceManager"/>. /// managed by the <see cref="WebSocketServiceManager"/>.
/// </value> /// </value>
public int Count { public int Count {
get { get {
lock (_syncRoot) lock (_sync)
{ {
return _services.Count; return _services.Count;
} }
@ -100,11 +101,29 @@ namespace WebSocketSharp.Server {
} }
/// <summary> /// <summary>
/// Gets the collection of IDs of inactive <see cref="WebSocketService"/> objects /// Gets the collection of IDs of <see cref="WebSocketService"/> instances
/// managed by the <see cref="WebSocketServiceManager"/>. /// managed by the <see cref="WebSocketServiceManager"/>.
/// </summary> /// </summary>
/// <value> /// <value>
/// An IEnumerable&lt;string&gt; that contains the collection of IDs of inactive <see cref="WebSocketService"/> objects. /// An IEnumerable&lt;string&gt; that contains the collection of IDs
/// of <see cref="WebSocketService"/> instances.
/// </value>
public IEnumerable<string> IDs {
get {
lock (_sync)
{
return _services.Keys;
}
}
}
/// <summary>
/// Gets the collection of IDs of inactive <see cref="WebSocketService"/> instances
/// managed by the <see cref="WebSocketServiceManager"/>.
/// </summary>
/// <value>
/// An IEnumerable&lt;string&gt; that contains the collection of IDs
/// of inactive <see cref="WebSocketService"/> instances.
/// </value> /// </value>
public IEnumerable<string> InactiveIDs { public IEnumerable<string> InactiveIDs {
get { get {
@ -114,29 +133,13 @@ namespace WebSocketSharp.Server {
} }
} }
/// <summary>
/// Gets the collection of IDs of <see cref="WebSocketService"/> objects
/// managed by the <see cref="WebSocketServiceManager"/>.
/// </summary>
/// <value>
/// An IEnumerable&lt;string&gt; that contains the collection of IDs of <see cref="WebSocketService"/> objects.
/// </value>
public IEnumerable<string> IDs {
get {
lock (_syncRoot)
{
return _services.Keys;
}
}
}
/// <summary> /// <summary>
/// Gets a value indicating whether the <see cref="WebSocketServiceManager"/> cleans up /// Gets a value indicating whether the <see cref="WebSocketServiceManager"/> cleans up
/// the inactive <see cref="WebSocketService"/> objects periodically. /// the inactive <see cref="WebSocketService"/> instances periodically.
/// </summary> /// </summary>
/// <value> /// <value>
/// <c>true</c> if the <see cref="WebSocketServiceManager"/> cleans up the inactive <see cref="WebSocketService"/> objects /// <c>true</c> if the <see cref="WebSocketServiceManager"/> cleans up
/// every 60 seconds; otherwise, <c>false</c>. /// the inactive <see cref="WebSocketService"/> instances every 60 seconds; otherwise, <c>false</c>.
/// </value> /// </value>
public bool Sweeping { public bool Sweeping {
get { get {
@ -144,10 +147,12 @@ namespace WebSocketSharp.Server {
} }
internal set { internal set {
if (value && !_isStopped) if (value)
{
if (!_stopped)
startSweepTimer (); startSweepTimer ();
}
if (!value) else
stopSweepTimer (); stopSweepTimer ();
} }
} }
@ -158,7 +163,7 @@ namespace WebSocketSharp.Server {
private void broadcast (byte [] data) private void broadcast (byte [] data)
{ {
lock (_syncRoot) lock (_sync)
{ {
foreach (var service in _services.Values) foreach (var service in _services.Values)
service.Send (data); service.Send (data);
@ -167,7 +172,7 @@ namespace WebSocketSharp.Server {
private void broadcast (string data) private void broadcast (string data)
{ {
lock (_syncRoot) lock (_sync)
{ {
foreach (var service in _services.Values) foreach (var service in _services.Values)
service.Send (data); service.Send (data);
@ -208,13 +213,13 @@ namespace WebSocketSharp.Server {
private Dictionary<string, WebSocketService> copy () private Dictionary<string, WebSocketService> copy ()
{ {
lock (_syncRoot) lock (_sync)
{ {
return new Dictionary<string, WebSocketService> (_services); return new Dictionary<string, WebSocketService> (_services);
} }
} }
private string createID() private static string createID ()
{ {
return Guid.NewGuid ().ToString ("N"); return Guid.NewGuid ().ToString ("N");
} }
@ -237,12 +242,12 @@ namespace WebSocketSharp.Server {
private void stop (ushort code, string reason, bool ignoreArgs) private void stop (ushort code, string reason, bool ignoreArgs)
{ {
stopSweepTimer (); stopSweepTimer ();
lock (_syncRoot) lock (_sync)
{ {
if (_isStopped) if (_stopped)
return; return;
_isStopped = true; _stopped = true;
foreach (var service in copy ().Values) foreach (var service in copy ().Values)
if (ignoreArgs) if (ignoreArgs)
service.Stop (); service.Stop ();
@ -263,9 +268,9 @@ namespace WebSocketSharp.Server {
internal string Add (WebSocketService service) internal string Add (WebSocketService service)
{ {
lock (_syncRoot) lock (_sync)
{ {
if (_isStopped) if (_stopped)
return null; return null;
var id = createID (); var id = createID ();
@ -277,7 +282,7 @@ namespace WebSocketSharp.Server {
internal bool Remove (string id) internal bool Remove (string id)
{ {
lock (_syncRoot) lock (_sync)
{ {
return _services.Remove (id); return _services.Remove (id);
} }
@ -303,45 +308,45 @@ namespace WebSocketSharp.Server {
#region Public Methods #region Public Methods
/// <summary> /// <summary>
/// Broadcasts the specified array of <see cref="byte"/> to the clients of every <see cref="WebSocketService"/> /// Broadcasts the specified array of <see cref="byte"/> to the clients of every
/// managed by the <see cref="WebSocketServiceManager"/>. /// <see cref="WebSocketService"/> instances managed by the <see cref="WebSocketServiceManager"/>.
/// </summary> /// </summary>
/// <param name="data"> /// <param name="data">
/// An array of <see cref="byte"/> to broadcast. /// An array of <see cref="byte"/> to broadcast.
/// </param> /// </param>
public void Broadcast (byte [] data) public void Broadcast (byte [] data)
{ {
if (_isStopped) if (_stopped)
broadcast (data); broadcast (data);
else else
broadcastAsync (data); broadcastAsync (data);
} }
/// <summary> /// <summary>
/// Broadcasts the specified <see cref="string"/> to the clients of every <see cref="WebSocketService"/> /// Broadcasts the specified <see cref="string"/> to the clients of every
/// managed by the <see cref="WebSocketServiceManager"/>. /// <see cref="WebSocketService"/> instances managed by the <see cref="WebSocketServiceManager"/>.
/// </summary> /// </summary>
/// <param name="data"> /// <param name="data">
/// A <see cref="string"/> to broadcast. /// A <see cref="string"/> to broadcast.
/// </param> /// </param>
public void Broadcast (string data) public void Broadcast (string data)
{ {
if (_isStopped) if (_stopped)
broadcast (data); broadcast (data);
else else
broadcastAsync (data); broadcastAsync (data);
} }
/// <summary> /// <summary>
/// Pings with the specified <see cref="string"/> to the clients of every <see cref="WebSocketService"/> /// Sends Pings with the specified <see cref="string"/> to the clients of every
/// managed by the <see cref="WebSocketServiceManager"/>. /// <see cref="WebSocketService"/> instances managed by the <see cref="WebSocketServiceManager"/>.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of IDs and values /// A Dictionary&lt;string, bool&gt; that contains the collection of IDs and values indicating
/// indicating whether each <see cref="WebSocketService"/> received a Pong in a time. /// whether each <see cref="WebSocketService"/> instances received a Pong in a time.
/// </returns> /// </returns>
/// <param name="message"> /// <param name="message">
/// A <see cref="string"/> that contains a message. /// A <see cref="string"/> that contains a message to send.
/// </param> /// </param>
public Dictionary<string, bool> Broadping (string message) public Dictionary<string, bool> Broadping (string message)
{ {
@ -353,51 +358,61 @@ namespace WebSocketSharp.Server {
} }
/// <summary> /// <summary>
/// Cleans up the inactive <see cref="WebSocketService"/> objects. /// Cleans up the inactive <see cref="WebSocketService"/> instances.
/// </summary> /// </summary>
public void Sweep () public void Sweep ()
{ {
if (_isStopped || _isSweeping || Count == 0) if (_stopped || _sweeping || Count == 0)
return; return;
lock (_forSweep) lock (_forSweep)
{ {
_isSweeping = true; _sweeping = true;
foreach (var id in InactiveIDs) foreach (var id in InactiveIDs)
{ {
lock (_syncRoot) lock (_sync)
{ {
if (_isStopped) if (_stopped)
{ {
_isSweeping = false; _sweeping = false;
return; return;
} }
WebSocketService service; WebSocketService service;
if (TryGetWebSocketService(id, out service)) if (_services.TryGetValue (id, out service))
{
var state = service.WebSocket.ReadyState;
if (state == WsState.OPEN)
service.Stop (CloseStatusCode.ABNORMAL, String.Empty); service.Stop (CloseStatusCode.ABNORMAL, String.Empty);
else if (state == WsState.CLOSING)
continue;
else
_services.Remove (id);
}
} }
} }
_isSweeping = false; _sweeping = false;
} }
} }
/// <summary> /// <summary>
/// Tries to get the <see cref="WebSocketService"/> associated with the specified <paramref name="id"/>. /// Tries to get the <see cref="WebSocketService"/> associated with the specified ID.
/// </summary> /// </summary>
/// <returns> /// <returns>
/// <c>true</c> if the <see cref="WebSocketServiceManager"/> manages the <see cref="WebSocketService"/> with the specified <paramref name="id"/>; otherwise, <c>false</c>. /// <c>true</c> if the <see cref="WebSocketServiceManager"/> manages the <see cref="WebSocketService"/>
/// with <paramref name="id"/>; otherwise, <c>false</c>.
/// </returns> /// </returns>
/// <param name="id"> /// <param name="id">
/// A <see cref="string"/> that contains the ID to find. /// A <see cref="string"/> that contains an ID to find.
/// </param> /// </param>
/// <param name="service"> /// <param name="service">
/// When this method returns, contains the <see cref="WebSocketService"/> with the specified <paramref name="id"/>, if the <paramref name="id"/> is found; otherwise, <see langword="null"/>. /// When this method returns, contains a <see cref="WebSocketService"/> with <paramref name="id"/>
/// if it is found; otherwise, <see langword="null"/>.
/// </param> /// </param>
public bool TryGetWebSocketService (string id, out WebSocketService service) public bool TryGetWebSocketService (string id, out WebSocketService service)
{ {
lock (_syncRoot) lock (_sync)
{ {
return _services.TryGetValue (id, out service); return _services.TryGetValue (id, out service);
} }