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

Commit df5b1aa

Browse files
committed
Improve DefaultHttpXxx default paths
1 parent 0da88e0 commit df5b1aa

File tree

8 files changed

+128
-126
lines changed

8 files changed

+128
-126
lines changed
Lines changed: 58 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,86 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
using System;
5+
using System.Collections.Generic;
6+
using System.Security.Claims;
7+
using System.Threading;
48
using Microsoft.AspNetCore.Http;
9+
using Microsoft.AspNetCore.Http.Authentication;
510
using Microsoft.AspNetCore.Http.Features;
6-
using Microsoft.AspNetCore.Http.Internal;
711

812
namespace SampleApp
913
{
10-
public class PooledHttpContext : DefaultHttpContext
14+
public sealed class PooledHttpContext : HttpContext
1115
{
12-
DefaultHttpRequest _pooledHttpRequest;
13-
DefaultHttpResponse _pooledHttpResponse;
16+
private readonly DefaultHttpContext _context;
1417

15-
public PooledHttpContext(IFeatureCollection featureCollection) :
16-
base(featureCollection)
18+
public PooledHttpContext(IFeatureCollection featureCollection)
1719
{
20+
_context = new DefaultHttpContext(featureCollection);
1821
}
1922

20-
protected override HttpRequest InitializeHttpRequest()
23+
public void Initialize(IFeatureCollection featureCollection)
2124
{
22-
if (_pooledHttpRequest != null)
23-
{
24-
_pooledHttpRequest.Initialize(this);
25-
return _pooledHttpRequest;
26-
}
25+
_context.Initialize(featureCollection);
26+
}
2727

28-
return new DefaultHttpRequest(this);
28+
public void Uninitialize()
29+
{
30+
_context.Uninitialize();
2931
}
3032

31-
protected override void UninitializeHttpRequest(HttpRequest instance)
33+
public override IFeatureCollection Features => _context.Features;
34+
35+
public override HttpRequest Request => _context.Request;
36+
37+
public override HttpResponse Response => _context.Response;
38+
39+
public override ConnectionInfo Connection => _context.Connection;
40+
41+
public override WebSocketManager WebSockets => _context.WebSockets;
42+
43+
public override AuthenticationManager Authentication => _context.Authentication;
44+
45+
public override ClaimsPrincipal User
3246
{
33-
_pooledHttpRequest = instance as DefaultHttpRequest;
34-
_pooledHttpRequest?.Uninitialize();
47+
get => _context.User;
48+
set => _context.User = value;
3549
}
3650

37-
protected override HttpResponse InitializeHttpResponse()
51+
public override IDictionary<object, object> Items
3852
{
39-
if (_pooledHttpResponse != null)
40-
{
41-
_pooledHttpResponse.Initialize(this);
42-
return _pooledHttpResponse;
43-
}
53+
get => _context.Items;
54+
set => _context.Items = value;
55+
}
4456

45-
return new DefaultHttpResponse(this);
57+
public override IServiceProvider RequestServices
58+
{
59+
get => _context.RequestServices;
60+
set => _context.RequestServices = value;
61+
}
62+
63+
public override CancellationToken RequestAborted
64+
{
65+
get => _context.RequestAborted;
66+
set => _context.RequestAborted = value;
67+
}
68+
69+
public override string TraceIdentifier
70+
{
71+
get => _context.TraceIdentifier;
72+
set => _context.TraceIdentifier = value;
73+
}
74+
75+
public override ISession Session
76+
{
77+
get => _context.Session;
78+
set => _context.Session = value;
4679
}
4780

48-
protected override void UninitializeHttpResponse(HttpResponse instance)
81+
public override void Abort()
4982
{
50-
_pooledHttpResponse = instance as DefaultHttpResponse;
51-
_pooledHttpResponse?.Uninitialize();
83+
_context.Abort();
5284
}
5385
}
5486
}

samples/SampleApp/PooledHttpContextFactory.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
using System;
55
using System.Collections.Generic;
6-
using System.Text;
76
using Microsoft.AspNetCore.Http;
87
using Microsoft.AspNetCore.Http.Features;
98
using Microsoft.Extensions.ObjectPool;

src/Microsoft.AspNetCore.Http.Features/FeatureReferences.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ public FeatureReferences(IFeatureCollection collection)
1515
Revision = collection.Revision;
1616
}
1717

18+
public FeatureReferences(IFeatureCollection collection, int featuresVersion)
19+
{
20+
Collection = collection;
21+
Cache = default(TCache);
22+
Revision = featuresVersion;
23+
}
24+
1825
public IFeatureCollection Collection { get; private set; }
1926
public int Revision { get; private set; }
2027

src/Microsoft.AspNetCore.Http/DefaultHttpContext.cs

Lines changed: 34 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Runtime.CompilerServices;
67
using System.Security.Claims;
78
using System.Threading;
89
using Microsoft.AspNetCore.Http.Authentication;
@@ -13,7 +14,7 @@
1314

