10
10
using System . Collections . Generic ;
11
11
using System . Diagnostics ;
12
12
using System . Threading ;
13
- using JavaScriptEngineSwitcher . Core ;
14
13
using JSPool . Exceptions ;
15
14
16
15
namespace JSPool
@@ -19,24 +18,24 @@ namespace JSPool
19
18
/// Handles acquiring JavaScript engines from a shared pool. This class is thread-safe.
20
19
/// </summary>
21
20
[ DebuggerDisplay ( "{DebuggerDisplay,nq}" ) ]
22
- public class JsPool : IJsPool
21
+ public class JsPool < T > : IJsPool < T >
23
22
{
24
23
/// <summary>
25
24
/// Configuration for this engine pool.
26
25
/// </summary>
27
- protected readonly JsPoolConfig _config ;
26
+ protected readonly JsPoolConfig < T > _config ;
28
27
/// <summary>
29
28
/// Engines that are currently available for use.
30
29
/// </summary>
31
- protected readonly BlockingCollection < IJsEngine > _availableEngines = new BlockingCollection < IJsEngine > ( ) ;
30
+ protected readonly BlockingCollection < T > _availableEngines = new BlockingCollection < T > ( ) ;
32
31
/// <summary>
33
32
/// Metadata for the engines. Total number of engines that have been created is reflected in its Count.
34
33
/// </summary>
35
- protected readonly IDictionary < IJsEngine , EngineMetadata > _metadata = new ConcurrentDictionary < IJsEngine , EngineMetadata > ( ) ;
34
+ protected readonly IDictionary < T , EngineMetadata > _metadata = new ConcurrentDictionary < T , EngineMetadata > ( ) ;
36
35
/// <summary>
37
36
/// Factory method used to create engines.
38
37
/// </summary>
39
- protected readonly Func < IJsEngine > _engineFactory ;
38
+ protected readonly Func < T > _engineFactory ;
40
39
/// <summary>
41
40
/// Handles watching for changes to files, to recycle the engines if any related files change.
42
41
/// </summary>
@@ -62,9 +61,9 @@ public class JsPool : IJsPool
62
61
/// <param name="config">
63
62
/// The configuration to use. If not provided, a default configuration will be used.
64
63
/// </param>
65
- public JsPool ( JsPoolConfig config = null )
64
+ public JsPool ( JsPoolConfig < T > config )
66
65
{
67
- _config = config ?? new JsPoolConfig ( ) ;
66
+ _config = config ;
68
67
_engineFactory = CreateEngineFactory ( ) ;
69
68
PopulateEngines ( ) ;
70
69
InitializeWatcher ( ) ;
@@ -73,21 +72,9 @@ public JsPool(JsPoolConfig config = null)
73
72
/// <summary>
74
73
/// Gets a factory method used to create engines.
75
74
/// </summary>
76
- protected virtual Func < IJsEngine > CreateEngineFactory ( )
75
+ protected virtual Func < T > CreateEngineFactory ( )
77
76
{
78
- using ( var tempEngine = _config . EngineFactory ( ) )
79
- {
80
- if ( ! tempEngine . NeedsOwnThread ( ) )
81
- {
82
- // Engine is fine with being accessed across multiple threads, we can just
83
- // return its factory directly.
84
- return _config . EngineFactory ;
85
- }
86
- // Engine needs special treatment. This is the case with the MSIE engine, which
87
- // can only be accessed from the thread it was created on. In this case we need
88
- // to create the engine in a separate thread and marshall the requests across.
89
- return ( ) => new JsEngineWithOwnThread ( _config . EngineFactory , _cancellationTokenSource . Token ) ;
90
- }
77
+ return _config . EngineFactory ;
91
78
}
92
79
93
80
/// <summary>
@@ -122,7 +109,7 @@ protected virtual void PopulateEngines()
122
109
/// <summary>
123
110
/// Creates a new JavaScript engine and adds it to the list of all available engines.
124
111
/// </summary>
125
- protected virtual IJsEngine CreateEngine ( )
112
+ protected virtual T CreateEngine ( )
126
113
{
127
114
var engine = _engineFactory ( ) ;
128
115
_config . Initializer ( engine ) ;
@@ -146,9 +133,9 @@ protected virtual IJsEngine CreateEngine()
146
133
/// <exception cref="JsPoolExhaustedException">
147
134
/// Thrown if no engines are available in the pool within the provided timeout period.
148
135
/// </exception>
149
- public virtual IJsEngine GetEngine ( TimeSpan ? timeout = null )
136
+ public virtual T GetEngine ( TimeSpan ? timeout = null )
150
137
{
151
- IJsEngine engine ;
138
+ T engine ;
152
139
153
140
// First see if a pooled engine is immediately available
154
141
if ( _availableEngines . TryTake ( out engine ) )
@@ -183,7 +170,7 @@ public virtual IJsEngine GetEngine(TimeSpan? timeout = null)
183
170
/// Marks the specified engine as "in use"
184
171
/// </summary>
185
172
/// <param name="engine"></param>
186
- private IJsEngine TakeEngine ( IJsEngine engine )
173
+ private T TakeEngine ( T engine )
187
174
{
188
175
var metadata = _metadata [ engine ] ;
189
176
metadata . InUse = true ;
@@ -195,15 +182,18 @@ private IJsEngine TakeEngine(IJsEngine engine)
195
182
/// Returns an engine to the pool so it can be reused
196
183
/// </summary>
197
184
/// <param name="engine">Engine to return</param>
198
- public virtual void ReturnEngineToPool ( IJsEngine engine )
185
+ public virtual void ReturnEngineToPool ( T engine )
199
186
{
200
187
EngineMetadata metadata ;
201
188
if ( ! _metadata . TryGetValue ( engine , out metadata ) )
202
189
{
203
190
// This engine was from another pool. This could happen if a pool is recycled
204
191
// and replaced with a different one (like what ReactJS.NET does when any
205
192
// loaded files change). Let's just pretend we never saw it.
206
- engine . Dispose ( ) ;
193
+ if ( engine is IDisposable )
194
+ {
195
+ ( ( IDisposable ) engine ) . Dispose ( ) ;
196
+ }
207
197
return ;
208
198
}
209
199
@@ -218,11 +208,10 @@ public virtual void ReturnEngineToPool(IJsEngine engine)
218
208
219
209
if (
220
210
_config . GarbageCollectionInterval > 0 &&
221
- usageCount % _config . GarbageCollectionInterval == 0 &&
222
- engine . SupportsGarbageCollection ( )
211
+ metadata . UsageCount % _config . GarbageCollectionInterval == 0
223
212
)
224
213
{
225
- engine . CollectGarbage ( ) ;
214
+ CollectGarbage ( engine ) ;
226
215
}
227
216
228
217
_availableEngines . Add ( engine ) ;
@@ -235,9 +224,12 @@ public virtual void ReturnEngineToPool(IJsEngine engine)
235
224
/// <param name="repopulateEngines">
236
225
/// If <c>true</c>, a new engine will be created to replace the disposed engine
237
226
/// </param>
238
- public virtual void DisposeEngine ( IJsEngine engine , bool repopulateEngines = true )
227
+ public virtual void DisposeEngine ( T engine , bool repopulateEngines = true )
239
228
{
240
- engine . Dispose ( ) ;
229
+ if ( engine is IDisposable )
230
+ {
231
+ ( ( IDisposable ) engine ) . Dispose ( ) ;
232
+ }
241
233
_metadata . Remove ( engine ) ;
242
234
243
235
if ( repopulateEngines )
@@ -254,7 +246,7 @@ public virtual void DisposeEngine(IJsEngine engine, bool repopulateEngines = tru
254
246
/// </summary>
255
247
protected virtual void DisposeAllEngines ( )
256
248
{
257
- IJsEngine engine ;
249
+ T engine ;
258
250
while ( _availableEngines . TryTake ( out engine ) )
259
251
{
260
252
DisposeEngine ( engine , repopulateEngines : false ) ;
@@ -290,6 +282,15 @@ public virtual void Dispose()
290
282
_fileWatcher . Dispose ( ) ;
291
283
}
292
284
}
285
+
286
+ /// <summary>
287
+ /// Runs garbage collection for the specified engine
288
+ /// </summary>
289
+ /// <param name="engine"></param>
290
+ protected virtual void CollectGarbage ( T engine )
291
+ {
292
+ // No-op by default
293
+ }
293
294
294
295
#region Statistics and debugging
295
296
/// <summary>
0 commit comments