Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Jit] Proposal: Non-shared generics #9682

Open
benaadams opened this issue Feb 7, 2018 · 2 comments
Open

[Jit] Proposal: Non-shared generics #9682

benaadams opened this issue Feb 7, 2018 · 2 comments

Comments

@benaadams
Copy link
Member

Proposal

[MethodImpl(MethodImplOptions.NonSharedGeneric)] 

If you had for example aspnet/KestrelHttpServer#2290

TFeature IFeatureCollection.Get<TFeature>()
{
    TFeature feature;
    if (typeof(TFeature) == typeof(IHttpRequestFeature))
    {
        feature = (TFeature)_currentIHttpRequestFeature;
    }
    else if (typeof(TFeature) == typeof(IHttpResponseFeature))
    {
        feature = (TFeature)_currentIHttpResponseFeature;
    }
    else if (typeof(TFeature) == typeof(IHttpRequestIdentifierFeature))
    {
        feature = (TFeature)_currentIHttpRequestIdentifierFeature;
    }
    else if (typeof(TFeature) == typeof(IServiceProvidersFeature))
    {
        feature = (TFeature)_currentIServiceProvidersFeature;
    }
    else if (typeof(TFeature) == typeof(IHttpRequestLifetimeFeature))
    {
        feature = (TFeature)_currentIHttpRequestLifetimeFeature;
    }
    else if (typeof(TFeature) == typeof(IHttpConnectionFeature))
    {
        feature = (TFeature)_currentIHttpConnectionFeature;
    }
    else if (typeof(TFeature) == typeof(IHttpAuthenticationFeature))
    {
        feature = (TFeature)_currentIHttpAuthenticationFeature;
    }
    else if (typeof(TFeature) == typeof(IQueryFeature))
    {
        feature = (TFeature)_currentIQueryFeature;
    }
    else if (typeof(TFeature) == typeof(IFormFeature))
    {
        feature = (TFeature)_currentIFormFeature;
    }
    else if (typeof(TFeature) == typeof(IHttpUpgradeFeature))
    {
        feature = (TFeature)_currentIHttpUpgradeFeature;
    }
    else if (typeof(TFeature) == typeof(IHttp2StreamIdFeature))
    {
        feature = (TFeature)_currentIHttp2StreamIdFeature;
    }
    else if (typeof(TFeature) == typeof(IResponseCookiesFeature))
    {
        feature = (TFeature)_currentIResponseCookiesFeature;
    }
    else if (typeof(TFeature) == typeof(IItemsFeature))
    {
        feature = (TFeature)_currentIItemsFeature;
    }
    else if (typeof(TFeature) == typeof(ITlsConnectionFeature))
    {
        feature = (TFeature)_currentITlsConnectionFeature;
    }
    else if (typeof(TFeature) == typeof(IHttpWebSocketFeature))
    {
        feature = (TFeature)_currentIHttpWebSocketFeature;
    }
    else if (typeof(TFeature) == typeof(ISessionFeature))
    {
        feature = (TFeature)_currentISessionFeature;
    }
    else if (typeof(TFeature) == typeof(IHttpMaxRequestBodySizeFeature))
    {
        feature = (TFeature)_currentIHttpMaxRequestBodySizeFeature;
    }
    else if (typeof(TFeature) == typeof(IHttpMinRequestBodyDataRateFeature))
    {
        feature = (TFeature)_currentIHttpMinRequestBodyDataRateFeature;
    }
    else if (typeof(TFeature) == typeof(IHttpMinResponseDataRateFeature))
    {
        feature = (TFeature)_currentIHttpMinResponseDataRateFeature;
    }
    else if (typeof(TFeature) == typeof(IHttpBodyControlFeature))
    {
        feature = (TFeature)_currentIHttpBodyControlFeature;
    }
    else if (typeof(TFeature) == typeof(IHttpSendFileFeature))
    {
        feature = (TFeature)_currentIHttpSendFileFeature;
    }
    else
    {
        feature = (TFeature)(ExtraFeatureGet(typeof(TFeature)));
    }

    if (feature != null)
    {
        return feature;
    }

    return (TFeature)ConnectionFeatures[typeof(TFeature)];
}

and you marked it with this MethodImplOptions.NonSharedGeneric it would elide all the type checks for classes/interfaces as it does for structs meaning it would turn into a branchless function (and create an implementation for every TFeature type it was called with).

Still performance issues with it being an interface generic method IFeatureCollection.Get<TFeature>(); but better performance...

public interface IFeatureCollection : IEnumerable<KeyValuePair<Type, object>>
{
    bool IsReadOnly { get; }
    int Revision { get; }
    object this[Type key] { get; set; }
    TFeature Get<TFeature>();
    void Set<TFeature>(TFeature instance);
}
@tannergooding
Copy link
Member

tannergooding commented Nov 6, 2018

Would it perhaps be worthwhile for the attribute to take a list of types that generic specialization for reference types would be valid for (ex: [GenericSpecialization(typeof(string))] or [GenericSpecialization(typeof(IHttpRequestFeature), typeof(IHttpResponseFeature))])?

I could imagine there being cases where you only want to specialize a handful of types and you want everything else to take the same code-path (such as if other types are unsupported)...

@benaadams
Copy link
Member Author

Makes sense; something like?

public class GenericSpecializationAttribute : Attribute
{
    public GenericSpecializationAttribute();
    public GenericSpecializationAttribute(params Type[] types);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Development

No branches or pull requests

6 participants