Source/TNLPriority.m (258 lines of code) (raw):
//
// TNLPriority.m
// TwitterNetworkLayer
//
// Created on 7/17/14.
// Copyright © 2020 Twitter. All rights reserved.
//
#import <sys/sysctl.h>
#import "TNL_Project.h"
#import "TNLPriority.h"
NS_ASSUME_NONNULL_BEGIN
TNLPriority TNLConvertQueuePriorityToTNLPriority(NSOperationQueuePriority pri)
{
switch (pri) {
case NSOperationQueuePriorityVeryLow:
return TNLPriorityVeryLow;
case NSOperationQueuePriorityLow:
return TNLPriorityLow;
case NSOperationQueuePriorityNormal:
return TNLPriorityNormal;
case NSOperationQueuePriorityHigh:
return TNLPriorityHigh;
case NSOperationQueuePriorityVeryHigh:
return TNLPriorityVeryHigh;
default:
break;
}
if (pri < NSOperationQueuePriorityVeryLow) {
return TNLPriorityVeryLow;
}
if (pri < NSOperationQueuePriorityNormal) {
return TNLPriorityLow;
}
if (pri > NSOperationQueuePriorityVeryHigh) {
return TNLPriorityVeryHigh;
}
if (pri > NSOperationQueuePriorityNormal) {
return TNLPriorityHigh;
}
TNLAssertNever();
return TNLPriorityNormal;
}
static const float sFloatPriorityBucketOffset = 0.1f;
static const float sFloatPriorityBucketSize = (1.0f - (2.0f * sFloatPriorityBucketOffset)) / 5.0f;
TNLPriority TNLConvertURLSessionTaskPriorityToTNLPriority(float pri)
{
if (pri < sFloatPriorityBucketOffset + sFloatPriorityBucketSize) {
return TNLPriorityVeryLow;
} else if (pri < sFloatPriorityBucketOffset + (sFloatPriorityBucketSize * 2.0f)) {
return TNLPriorityLow;
} else if (pri < sFloatPriorityBucketOffset + (sFloatPriorityBucketSize * 3.0f)) {
return TNLPriorityNormal;
} else if (pri < sFloatPriorityBucketOffset + (sFloatPriorityBucketSize * 4.0f)) {
return TNLPriorityHigh;
}
return TNLPriorityVeryHigh;
}
TNLPriority TNLConvertQualityOfServiceToTNLPriority(NSQualityOfService qos)
{
if (qos == NSQualityOfServiceDefault) {
qos = (NSQualityOfServiceUserInitiated + NSQualityOfServiceUtility) / 2;
}
// Below I will denote how much of the range of possibilities remain with comments
// [] == bounded inclusive
// () == bounded exclusive
// Example:
// [Val1...Val2) == "from Val1 inclusive to Val2 exclusive"
// [INF...INF]
if (qos > NSQualityOfServiceUserInitiated) {
return TNLPriorityVeryHigh + 1;
}
// [INF...UserInitiated]
if (qos < NSQualityOfServiceBackground) {
return TNLPriorityVeryLow - 1;
}
// [Background...UserInitiated]
if (qos < NSQualityOfServiceUtility) {
return TNLPriorityVeryLow;
}
// [Utility...UserInitiated]
if (qos == NSQualityOfServiceUtility) {
return TNLPriorityLow;
}
// (Utility...UserInitiated]
if (qos <= ((NSQualityOfServiceUserInitiated + NSQualityOfServiceUtility) / 2)) {
return TNLPriorityNormal;
}
// (Default...UserInitiated]
return TNLPriorityHigh;
}
TNLPriority TNLConvertGCDQOSToTNLPriority(qos_class_t gcdQOS)
{
if (gcdQOS == QOS_CLASS_DEFAULT) {
return (QOS_CLASS_USER_INITIATED + QOS_CLASS_UTILITY) / 2;
}
// Below I will denote how much of the range of possibilities remain with comments
// [] == bounded inclusive
// () == bounded exclusive
// Example:
// [Val1...Val2) == "from Val1 inclusive to Val2 exclusive"
// [INF...INF]
if (gcdQOS > QOS_CLASS_USER_INITIATED) {
return TNLPriorityVeryHigh + 1;
}
// [INF...UserInitiated]
if (gcdQOS < QOS_CLASS_BACKGROUND) {
return TNLPriorityVeryLow - 1;
}
// [Background...UserInitiated]
if (gcdQOS < QOS_CLASS_UTILITY) {
return TNLPriorityVeryLow;
}
// [Utility...UserInitiated]
if (gcdQOS == QOS_CLASS_UTILITY) {
return TNLPriorityLow;
}
// (Utility...UserInitiated]
if (gcdQOS <= ((QOS_CLASS_USER_INITIATED + QOS_CLASS_UTILITY) / 2)) {
return TNLPriorityNormal;
}
// (Default...UserInitiated]
return TNLPriorityHigh;
}
TNLPriority TNLConvertGCDPriorityToTNLPriority(dispatch_queue_priority_t priority)
{
if (priority == DISPATCH_QUEUE_PRIORITY_DEFAULT) {
return TNLPriorityNormal;
}
if (priority > DISPATCH_QUEUE_PRIORITY_HIGH) {
return TNLPriorityVeryHigh;
}
if (priority > DISPATCH_QUEUE_PRIORITY_DEFAULT) {
return TNLPriorityHigh;
}
if (priority < DISPATCH_QUEUE_PRIORITY_LOW) {
return TNLPriorityVeryLow;
}
if (priority < DISPATCH_QUEUE_PRIORITY_DEFAULT) {
return TNLPriorityLow;
}
TNLAssertNever();
return TNLPriorityNormal;
}
NSOperationQueuePriority TNLConvertTNLPriorityToQueuePriority(TNLPriority pri)
{
switch (pri) {
case TNLPriorityVeryLow:
return NSOperationQueuePriorityVeryLow;
case TNLPriorityLow:
return NSOperationQueuePriorityLow;
case TNLPriorityNormal:
return NSOperationQueuePriorityNormal;
case TNLPriorityHigh:
return NSOperationQueuePriorityHigh;
case TNLPriorityVeryHigh:
return NSOperationQueuePriorityVeryHigh;
default:
break;
}
if (pri < TNLPriorityVeryLow) {
return NSOperationQueuePriorityVeryLow;
}
if (pri > TNLPriorityVeryHigh) {
return NSOperationQueuePriorityVeryHigh;
}
TNLAssertNever();
return NSOperationQueuePriorityNormal;
}
dispatch_queue_priority_t TNLConvertTNLPriorityToGCDPriority(TNLPriority pri)
{
switch (pri) {
case TNLPriorityVeryHigh:
return DISPATCH_QUEUE_PRIORITY_HIGH + 1;
case TNLPriorityHigh:
return DISPATCH_QUEUE_PRIORITY_HIGH;
case TNLPriorityNormal:
return DISPATCH_QUEUE_PRIORITY_DEFAULT;
case TNLPriorityLow:
return DISPATCH_QUEUE_PRIORITY_LOW;
case TNLPriorityVeryLow:
return DISPATCH_QUEUE_PRIORITY_BACKGROUND;
default:
break;
}
if (pri > TNLPriorityVeryHigh) {
return DISPATCH_QUEUE_PRIORITY_HIGH + 2;
}
if (pri < TNLPriorityVeryLow) {
return DISPATCH_QUEUE_PRIORITY_BACKGROUND;
}
TNLAssertNever();
return DISPATCH_QUEUE_PRIORITY_DEFAULT;
}
float TNLConvertTNLPriorityToURLSessionTaskPriority(TNLPriority pri)
{
switch (pri) {
case TNLPriorityVeryLow:
return 0.1f;
case TNLPriorityLow:
return 0.3f;
case TNLPriorityNormal:
return 0.5f;
case TNLPriorityHigh:
return 0.7f;
case TNLPriorityVeryHigh:
return 0.9f;
default:
break;
}
TNLStaticAssert(0.1f < sFloatPriorityBucketOffset + sFloatPriorityBucketSize, Miss_Matched_Priority_Buckets);
TNLStaticAssert(0.3f < sFloatPriorityBucketOffset + (sFloatPriorityBucketSize * 2.0), Miss_Matched_Priority_Buckets);
TNLStaticAssert(0.5f < sFloatPriorityBucketOffset + (sFloatPriorityBucketSize * 3.0), Miss_Matched_Priority_Buckets);
TNLStaticAssert(0.7f < sFloatPriorityBucketOffset + (sFloatPriorityBucketSize * 4.0), Miss_Matched_Priority_Buckets);
TNLStaticAssert(0.9f > sFloatPriorityBucketOffset + (sFloatPriorityBucketSize * 4.0), Miss_Matched_Priority_Buckets);
if (pri < TNLPriorityVeryLow) {
return 0.0f;
}
if (pri > TNLPriorityVeryHigh) {
return 1.0f;
}
TNLAssertNever();
return 0.5f;
}
NSQualityOfService TNLConvertTNLPriorityToQualityOfService(TNLPriority pri)
{
/*
VLo Lo Nml Hi VHi
-2 -1 0 1 2
9 17 21 25 33
Bg Uti UIni UInt
*/
switch (pri) {
case TNLPriorityVeryHigh:
return NSQualityOfServiceUserInteractive;
case TNLPriorityHigh:
return NSQualityOfServiceUserInitiated;
case TNLPriorityNormal:
return ((NSQualityOfServiceUserInitiated - NSQualityOfServiceUtility) / 2) + NSQualityOfServiceUtility;
case TNLPriorityLow:
return NSQualityOfServiceUtility;
case TNLPriorityVeryLow:
return NSQualityOfServiceBackground;
default:
break;
}
if (pri < TNLPriorityVeryLow) {
return NSQualityOfServiceBackground - 1;
}
if (pri > TNLPriorityVeryHigh) {
return NSQualityOfServiceUserInteractive + 1;
}
TNLAssertNever();
return NSQualityOfServiceDefault;
}
qos_class_t TNLConvertTNLPriorityToGCDQOS(TNLPriority pri)
{
switch (pri) {
case TNLPriorityVeryLow:
return QOS_CLASS_BACKGROUND;
case TNLPriorityLow:
return QOS_CLASS_UTILITY;
case TNLPriorityHigh:
return QOS_CLASS_USER_INITIATED;
case TNLPriorityVeryHigh:
return QOS_CLASS_USER_INTERACTIVE;
case TNLPriorityNormal:
return QOS_CLASS_DEFAULT;
default:
break;
}
if (pri < TNLPriorityVeryLow) {
return QOS_CLASS_BACKGROUND;
} else if (pri > TNLPriorityVeryHigh) {
return QOS_CLASS_USER_INTERACTIVE;
}
TNLAssertNever();
return QOS_CLASS_DEFAULT;
}
NSTimeInterval TNLDeferrableIntervalForPriority(TNLPriority pri)
{
switch (pri) {
case TNLPriorityVeryLow:
return 60.0;
case TNLPriorityLow:
return 10.0;
case TNLPriorityNormal:
case TNLPriorityHigh:
case TNLPriorityVeryHigh:
break;
}
return 0.0;
}
NS_ASSUME_NONNULL_END