Skip to content

Commit d87574f

Browse files
authored
Setting stopwatch policy TTL to TimeSpan.MaxValue gives invalid TTL (#336)
* max ttl * fix stopwatch * testmac * common max * mul * rem * rem * mul ---------
1 parent 116476f commit d87574f

File tree

4 files changed

+38
-6
lines changed

4 files changed

+38
-6
lines changed

BitFaster.Caching.UnitTests/Lru/TLruTickCount64PolicyTests .cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
using FluentAssertions.Extensions;
33
using BitFaster.Caching.Lru;
44
using System;
5-
using System.Collections.Generic;
6-
using System.Linq;
7-
using System.Text;
85
using System.Threading.Tasks;
96
using Xunit;
107

@@ -25,7 +22,7 @@ public void WhenTtlIsTimeSpanMaxThrow()
2522
[Fact]
2623
public void WhenTtlIsZeroThrow()
2724
{
28-
Action constructor = () => { new TLruTickCount64Policy<int, int>(TimeSpan.MaxValue); };
25+
Action constructor = () => { new TLruTickCount64Policy<int, int>(TimeSpan.Zero); };
2926

3027
constructor.Should().Throw<ArgumentOutOfRangeException>();
3128
}

BitFaster.Caching.UnitTests/Lru/TlruStopwatchPolicyTests.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,31 @@ public class TlruStopwatchPolicyTests
1111
{
1212
private readonly TlruStopwatchPolicy<int, int> policy = new TlruStopwatchPolicy<int, int>(TimeSpan.FromSeconds(10));
1313

14+
[Fact]
15+
public void WhenTtlIsZeroThrow()
16+
{
17+
Action constructor = () => { new TlruStopwatchPolicy<int, int>(TimeSpan.Zero); };
18+
19+
constructor.Should().Throw<ArgumentOutOfRangeException>();
20+
}
21+
22+
[Fact]
23+
public void WhenTtlIsTimeSpanMaxThrow()
24+
{
25+
Action constructor = () => { new TlruStopwatchPolicy<int, int>(TimeSpan.MaxValue); };
26+
27+
constructor.Should().Throw<ArgumentOutOfRangeException>();
28+
}
29+
30+
[Fact]
31+
public void WhenTtlIsCloseToMaxAllow()
32+
{
33+
double maxTicks = long.MaxValue / 100.0d;
34+
var ttl = TimeSpan.FromTicks((long)maxTicks) - TimeSpan.FromTicks(10);
35+
36+
new TlruStopwatchPolicy<int, int>(ttl).TimeToLive.Should().BeCloseTo(ttl, TimeSpan.FromTicks(20));
37+
}
38+
1439
[Fact]
1540
public void TimeToLiveShouldBeTenSecs()
1641
{

BitFaster.Caching/Lru/TlruStopwatchPolicy.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,16 @@ public ItemDestination RouteCold(LongTickCountLruItem<K, V> item)
128128
/// <returns>The time represented as ticks.</returns>
129129
public static long ToTicks(TimeSpan timespan)
130130
{
131+
// mac adjustment factor is 100, giving lowest maximum TTL on mac platform - use same upper limit on all platforms for consistency
132+
// this also avoids overflow when multipling long.MaxValue by 1.0
133+
double maxTicks = long.MaxValue * 0.01d;
134+
135+
if (timespan <= TimeSpan.Zero || timespan.Ticks >= maxTicks)
136+
{
137+
TimeSpan maxRepresentable = TimeSpan.FromTicks((long)maxTicks);
138+
Ex.ThrowArgOutOfRange(nameof(timespan), $"Value must be greater than zero and less than {maxRepresentable}");
139+
}
140+
131141
return (long)(timespan.Ticks * stopwatchAdjustmentFactor);
132142
}
133143

@@ -137,7 +147,7 @@ public static long ToTicks(TimeSpan timespan)
137147
/// <param name="ticks">The time represented as ticks.</param>
138148
/// <returns>The time represented as a TimeSpan.</returns>
139149
public static TimeSpan FromTicks(long ticks)
140-
{
150+
{
141151
return TimeSpan.FromTicks((long)(ticks / stopwatchAdjustmentFactor));
142152
}
143153
}

BitFaster.Caching/Lru/TlruTickCount64Policy.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace BitFaster.Caching.Lru
2727
public TLruTickCount64Policy(TimeSpan timeToLive)
2828
{
2929
TimeSpan maxRepresentable = TimeSpan.FromTicks(9223372036854769664);
30-
if (timeToLive < TimeSpan.Zero || timeToLive > maxRepresentable)
30+
if (timeToLive <= TimeSpan.Zero || timeToLive > maxRepresentable)
3131
{
3232
Ex.ThrowArgOutOfRange(nameof(timeToLive), $"Value must greater than zero and less than {maxRepresentable}");
3333
}

0 commit comments

Comments
 (0)