Skip to content
This repository was archived by the owner on Nov 20, 2018. It is now read-only.

Commit 364a712

Browse files
committed
Merge branch 'lodejard/featurereferences' into dev
2 parents 161d6ca + c95d816 commit 364a712

15 files changed

+439
-670
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using Microsoft.AspNet.Http;
5+
using Microsoft.AspNet.Http.Features;
6+
using Microsoft.AspNet.Http.Internal;
7+
8+
namespace SampleApp
9+
{
10+
public class PooledHttpContext : DefaultHttpContext
11+
{
12+
DefaultHttpRequest _pooledHttpRequest;
13+
DefaultHttpResponse _pooledHttpResponse;
14+
15+
public PooledHttpContext(IFeatureCollection featureCollection) :
16+
base(featureCollection)
17+
{
18+
}
19+
20+
protected override HttpRequest InitializeHttpRequest()
21+
{
22+
if (_pooledHttpRequest != null)
23+
{
24+
_pooledHttpRequest.Initialize(this, Features);
25+
return _pooledHttpRequest;
26+
}
27+
28+
return new DefaultHttpRequest(this, Features);
29+
}
30+
31+
protected override void UninitializeHttpRequest(HttpRequest instance)
32+
{
33+
_pooledHttpRequest = instance as DefaultHttpRequest;
34+
_pooledHttpRequest?.Uninitialize();
35+
}
36+
37+
protected override HttpResponse InitializeHttpResponse()
38+
{
39+
if (_pooledHttpResponse != null)
40+
{
41+
_pooledHttpResponse.Initialize(this, Features);
42+
return _pooledHttpResponse;
43+
}
44+
45+
return new DefaultHttpResponse(this, Features);
46+
}
47+
48+
protected override void UninitializeHttpResponse(HttpResponse instance)
49+
{
50+
_pooledHttpResponse = instance as DefaultHttpResponse;
51+
_pooledHttpResponse?.Uninitialize();
52+
}
53+
}
54+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System.Collections.Generic;
5+
using Microsoft.AspNet.Http;
6+
using Microsoft.AspNet.Http.Features;
7+
8+
namespace SampleApp
9+
{
10+
public class PooledHttpContextFactory : IHttpContextFactory
11+
{
12+
private readonly IHttpContextAccessor _httpContextAccessor;
13+
private readonly Stack<PooledHttpContext> _pool = new Stack<PooledHttpContext>();
14+
15+
public PooledHttpContextFactory(IHttpContextAccessor httpContextAccessor)
16+
{
17+
_httpContextAccessor = httpContextAccessor;
18+
}
19+
20+
public HttpContext Create(IFeatureCollection featureCollection)
21+
{
22+
PooledHttpContext httpContext = null;
23+
lock (_pool)
24+
{
25+
if (_pool.Count != 0)
26+
{
27+
httpContext = _pool.Pop();
28+
}
29+
}
30+
31+
if (httpContext == null)
32+
{
33+
httpContext = new PooledHttpContext(featureCollection);
34+
}
35+
else
36+
{
37+
httpContext.Initialize(featureCollection);
38+
}
39+
40+
if (_httpContextAccessor != null)
41+
{
42+
_httpContextAccessor.HttpContext = httpContext;
43+
}
44+
return httpContext;
45+
}
46+
47+
public void Dispose(HttpContext httpContext)
48+
{
49+
if (_httpContextAccessor != null)
50+
{
51+
_httpContextAccessor.HttpContext = null;
52+
}
53+
54+
var pooled = httpContext as PooledHttpContext;
55+
if (pooled != null)
56+
{
57+
pooled.Uninitialize();
58+
lock (_pool)
59+
{
60+
_pool.Push(pooled);
61+
}
62+
}
63+
}
64+
}
65+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
6+
namespace Microsoft.AspNet.Http.Features
7+
{
8+
public struct FeatureReferences<TCache>
9+
{
10+
public FeatureReferences(IFeatureCollection collection)
11+
{
12+
Collection = collection;
13+
Cache = default(TCache);
14+
Revision = collection.Revision;
15+
}
16+
17+
public IFeatureCollection Collection { get; private set; }
18+
public int Revision { get; private set; }
19+
20+
// cache is a public field because the code calling Fetch must
21+
// be able to pass ref values that "dot through" the TCache struct memory,
22+
// if it was a Property then that getter would return a copy of the memory
23+
// preventing the use of "ref"
24+
public TCache Cache;
25+
26+
public TFeature Fetch<TFeature, TState>(
27+
ref TFeature cached,
28+
TState state,
29+
Func<TState, TFeature> factory)
30+
{
31+
var cleared = false;
32+
if (Revision != Collection.Revision)
33+
{
34+
cleared = true;
35+
Cache = default(TCache);
36+
Revision = Collection.Revision;
37+
}
38+
39+
var feature = cached;
40+
if (feature == null)
41+
{
42+
feature = Collection.Get<TFeature>();
43+
if (feature == null)
44+
{
45+
feature = factory(state);
46+
47+
Collection.Set(feature);
48+
if (!cleared)
49+
{
50+
Cache = default(TCache);
51+
}
52+
Revision = Collection.Revision;
53+
}
54+
cached = feature;
55+
}
56+
return feature;
57+
}
58+
59+
public TFeature Fetch<TFeature>(ref TFeature cached, Func<IFeatureCollection, TFeature> factory) =>
60+
Fetch(ref cached, Collection, factory);
61+
}
62+
}

src/Microsoft.AspNet.Http/Authentication/DefaultAuthenticationManager.cs

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -12,56 +12,27 @@
1212

1313
namespace Microsoft.AspNet.Http.Authentication.Internal
1414
{
15-
public class DefaultAuthenticationManager : AuthenticationManager, IFeatureCache
15+
public class DefaultAuthenticationManager : AuthenticationManager
1616
{
17-
private IFeatureCollection _features;
18-
private int _cachedFeaturesRevision = -1;
19-
20-
private IHttpAuthenticationFeature _authentication;
17+
private FeatureReferences<IHttpAuthenticationFeature> _features;
2118

2219
public DefaultAuthenticationManager(IFeatureCollection features)
2320
{
24-
_features = features;
25-
((IFeatureCache)this).SetFeaturesRevision();
26-
}
27-
28-
void IFeatureCache.CheckFeaturesRevision()
29-
{
30-
if (_cachedFeaturesRevision != _features.Revision)
31-
{
32-
ResetFeatures();
33-
}
34-
}
35-
36-
void IFeatureCache.SetFeaturesRevision()
37-
{
38-
_cachedFeaturesRevision = _features.Revision;
21+
Initialize(features);
3922
}
4023

41-
public void UpdateFeatures(IFeatureCollection features)
24+
public virtual void Initialize(IFeatureCollection features)
4225
{
43-
_features = features;
44-
ResetFeatures();
26+
_features = new FeatureReferences<IHttpAuthenticationFeature>(features);
4527
}
4628

47-
private void ResetFeatures()
29+
public virtual void Uninitialize()
4830
{
49-
_authentication = null;
50-
51-
((IFeatureCache)this).SetFeaturesRevision();
31+
_features = default(FeatureReferences<IHttpAuthenticationFeature>);
5232
}
5333

54-
private IHttpAuthenticationFeature HttpAuthenticationFeature
55-
{
56-
get
57-
{
58-
return FeatureHelpers.GetOrCreateAndCache(
59-
this,
60-
_features,
61-
() => new HttpAuthenticationFeature(),
62-
ref _authentication);
63-
}
64-
}
34+
private IHttpAuthenticationFeature HttpAuthenticationFeature =>
35+
_features.Fetch(ref _features.Cache, f => new HttpAuthenticationFeature());
6536

6637
public override IEnumerable<AuthenticationDescription> GetAuthenticationSchemes()
6738
{

src/Microsoft.AspNet.Http/DefaultConnectionInfo.cs

Lines changed: 17 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -10,70 +10,30 @@
1010

1111
namespace Microsoft.AspNet.Http.Internal
1212
{
13-
public class DefaultConnectionInfo : ConnectionInfo, IFeatureCache
13+
public class DefaultConnectionInfo : ConnectionInfo
1414
{
15-
private IFeatureCollection _features;
16-
private int _cachedFeaturesRevision = -1;
17-
18-
private IHttpConnectionFeature _connection;
19-
private ITlsConnectionFeature _tlsConnection;
15+
private FeatureReferences<FeatureInterfaces> _features;
2016

2117
public DefaultConnectionInfo(IFeatureCollection features)
2218
{
23-
_features = features;
24-
((IFeatureCache)this).SetFeaturesRevision();
25-
}
26-
27-
void IFeatureCache.CheckFeaturesRevision()
28-
{
29-
if (_cachedFeaturesRevision != _features.Revision)
30-
{
31-
ResetFeatures();
32-
}
19+
Initialize(features);
3320
}
3421

35-
void IFeatureCache.SetFeaturesRevision()
22+
public virtual void Initialize( IFeatureCollection features)
3623
{
37-
_cachedFeaturesRevision = _features.Revision;
24+
_features = new FeatureReferences<FeatureInterfaces>(features);
3825
}
3926

40-
public void UpdateFeatures(IFeatureCollection features)
27+
public virtual void Uninitialize()
4128
{
42-
_features = features;
43-
ResetFeatures();
29+
_features = default(FeatureReferences<FeatureInterfaces>);
4430
}
4531

46-
private void ResetFeatures()
47-
{
48-
_connection = null;
49-
_tlsConnection = null;
32+
private IHttpConnectionFeature HttpConnectionFeature =>
33+
_features.Fetch(ref _features.Cache.Connection, f => new HttpConnectionFeature());
5034

51-
((IFeatureCache)this).SetFeaturesRevision();
52-
}
53-
54-
private IHttpConnectionFeature HttpConnectionFeature
55-
{
56-
get
57-
{
58-
return FeatureHelpers.GetOrCreateAndCache(
59-
this,
60-
_features,
61-
() => new HttpConnectionFeature(),
62-
ref _connection);
63-
}
64-
}
65-
66-
private ITlsConnectionFeature TlsConnectionFeature
67-
{
68-
get
69-
{
70-
return FeatureHelpers.GetOrCreateAndCache(
71-
this,
72-
_features,
73-
() => new TlsConnectionFeature(),
74-
ref _tlsConnection);
75-
}
76-
}
35+
private ITlsConnectionFeature TlsConnectionFeature=>
36+
_features.Fetch(ref _features.Cache.TlsConnection, f => new TlsConnectionFeature());
7737

7838
public override IPAddress RemoteIpAddress
7939
{
@@ -115,5 +75,11 @@ public override X509Certificate2 ClientCertificate
11575
{
11676
return TlsConnectionFeature.GetClientCertificateAsync(cancellationToken);
11777
}
78+
79+
struct FeatureInterfaces
80+
{
81+
public IHttpConnectionFeature Connection;
82+
public ITlsConnectionFeature TlsConnection;
83+
}
11884
}
11985
}

0 commit comments

Comments
 (0)