Permalink
Browse files

Fixed the thread safety problem with groups and the Connection.cs

Fixes #388, #537.
  • Loading branch information...
1 parent b51a414 commit 399fe592dd0d17dafb2144c714be96695a2cd568 @davidfowl davidfowl committed Jul 24, 2012
Showing with 107 additions and 5 deletions.
  1. +40 −0 SignalR.Tests/CountDown.cs
  2. +61 −0 SignalR.Tests/HubFacts.cs
  3. +1 −0 SignalR.Tests/SignalR.Tests.csproj
  4. +5 −5 SignalR/Connection.cs
View
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+
+namespace SignalR.Tests
+{
+ public class CountDown
+ {
+ private int _count;
+ private ManualResetEventSlim _wh = new ManualResetEventSlim(false);
+
+ public int Count
+ {
+ get
+ {
+ return _count;
+ }
+ }
+
+ public CountDown(int count)
+ {
+ _count = count;
+ }
+
+ public void Dec()
+ {
+ if (Interlocked.Decrement(ref _count) == 0)
+ {
+ _wh.Set();
+ }
+ }
+
+ public bool Wait(TimeSpan timeout)
+ {
+ return _wh.Wait(timeout);
+ }
+ }
+}
View
@@ -1,8 +1,11 @@
using System;
+using System.Linq;
using System.Threading;
+using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using SignalR.Client.Hubs;
using SignalR.Hosting.Memory;
+using SignalR.Hubs;
using Xunit;
namespace SignalR.Tests
@@ -272,5 +275,63 @@ public void CreateProxyAfterConnectionStartsThrows()
connection.Stop();
}
}
+
+ [Fact]
+ public void AddingToMultipleGroups()
+ {
+ var host = new MemoryHost();
+ host.MapHubs();
+ int max = 100;
+
+ var countDown = new CountDown(max);
+ var list = Enumerable.Range(0, max).ToList();
+ var connection = new Client.Hubs.HubConnection("http://foo");
+ var proxy = connection.CreateProxy("MultGroupHub");
+
+ proxy.On<User>("onRoomJoin", user =>
+ {
+ lock (list)
+ {
+ list.Remove(user.Index);
+ }
+
+ countDown.Dec();
+ });
+
+ connection.Start(host).Wait();
+
+ for (int i = 0; i < max; i++)
+ {
+ proxy.Invoke("login", new User { Index = i, Name = "tester", Room = "test" + i }).Wait();
+ }
+
+ Assert.True(countDown.Wait(TimeSpan.FromSeconds(10)), "Didn't receive " + max + " messages. Got " + (max - countDown.Count) + " missed " + String.Join(",", list.Select(i => i.ToString())));
+
+ connection.Stop();
+ }
+
+ public class MultGroupHub : Hub
+ {
+ public Task Login(User user)
+ {
+ return Task.Factory.StartNew(
+ () =>
+ {
+ Groups.Remove(Context.ConnectionId, "foo").Wait();
+ Groups.Add(Context.ConnectionId, "foo").Wait();
+
+ Groups.Remove(Context.ConnectionId, user.Name).Wait();
+ Groups.Add(Context.ConnectionId, user.Name).Wait();
+ Clients[user.Name].onRoomJoin(user).Wait();
+ });
+ }
+ }
+
+ public class User
+ {
+ public int Index { get; set; }
+ public string Name { get; set; }
+ public string Room { get; set; }
+ }
}
}
@@ -56,6 +56,7 @@
</Compile>
<Compile Include="ChunkBufferFacts.cs" />
<Compile Include="ConnectionFacts.cs" />
+ <Compile Include="CountDown.cs" />
<Compile Include="DefaultHubResolverTest.cs" />
<Compile Include="DisconnectFacts.cs" />
<Compile Include="EventSourceStreamReaderFacts.cs" />
View
@@ -15,7 +15,7 @@ public class Connection : IConnection, ITransportConnection
private readonly string _baseSignal;
private readonly string _connectionId;
private readonly HashSet<string> _signals;
- private readonly HashSet<string> _groups;
+ private readonly SafeSet<string> _groups;
private readonly ITraceManager _trace;
private bool _disconnected;
private bool _aborted;
@@ -33,15 +33,15 @@ public class Connection : IConnection, ITransportConnection
_baseSignal = baseSignal;
_connectionId = connectionId;
_signals = new HashSet<string>(signals);
- _groups = new HashSet<string>(groups);
+ _groups = new SafeSet<string>(groups);
_trace = traceManager;
}
private IEnumerable<string> Signals
{
get
{
- return _signals.Concat(_groups);
+ return _signals.Concat(_groups.GetSnapshot());
}
}
@@ -152,9 +152,9 @@ private Task SendMessage(string key, object value)
private void PopulateResponseState(PersistentResponse response)
{
// Set the groups on the outgoing transport data
- if (_groups.Any())
+ if (_groups.Count > 0)
{
- response.TransportData["Groups"] = _groups;
+ response.TransportData["Groups"] = _groups.GetSnapshot();
}
}

0 comments on commit 399fe59

Please sign in to comment.