Skip to content

Commit eca3213

Browse files
authored
fix concurrent collection modification issue (#62)
1 parent c73b027 commit eca3213

File tree

6 files changed

+19
-16
lines changed

6 files changed

+19
-16
lines changed

Analytics-CSharp/Analytics-CSharp.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
</ItemGroup>
4040
<ItemGroup>
4141
<PackageReference Include="Coroutine.NET" Version="1.3.0" />
42-
<PackageReference Include="Serialization.NET" Version="1.3.0" />
42+
<PackageReference Include="Serialization.NET" Version="1.4.0" />
4343
<PackageReference Include="Sovran.NET" Version="1.3.0" />
4444
</ItemGroup>
4545
<ItemGroup>

Analytics-CSharp/Segment/Analytics/Configuration.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Segment.Analytics.Policies;
44
using Segment.Analytics.Utilities;
55
using Segment.Concurrent;
6+
using Segment.Serialization;
67

78
namespace Segment.Analytics
89
{
@@ -94,7 +95,7 @@ public Configuration(string writeKey,
9495
AnalyticsErrorHandler = analyticsErrorHandler;
9596
StorageProvider = storageProvider ?? new DefaultStorageProvider();
9697
HttpClientProvider = httpClientProvider ?? new DefaultHTTPClientProvider();
97-
FlushPolicies = flushPolicies ?? new List<IFlushPolicy>();
98+
FlushPolicies = flushPolicies == null ? new ConcurrentList<IFlushPolicy>() : new ConcurrentList<IFlushPolicy>(flushPolicies);
9899
if (FlushPolicies.Count == 0)
99100
{
100101
FlushPolicies.Add(new CountFlushPolicy(flushAt));

Analytics-CSharp/Segment/Analytics/Timeline.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Collections.Concurrent;
12
using System.Reflection;
23
using global::System;
34
using global::System.Collections.Generic;
@@ -12,15 +13,15 @@ namespace Segment.Analytics
1213
/// </summary>
1314
public class Timeline
1415
{
15-
internal Dictionary<PluginType, Mediator> _plugins;
16+
internal IDictionary<PluginType, Mediator> _plugins;
1617

17-
public Timeline() => _plugins = new Dictionary<PluginType, Mediator>()
18+
public Timeline() => _plugins = new ConcurrentDictionary<PluginType, Mediator>
1819
{
19-
{ PluginType.Before, new Mediator() },
20-
{ PluginType.Enrichment, new Mediator() },
21-
{ PluginType.Destination, new Mediator() },
22-
{ PluginType.After, new Mediator() },
23-
{ PluginType.Utility, new Mediator() }
20+
[PluginType.Before] = new Mediator(),
21+
[PluginType.Enrichment] = new Mediator(),
22+
[PluginType.Destination] = new Mediator(),
23+
[PluginType.After] = new Mediator(),
24+
[PluginType.Utility] = new Mediator()
2425
};
2526

2627
/// <summary>

Analytics-CSharp/Segment/Analytics/Utilities/UserPrefs.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,6 @@ private long CommitToMemory()
620620
if (!copyToDisk.ContainsKey(k))
621621
{
622622
continue;
623-
;
624623
}
625624

626625
copyToDisk.Remove(k);

Samples/UnitySample/LifecyclePlugin.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ public void OnError(Exception error)
5656
/// </summary>
5757
public class Lifecycle : Singleton<Lifecycle>, IObservable<Lifecycle.State>
5858
{
59-
private readonly List<IObserver<State>> _observers = new List<IObserver<State>>();
59+
// use Segment's ConcurrentList to avoid modification during enumeration
60+
// or you have to make a copy for iterating the observers.
61+
private readonly IList<IObserver<State>> _observers = new ConcurrentList<IObserver<State>>();
6062

6163
private const string AppVersionKey = "app_version";
6264

@@ -122,10 +124,10 @@ public IDisposable Subscribe(IObserver<State> observer)
122124

123125
private class Unsubscriber : IDisposable
124126
{
125-
private List<IObserver<State>> _observers;
127+
private IList<IObserver<State>> _observers;
126128
private IObserver<State> _observer;
127129

128-
public Unsubscriber(List<IObserver<State>> observers, IObserver<State> observer)
130+
public Unsubscriber(IList<IObserver<State>> observers, IObserver<State> observer)
129131
{
130132
_observers = observers;
131133
_observer = observer;

Samples/UnitySample/UnitySample.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@
3333
</PropertyGroup>
3434
<ItemGroup>
3535
<Reference Include="Coroutine.NET, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
36-
<HintPath>..\..\packages\Coroutine.NET.1.1.0\lib\netstandard2.0\Coroutine.NET.dll</HintPath>
36+
<HintPath>..\..\packages\Coroutine.NET.1.3.0\lib\netstandard2.0\Coroutine.NET.dll</HintPath>
3737
</Reference>
3838
<Reference Include="Serialization.NET">
39-
<HintPath>..\..\..\..\.nuget\packages\serialization.net\1.2.0\lib\netstandard2.0\Serialization.NET.dll</HintPath>
39+
<HintPath>..\..\..\..\.nuget\packages\serialization.net\1.4.0\lib\netstandard2.0\Serialization.NET.dll</HintPath>
4040
</Reference>
4141
<Reference Include="System" />
4242
<Reference Include="System.Core" />
@@ -59,7 +59,7 @@
5959
</ProjectReference>
6060
</ItemGroup>
6161
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
62-
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
62+
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
6363
Other similar extension points exist, see Microsoft.Common.targets.
6464
<Target Name="BeforeBuild">
6565
</Target>

0 commit comments

Comments
 (0)