Skip to content
File

Blob: src/workerd/io/io-timers.h

cpp91 lines
1#pragma once
2 
3#include <workerd/jsg/jsg.h>
4 
5namespace workerd {
6 
7class IoContext;
8 
9// A TimeoutId is a positive non-zero integer value that explicitly identifies a timeout set on an
10// isolate.
11//
12// Lastly, timeout ids can experience integer roll over. It is expected that the
13// setTimeout/clearTimeout implementation will enforce id uniqueness for *active* timeouts. This
14// does not mean that an external user cannot have cached a timeout id for a long expired timeout.
15// However, clearTimeout implementations are expected to only have access to timeouts set via that
16// same implementation.
17class TimeoutId {
18 public:
19 // Use a double so that we can exceed the maximum value for uint32_t.
20 using NumberType = double;
21 
22 // Store as a uint64_t so that we treat this id as an integer.
23 using ValueType = uint64_t;
24 
25 class Generator;
26 
27 // Convert an externally provided double into a TimeoutId. If you are making a new TimeoutId,
28 // use a Generator instead.
29 inline static TimeoutId fromNumber(NumberType id) {
30 return TimeoutId(static_cast<ValueType>(id));
31 }
32 
33 // Convert a TimeoutId to an integer-convertable double for external consumption.
34 // Note that this is expected to be less than or equal to JavaScript Number.MAX_SAFE_INTEGER
35 // (2^53 - 1). To reach greater than that value in normal operation, we'd need a Generator to
36 // live far far longer than our normal release/restart cycle, be initialized with a large
37 // starting value, or experience active concurrency _somehow_.
38 inline NumberType toNumber() const {
39 return value;
40 }
41 
42 inline bool operator<(TimeoutId id) const {
43 return value < id.value;
44 }
45 
46 private:
47 constexpr explicit TimeoutId(ValueType value): value(value) {}
48 
49 ValueType value;
50};
51 
52class TimeoutId::Generator {
53 public:
54 Generator() = default;
55 KJ_DISALLOW_COPY_AND_MOVE(Generator);
56 
57 // Get the next TimeoutId for this generator. This function will never return a TimeoutId <= 0.
58 TimeoutId getNext();
59 
60 private:
61 // We always skip 0 per the spec:
62 // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers.
63 TimeoutId::ValueType nextId = 1;
64};
65 
66class TimeoutManager {
67 public:
68 // Upper bound on the number of timeouts a user can *ever* have active.
69 constexpr static auto MAX_TIMEOUTS = 10'000;
70 
71 struct TimeoutParameters {
72 TimeoutParameters(bool repeat, int64_t msDelay, jsg::Function<void()> function);
73 
74 bool repeat;
75 int64_t msDelay;
76 
77 // This is a maybe to allow cancel to clear it and free the reference
78 // when it is no longer needed.
79 kj::Maybe<jsg::Function<void()>> function;
80 };
81 
82 virtual TimeoutId setTimeout(
83 IoContext& context, TimeoutId::Generator& generator, TimeoutParameters params) = 0;
84 virtual void clearTimeout(IoContext& context, TimeoutId id) = 0;
85 virtual size_t getTimeoutCount() const = 0;
86 virtual kj::Maybe<kj::Date> getNextTimeout() const = 0;
87 virtual void cancelAll() = 0;
88};
89 
90} // namespace workerd