Skip to content
This repository has been archived by the owner on Nov 1, 2021. It is now read-only.

Commit

Permalink
Merge pull request #87 from kgoodier/review/absolute-time
Browse files Browse the repository at this point in the history
Avoid use of CFAbsoluteTime as much as possible.
  • Loading branch information
goaway committed Nov 27, 2014
2 parents 02160a4 + d6d7a01 commit bb02228
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 32 deletions.
30 changes: 25 additions & 5 deletions SPDY.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,18 @@
5C2229591952257800CAF160 /* SPDYURLRequestTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C2229581952257800CAF160 /* SPDYURLRequestTest.m */; };
5C2A211D19F9CA0E00D0EA76 /* SPDYLoggingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C2A211C19F9CA0E00D0EA76 /* SPDYLoggingTest.m */; };
5C427F0F1A1C7C4D0072403D /* SPDYSenTestLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C427F0E1A1C7C4D0072403D /* SPDYSenTestLog.m */; };
5C427F111A1D57890072403D /* SPDYStopwatchTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C427F101A1D57890072403D /* SPDYStopwatchTest.m */; };
5CF0A2C91A089BC500B6D141 /* SPDYMetadataTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CF0A2C81A089BC500B6D141 /* SPDYMetadataTest.m */; };
5CF0A2CC1A0952D900B6D141 /* SPDYMockURLProtocolClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CF0A2CB1A0952D900B6D141 /* SPDYMockURLProtocolClient.m */; };
7774C1318AB029C6BCEF84D6 /* SPDYSessionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7774C2026A4DE9957D75F629 /* SPDYSessionTest.m */; };
7774C1F1E544793907908882 /* SPDYMockFrameEncoderDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7774C69089A6978113F0C275 /* SPDYMockFrameEncoderDelegate.m */; };
7774C868441241542B0A90C0 /* SPDYStopwatch.m in Sources */ = {isa = PBXBuildFile; fileRef = 7774CE34A3AA067D98DA7ECC /* SPDYStopwatch.m */; };
7774CA1FA1F4A59CA0906BB7 /* SPDYSocket+SPDYSocketMock.m in Sources */ = {isa = PBXBuildFile; fileRef = 7774C0ECD0C6E5D73FB38752 /* SPDYSocket+SPDYSocketMock.m */; };
7774CC29BBD86413798C1425 /* SPDYStopwatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 7774CE030BB898D2BE3D320D /* SPDYStopwatch.h */; };
7774CD12A73EA9ABAE521441 /* SPDYStopwatch.m in Sources */ = {isa = PBXBuildFile; fileRef = 7774CE34A3AA067D98DA7ECC /* SPDYStopwatch.m */; };
7774CD9416661E40D76713F5 /* SPDYStopwatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 7774CE030BB898D2BE3D320D /* SPDYStopwatch.h */; };
7774CDD84A5D07F8DE5B8684 /* SPDYStopwatch.m in Sources */ = {isa = PBXBuildFile; fileRef = 7774CE34A3AA067D98DA7ECC /* SPDYStopwatch.m */; };
7774CF887055793F373F0D5E /* SPDYStopwatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 7774CE030BB898D2BE3D320D /* SPDYStopwatch.h */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand Down Expand Up @@ -152,6 +159,7 @@
5C2229581952257800CAF160 /* SPDYURLRequestTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPDYURLRequestTest.m; sourceTree = "<group>"; };
5C2A211C19F9CA0E00D0EA76 /* SPDYLoggingTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPDYLoggingTest.m; sourceTree = "<group>"; };
5C427F0E1A1C7C4D0072403D /* SPDYSenTestLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPDYSenTestLog.m; sourceTree = "<group>"; };
5C427F101A1D57890072403D /* SPDYStopwatchTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPDYStopwatchTest.m; sourceTree = "<group>"; };
5CF0A2C81A089BC500B6D141 /* SPDYMetadataTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPDYMetadataTest.m; sourceTree = "<group>"; };
5CF0A2CA1A0952BA00B6D141 /* SPDYMockURLProtocolClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPDYMockURLProtocolClient.h; sourceTree = "<group>"; };
5CF0A2CB1A0952D900B6D141 /* SPDYMockURLProtocolClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPDYMockURLProtocolClient.m; sourceTree = "<group>"; };
Expand All @@ -160,6 +168,8 @@
7774C69089A6978113F0C275 /* SPDYMockFrameEncoderDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPDYMockFrameEncoderDelegate.m; sourceTree = "<group>"; };
7774C7E1AF717FC36B7F15B6 /* SPDYSocket+SPDYSocketMock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SPDYSocket+SPDYSocketMock.h"; sourceTree = "<group>"; };
7774CD0A3295C8E314D6E3FF /* SPDYMockFrameEncoderDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPDYMockFrameEncoderDelegate.h; sourceTree = "<group>"; };
7774CE030BB898D2BE3D320D /* SPDYStopwatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPDYStopwatch.h; sourceTree = "<group>"; };
7774CE34A3AA067D98DA7ECC /* SPDYStopwatch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPDYStopwatch.m; sourceTree = "<group>"; };
D2CC14B216179B43002E37CF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
D2CC14B816179B43002E37CF /* SPDY-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SPDY-Prefix.pch"; sourceTree = "<group>"; };
D2CC14C01618CF62002E37CF /* SPDYProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPDYProtocol.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -234,6 +244,7 @@
0679F3CE186217FC006F122E /* SPDYOriginTest.m */,
25959A3E1937DE3900FC9731 /* SPDYSessionManagerTest.m */,
7774C2026A4DE9957D75F629 /* SPDYSessionTest.m */,
5C427F101A1D57890072403D /* SPDYStopwatchTest.m */,
060C235D17CE9FCE000B4E9C /* SPDYStreamManagerTest.m */,
067EBFE617418F350029F16C /* SPDYStreamTest.m */,
5C2229581952257800CAF160 /* SPDYURLRequestTest.m */,
Expand Down Expand Up @@ -320,8 +331,8 @@
D2CC14B816179B43002E37CF /* SPDY-Prefix.pch */,
062EA63E175D4CD3003BC1CE /* SPDYCommonLogger.h */,
062EA63F175D4CD3003BC1CE /* SPDYCommonLogger.m */,
06811C961714D426000D1677 /* SPDYError.h */,
062EA63C175D1A15003BC1CE /* SPDYDefinitions.h */,
06811C961714D426000D1677 /* SPDYError.h */,
D2CC14C9161A25CC002E37CF /* SPDYFrame.h */,
D2CC14CA161A25CC002E37CF /* SPDYFrame.m */,
D2CC14C6161A1952002E37CF /* SPDYFrameDecoder.h */,
Expand All @@ -333,6 +344,8 @@
4FE891C7065B348CC7EF4BFC /* SPDYHeaderBlockDecompressor.h */,
4FE895BE087AC28BBBC857F9 /* SPDYHeaderBlockDecompressor.m */,
06811C9A1715DC85000D1677 /* SPDYLogger.h */,
0655606619D5EDA600631121 /* SPDYMetadata.h */,
0655606719D5EDA600631121 /* SPDYMetadata.m */,
06B290CC1861018900540A03 /* SPDYOrigin.h */,
06B290CD1861018900540A03 /* SPDYOrigin.m */,
D2CC14C01618CF62002E37CF /* SPDYProtocol.h */,
Expand All @@ -343,16 +356,16 @@
D2CC14CD161A5826002E37CF /* SPDYSessionManager.m */,
06FC94121694B92400FC95DF /* SPDYSettingsStore.h */,
06FC94131694B92400FC95DF /* SPDYSettingsStore.m */,
069D0E88167F9D010037D8AF /* SPDYStream.h */,
069D0E89167F9D010037D8AF /* SPDYStream.m */,
D2CC14CF161A9EE9002E37CF /* SPDYSocket.h */,
D2CC14D0161A9EE9002E37CF /* SPDYSocket.m */,
7774CE030BB898D2BE3D320D /* SPDYStopwatch.h */,
7774CE34A3AA067D98DA7ECC /* SPDYStopwatch.m */,
069D0E88167F9D010037D8AF /* SPDYStream.h */,
069D0E89167F9D010037D8AF /* SPDYStream.m */,
061C8E9217C5954400D22083 /* SPDYStreamManager.h */,
061C8E9317C5954400D22083 /* SPDYStreamManager.m */,
06E7BF111823B74D004DB65D /* SPDYTLSTrustEvaluator.h */,
06290990169E497300E35A82 /* SPDYZLibCommon.h */,
0655606619D5EDA600631121 /* SPDYMetadata.h */,
0655606719D5EDA600631121 /* SPDYMetadata.m */,
);
path = SPDY;
sourceTree = "<group>";
Expand All @@ -370,6 +383,7 @@
0540DAAF19CB802600673796 /* SPDYTLSTrustEvaluator.h in Headers */,
0540DAAC19CB7FF900673796 /* SPDYError.h in Headers */,
0540DAA919CB7FEB00673796 /* SPDYCommonLogger.h in Headers */,
7774CD9416661E40D76713F5 /* SPDYStopwatch.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -383,6 +397,7 @@
05C7CEBB19CB45820032D681 /* SPDYProtocol.h in Headers */,
05C7CEBC19CB458F0032D681 /* SPDYTLSTrustEvaluator.h in Headers */,
0540DAAA19CB7FEB00673796 /* SPDYCommonLogger.h in Headers */,
7774CC29BBD86413798C1425 /* SPDYStopwatch.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -396,6 +411,7 @@
06E7BF131824371F004DB65D /* SPDYTLSTrustEvaluator.h in Headers */,
06811C971714D426000D1677 /* SPDYError.h in Headers */,
062EA640175D4CD3003BC1CE /* SPDYCommonLogger.h in Headers */,
7774CF887055793F373F0D5E /* SPDYStopwatch.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -580,6 +596,7 @@
5CF0A2C91A089BC500B6D141 /* SPDYMetadataTest.m in Sources */,
060C235E17CE9FCE000B4E9C /* SPDYStreamManagerTest.m in Sources */,
0655606819D5EDA600631121 /* SPDYMetadata.m in Sources */,
5C427F111A1D57890072403D /* SPDYStopwatchTest.m in Sources */,
06290995169E4D9700E35A82 /* SPDYHeaderBlockCompressor.m in Sources */,
06FDA21216717DF100137DBD /* SPDYHeaderBlockDecompressor.m in Sources */,
5C2229591952257800CAF160 /* SPDYURLRequestTest.m in Sources */,
Expand All @@ -599,6 +616,7 @@
5C427F0F1A1C7C4D0072403D /* SPDYSenTestLog.m in Sources */,
7774CA1FA1F4A59CA0906BB7 /* SPDYSocket+SPDYSocketMock.m in Sources */,
7774C1318AB029C6BCEF84D6 /* SPDYSessionTest.m in Sources */,
7774CD12A73EA9ABAE521441 /* SPDYStopwatch.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -622,6 +640,7 @@
062EA643175D4CD3003BC1CE /* SPDYCommonLogger.m in Sources */,
061C8E9617C5954400D22083 /* SPDYStreamManager.m in Sources */,
06B290CF1861018A00540A03 /* SPDYOrigin.m in Sources */,
7774C868441241542B0A90C0 /* SPDYStopwatch.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -645,6 +664,7 @@
062EA645175D4CD3003BC1CE /* SPDYCommonLogger.m in Sources */,
061C8E9817C5954400D22083 /* SPDYStreamManager.m in Sources */,
06B290D21861018A00540A03 /* SPDYOrigin.m in Sources */,
7774CDD84A5D07F8DE5B8684 /* SPDYStopwatch.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
4 changes: 2 additions & 2 deletions SPDY/SPDYMetadata.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
// Created by Michael Schore
//

#import "SPDYCommonLogger.h"
#import "SPDYMetadata.h"
#import "SPDYProtocol.h"
#import "SPDYStopwatch.h"

@implementation SPDYMetadata
{
Expand Down Expand Up @@ -71,7 +71,7 @@ - (id)init
_hostPort = 0;

NSUInteger ptr = (NSUInteger)self;
CFAbsoluteTime timestamp = CFAbsoluteTimeGetCurrent();
SPDYTimeInterval timestamp = [SPDYStopwatch currentSystemTime];
_identifier = [NSString stringWithFormat:@"%f/%tx", timestamp, ptr];

dispatch_barrier_async(__identifiersQueue, ^{
Expand Down
37 changes: 18 additions & 19 deletions SPDY/SPDYSession.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,14 @@
#import "SPDYCommonLogger.h"
#import "SPDYFrameDecoder.h"
#import "SPDYFrameEncoder.h"
#import "SPDYMetadata.h"
#import "SPDYOrigin.h"
#import "SPDYProtocol.h"
#import "SPDYSession.h"
#import "SPDYSessionManager.h"
#import "SPDYSettingsStore.h"
#import "SPDYSocket.h"
#import "SPDYStopwatch.h"
#import "SPDYStream.h"
#import "SPDYStreamManager.h"
#import "SPDYTLSTrustEvaluator.h"
#import "SPDYMetadata.h"

// The input buffer should be more than twice MAX_CHUNK_LENGTH and
// MAX_COMPRESSED_HEADER_BLOCK_LENGTH to avoid having to resize the
Expand Down Expand Up @@ -59,9 +57,8 @@ @implementation SPDYSession
NSMutableData *_inputBuffer;

SPDYStreamId _lastGoodStreamId;
CFAbsoluteTime _lastSocketActivity;
CFAbsoluteTime _sessionPingOut;
CFTimeInterval _sessionLatency;
SPDYStopwatch *_sessionPingStopwatch;
SPDYTimeInterval _sessionLatency;
NSUInteger _bufferReadIndex;
NSUInteger _bufferWriteIndex;
uint32_t _initialSendWindowSize;
Expand All @@ -78,7 +75,7 @@ @implementation SPDYSession
bool _established;
bool _receivedGoAwayFrame;
bool _sentGoAwayFrame;
CFAbsoluteTime _connectedTime;
SPDYStopwatch *_connectedStopwatch;
NSString *_connectedHost;
in_port_t _connectedPort;
}
Expand All @@ -103,6 +100,9 @@ - (id)initWithOrigin:(SPDYOrigin *)origin
return nil;
}

_sessionPingStopwatch = [[SPDYStopwatch alloc] init];
_connectedStopwatch = [[SPDYStopwatch alloc] init];

SPDYSocket *socket = [[SPDYSocket alloc] initWithDelegate:self];
bool connecting = [socket connectToHost:origin.host
onPort:origin.port
Expand Down Expand Up @@ -193,7 +193,7 @@ - (void)openStream:(SPDYStream *)stream
if (_sessionLatency >= 0) {
stream.metadata.latencyMs = (NSInteger)(_sessionLatency * 1000);
}
stream.metadata.connectedMs = (CFAbsoluteTimeGetCurrent() - _connectedTime) * 1000;
stream.metadata.connectedMs = _connectedStopwatch.elapsedSeconds * 1000;
stream.metadata.hostAddress = _connectedHost;
stream.metadata.hostPort = _connectedPort;

Expand Down Expand Up @@ -284,14 +284,12 @@ - (void)_closeWithStatus:(SPDYSessionStatus)status

- (bool)socket:(SPDYSocket *)socket securedWithTrust:(SecTrustRef)trust
{
_lastSocketActivity = CFAbsoluteTimeGetCurrent();
return [SPDYProtocol evaluateServerTrust:trust forHost:_origin.host];
}

- (void)socket:(SPDYSocket *)socket didConnectToHost:(NSString *)host port:(in_port_t)port
{
_lastSocketActivity = CFAbsoluteTimeGetCurrent();
_connectedTime = _lastSocketActivity;
[_connectedStopwatch reset];
SPDY_INFO(@"session connected to %@ (%@:%u)", _origin, host, port);

_connected = YES;
Expand All @@ -309,7 +307,6 @@ - (void)socket:(SPDYSocket *)socket didConnectToHost:(NSString *)host port:(in_p

- (void)socket:(SPDYSocket *)socket didReadData:(NSData *)data withTag:(long)tag
{
_lastSocketActivity = CFAbsoluteTimeGetCurrent();
SPDY_DEBUG(@"socket read[%li] (%lu)", tag, (unsigned long)data.length);

_bufferWriteIndex += data.length;
Expand Down Expand Up @@ -343,9 +340,8 @@ - (void)socket:(SPDYSocket *)socket didReadData:(NSData *)data withTag:(long)tag

- (void)socket:(SPDYSocket *)socket didWriteDataWithTag:(long)tag
{
_lastSocketActivity = CFAbsoluteTimeGetCurrent();
if (tag == 1) {
_sessionPingOut = _lastSocketActivity;
[_sessionPingStopwatch reset];
}
}

Expand All @@ -361,12 +357,10 @@ - (void)socket:(SPDYSocket *)socket didWriteDataWithTag:(long)tag

- (void)socket:(SPDYSocket *)socket didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag
{
_lastSocketActivity = CFAbsoluteTimeGetCurrent();
}

- (void)socket:(SPDYSocket *)socket willDisconnectWithError:(NSError *)error
{
_lastSocketActivity = CFAbsoluteTimeGetCurrent();
SPDY_WARNING(@"session connection error: %@", error);
for (SPDYStream *stream in _activeStreams) {
stream.delegate = nil;
Expand All @@ -377,7 +371,6 @@ - (void)socket:(SPDYSocket *)socket willDisconnectWithError:(NSError *)error

- (void)socketDidDisconnect:(SPDYSocket *)socket
{
_lastSocketActivity = CFAbsoluteTimeGetCurrent();
SPDY_INFO(@"session connection closed");

_connected = NO;
Expand Down Expand Up @@ -600,6 +593,12 @@ - (void)didReadSynReplyFrame:(SPDYSynReplyFrame *)synReplyFrame frameDecoder:(SP

stream.metadata.rxBytes += synReplyFrame.encodedLength;

// While we prefer to record latencyMs at stream open time, the ping response may not have been
// received yet. It will have been received by this point however.
if (_sessionLatency >= 0 && stream.metadata.latencyMs <= 0) {
stream.metadata.latencyMs = (NSInteger)(_sessionLatency * 1000);
}

// Check if we have received multiple frames for the same Stream-ID
if (stream.receivedReply) {
SPDY_WARNING(@"received duplicate SYN_REPLY");
Expand Down Expand Up @@ -722,7 +721,7 @@ - (void)didReadPingFrame:(SPDYPingFrame *)pingFrame frameDecoder:(SPDYFrameDecod

if (pingId & 1) {
if (pingId == 1) {
_sessionLatency = CFAbsoluteTimeGetCurrent() - _sessionPingOut;
_sessionLatency = _sessionPingStopwatch.elapsedSeconds;
SPDY_DEBUG(@"received PING.%u response (%f)", pingId, _sessionLatency);
_established = YES;
}
Expand Down
20 changes: 20 additions & 0 deletions SPDY/SPDYStopwatch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// SPDYStopwatch.h
// SPDY
//
// Copyright (c) 2014 Twitter, Inc. All rights reserved.
// Licensed under the Apache License v2.0
// http://www.apache.org/licenses/LICENSE-2.0
//
// Created by Kevin Goodier.
//

typedef double SPDYTimeInterval;

@interface SPDYStopwatch : NSObject
+ (SPDYTimeInterval)currentSystemTime;
+ (SPDYTimeInterval)currentAbsoluteTime;
- (id)init;
- (void)reset;
- (SPDYTimeInterval)elapsedSeconds;
@end
67 changes: 67 additions & 0 deletions SPDY/SPDYStopwatch.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//
// SPDYStopwatch.m
// SPDY
//
// Copyright (c) 2014 Twitter, Inc. All rights reserved.
// Licensed under the Apache License v2.0
// http://www.apache.org/licenses/LICENSE-2.0
//
// Created by Kevin Goodier
//

#import <mach/mach_time.h>
#import "SPDYStopwatch.h"

@implementation SPDYStopwatch
{
SPDYTimeInterval _startTime;
}

static dispatch_once_t __initTimebase;
static double __machTimebaseToSeconds;
static mach_timebase_info_data_t __machTimebase;

+ (void)initialize
{
dispatch_once(&__initTimebase, ^{
kern_return_t status = mach_timebase_info(&__machTimebase);
// Everything will be 0 if this fails.
if (status != KERN_SUCCESS) {
__machTimebase.numer = 0;
__machTimebase.denom = 1;
}
__machTimebaseToSeconds = (double)__machTimebase.numer / ((double)__machTimebase.denom * 1000000000.0);
});
}

+ (SPDYTimeInterval)currentSystemTime
{
uint64_t now = mach_absolute_time();
return (SPDYTimeInterval)now * __machTimebaseToSeconds;
}

+ (SPDYTimeInterval)currentAbsoluteTime
{
return CFAbsoluteTimeGetCurrent();
}

- (id)init
{
self = [super init];
if (self) {
_startTime = [SPDYStopwatch currentAbsoluteTime];
}
return self;
}

- (void)reset
{
_startTime = [SPDYStopwatch currentAbsoluteTime];
}

- (SPDYTimeInterval)elapsedSeconds
{
return [SPDYStopwatch currentAbsoluteTime] - _startTime;
}

@end
Loading

0 comments on commit bb02228

Please sign in to comment.