Skip to content

Commit 7784003

Browse files
author
Alex Peck
committed
outline
1 parent 47a547e commit 7784003

File tree

1 file changed

+32
-5
lines changed

1 file changed

+32
-5
lines changed

BitFaster.Caching/Atomic/AtomicFactory.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Diagnostics;
4+
using System.Diagnostics.CodeAnalysis;
5+
using System.Runtime.ExceptionServices;
46
using System.Threading;
57

68
namespace BitFaster.Caching.Atomic
@@ -98,8 +100,17 @@ private V CreateValue<TFactory>(K key, TFactory valueFactory) where TFactory : s
98100

99101
if (init != null)
100102
{
101-
value = init.CreateValue(key, valueFactory);
102-
Volatile.Write(ref initializer, null); // volatile write must occur after setting value
103+
try
104+
{
105+
value = init.CreateValue(key, valueFactory);
106+
Volatile.Write(ref initializer, null); // volatile write must occur after setting value
107+
}
108+
catch
109+
{
110+
// Overwrite the initializer with a fresh copy. New threads will start from a clean state.
111+
Volatile.Write(ref initializer, new Initializer());
112+
throw;
113+
}
103114
}
104115

105116
return value;
@@ -138,6 +149,7 @@ private class Initializer
138149
{
139150
private bool isInitialized;
140151
private V value;
152+
private ExceptionDispatchInfo exceptionDispatch;
141153

142154
public V CreateValue<TFactory>(K key, TFactory valueFactory) where TFactory : struct, IValueFactory<K, V>
143155
{
@@ -148,9 +160,24 @@ public V CreateValue<TFactory>(K key, TFactory valueFactory) where TFactory : st
148160
return value;
149161
}
150162

151-
value = valueFactory.Create(key);
152-
isInitialized = true;
153-
return value;
163+
// If a previous thread called the factory and failed, throw the same error instead
164+
// of calling the factory again.
165+
if (exceptionDispatch != null)
166+
{
167+
exceptionDispatch.Throw();
168+
}
169+
170+
try
171+
{
172+
value = valueFactory.Create(key);
173+
isInitialized = true;
174+
return value;
175+
}
176+
catch (Exception ex)
177+
{
178+
exceptionDispatch = ExceptionDispatchInfo.Capture(ex);
179+
throw;
180+
}
154181
}
155182
}
156183
}

0 commit comments

Comments
 (0)