1415
namespace Microsoft.AspNetCore.Http
1516
{
16-
public class DefaultHttpContext : HttpContext
17+
public sealed class DefaultHttpContext : HttpContext
1718
{
1819
// Lambdas hoisted to static readonly fields to improve inlining https://github.com/dotnet/roslyn/issues/13624
1920
private readonly static Func<IFeatureCollection, IItemsFeature> _newItemsFeature = f => new ItemsFeature();
@@ -26,8 +27,8 @@ public class DefaultHttpContext : HttpContext
2627

2728
private FeatureReferences<FeatureInterfaces> _features;
2829

29-
private HttpRequest _request;
30-
private HttpResponse _response;
30+
private DefaultHttpRequest _request;
31+
private DefaultHttpResponse _response;
3132
private AuthenticationManager _authenticationManager;
3233
private ConnectionInfo _connection;
3334
private WebSocketManager _websockets;
@@ -41,44 +42,22 @@ public DefaultHttpContext()
4142

4243
public DefaultHttpContext(IFeatureCollection features)
4344
{
44-
Initialize(features);
45-
}
45+
var featuresVersion = features.Revision;
4646

47-
public virtual void Initialize(IFeatureCollection features)
48-
{
49-
_features = new FeatureReferences<FeatureInterfaces>(features);
50-
_request = InitializeHttpRequest();
51-
_response = InitializeHttpResponse();
47+
// Speculatively populate always used features for current version
48+
_features = new FeatureReferences<FeatureInterfaces>(features, featuresVersion);
49+
_request = new DefaultHttpRequest(this, featuresVersion);
50+
_response = new DefaultHttpResponse(this, featuresVersion);
5251
}
5352

54-
public virtual void Uninitialize()
53+
public void Initialize(IFeatureCollection features)
5554
{
56-
_features = default(FeatureReferences<FeatureInterfaces>);
57-
if (_request != null)
58-
{
59-
UninitializeHttpRequest(_request);
60-
_request = null;
61-
}
62-
if (_response != null)
63-
{
64-
UninitializeHttpResponse(_response);
65-
_response = null;
66-
}
67-
if (_authenticationManager != null)
68-
{
69-
UninitializeAuthenticationManager(_authenticationManager);
70-
_authenticationManager = null;
71-
}
72-
if (_connection != null)
73-
{
74-
UninitializeConnectionInfo(_connection);
75-
_connection = null;
76-
}
77-
if (_websockets != null)
78-
{
79-
UninitializeWebSocketManager(_websockets);
80-
_websockets = null;
81-
}
55+
var featuresVersion = features.Revision;
56+
57+
// Speculatively populate always used features for current version
58+
_features = new FeatureReferences<FeatureInterfaces>(features, featuresVersion);
59+
_request.Initialize(features, featuresVersion);
60+
_response.Initialize(features, featuresVersion);
8261
}
8362

8463
private IItemsFeature ItemsFeature =>
@@ -109,11 +88,11 @@ public virtual void Uninitialize()
10988

11089
public override HttpResponse Response => _response;
11190

112-
public override ConnectionInfo Connection => _connection ?? (_connection = InitializeConnectionInfo());
91+
public override ConnectionInfo Connection => _connection ?? InitializeConnectionInfo();
11392

114-
public override AuthenticationManager Authentication => _authenticationManager ?? (_authenticationManager = InitializeAuthenticationManager());
93+
public override AuthenticationManager Authentication => _authenticationManager ?? InitializeAuthenticationManager();
11594

116-
public override WebSocketManager WebSockets => _websockets ?? (_websockets = InitializeWebSocketManager());
95+
public override WebSocketManager WebSockets => _websockets ?? InitializeWebSocketManager();
11796

11897

11998
public override ClaimsPrincipal User
@@ -180,21 +159,24 @@ public override void Abort()
180159
LifetimeFeature.Abort();
181160
}
182161

162+
[MethodImpl(MethodImplOptions.NoInlining)]
163+
private ConnectionInfo InitializeConnectionInfo() => (_connection = new DefaultConnectionInfo(Features));
183164

184-
protected virtual HttpRequest InitializeHttpRequest() => new DefaultHttpRequest(this);
185-
protected virtual void UninitializeHttpRequest(HttpRequest instance) { }
186-
187-
protected virtual HttpResponse InitializeHttpResponse() => new DefaultHttpResponse(this);
188-
protected virtual void UninitializeHttpResponse(HttpResponse instance) { }
165+
[MethodImpl(MethodImplOptions.NoInlining)]
166+
private AuthenticationManager InitializeAuthenticationManager() => (_authenticationManager = new DefaultAuthenticationManager(this));
189167

190-
protected virtual ConnectionInfo InitializeConnectionInfo() => new DefaultConnectionInfo(Features);
191-
protected virtual void UninitializeConnectionInfo(ConnectionInfo instance) { }
168+
[MethodImpl(MethodImplOptions.NoInlining)]
169+
private WebSocketManager InitializeWebSocketManager() => (_websockets = new DefaultWebSocketManager(Features));
192170

193-
protected virtual AuthenticationManager InitializeAuthenticationManager() => new DefaultAuthenticationManager(this);
194-
protected virtual void UninitializeAuthenticationManager(AuthenticationManager instance) { }
195-
196-
protected virtual WebSocketManager InitializeWebSocketManager() => new DefaultWebSocketManager(Features);
197-
protected virtual void UninitializeWebSocketManager(WebSocketManager instance) { }
171+
public void Uninitialize()
172+
{
173+
_features = default(FeatureReferences<FeatureInterfaces>);
174+
_request.Uninitialize();
175+
_response.Uninitialize();
176+
_authenticationManager = null;
177+
_connection = null;
178+
_websockets = null;
179+
}
198180

199181
struct FeatureInterfaces
200182
{

src/Microsoft.AspNetCore.Http/Internal/DefaultConnectionInfo.cs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
namespace Microsoft.AspNetCore.Http.Internal
1212
{
13-
public class DefaultConnectionInfo : ConnectionInfo
13+
public sealed class DefaultConnectionInfo : ConnectionInfo
1414
{
1515
// Lambdas hoisted to static readonly fields to improve inlining https://github.com/dotnet/roslyn/issues/13624
1616
private readonly static Func<IFeatureCollection, IHttpConnectionFeature> _newHttpConnectionFeature = f => new HttpConnectionFeature();
@@ -19,20 +19,10 @@ public class DefaultConnectionInfo : ConnectionInfo
1919
private FeatureReferences<FeatureInterfaces> _features;
2020

2121
public DefaultConnectionInfo(IFeatureCollection features)
22-
{
23-
Initialize(features);
24-
}
25-
26-
public virtual void Initialize( IFeatureCollection features)
2722
{
2823
_features = new FeatureReferences<FeatureInterfaces>(features);
2924
}
3025

31-
public virtual void Uninitialize()
32-
{
33-
_features = default(FeatureReferences<FeatureInterfaces>);
34-
}
35-
3626
private IHttpConnectionFeature HttpConnectionFeature =>
3727
_features.Fetch(ref _features.Cache.Connection, _newHttpConnectionFeature);
3828

src/Microsoft.AspNetCore.Http/Internal/DefaultHttpRequest.cs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,32 +10,28 @@
1010

1111
namespace Microsoft.AspNetCore.Http.Internal
1212
{
13-
public class DefaultHttpRequest : HttpRequest
13+
public sealed class DefaultHttpRequest : HttpRequest
1414
{
1515
// Lambdas hoisted to static readonly fields to improve inlining https://github.com/dotnet/roslyn/issues/13624
1616
private readonly static Func<IFeatureCollection, IHttpRequestFeature> _nullRequestFeature = f => null;
1717
private readonly static Func<IFeatureCollection, IQueryFeature> _newQueryFeature = f => new QueryFeature(f);
1818
private readonly static Func<HttpRequest, IFormFeature> _newFormFeature = r => new FormFeature(r);
1919
private readonly static Func<IFeatureCollection, IRequestCookiesFeature> _newRequestCookiesFeature = f => new RequestCookiesFeature(f);
2020

21-
private HttpContext _context;
21+
private readonly DefaultHttpContext _context;
2222
private FeatureReferences<FeatureInterfaces> _features;
2323

24-
public DefaultHttpRequest(HttpContext context)
25-
{
26-
Initialize(context);
27-
}
28-
29-
public virtual void Initialize(HttpContext context)
24+
public DefaultHttpRequest(DefaultHttpContext context, int featuresVersion)
3025
{
3126
_context = context;
32-
_features = new FeatureReferences<FeatureInterfaces>(context.Features);
27+
Initialize(context.Features, featuresVersion);
3328
}
3429

35-
public virtual void Uninitialize()
30+
public void Initialize(IFeatureCollection features, int featuresVersion)
3631
{
37-
_context = null;
38-
_features = default(FeatureReferences<FeatureInterfaces>);
32+
// Speculatively populate always used features for current version
33+
_features = new FeatureReferences<FeatureInterfaces>(features, featuresVersion);
34+
_features.Cache.Request = (IHttpRequestFeature)features[typeof(IHttpRequestFeature)];
3935
}
4036

4137
public override HttpContext HttpContext => _context;
@@ -151,6 +147,11 @@ public override Task<IFormCollection> ReadFormAsync(CancellationToken cancellati
151147
return FormFeature.ReadFormAsync(cancellationToken);
152148
}
153149

150+
public void Uninitialize()
151+
{
152+
_features = default(FeatureReferences<FeatureInterfaces>);
153+
}
154+
154155
struct FeatureInterfaces
155156
{
156157
public IHttpRequestFeature Request;

0 commit comments

Comments
 (0)