xref: /third_party/node/deps/undici/src/lib/timers.js (revision 1cb0ef41)
1'use strict'
2
3let fastNow = Date.now()
4let fastNowTimeout
5
6const fastTimers = []
7
8function onTimeout () {
9  fastNow = Date.now()
10
11  let len = fastTimers.length
12  let idx = 0
13  while (idx < len) {
14    const timer = fastTimers[idx]
15
16    if (timer.state === 0) {
17      timer.state = fastNow + timer.delay
18    } else if (timer.state > 0 && fastNow >= timer.state) {
19      timer.state = -1
20      timer.callback(timer.opaque)
21    }
22
23    if (timer.state === -1) {
24      timer.state = -2
25      if (idx !== len - 1) {
26        fastTimers[idx] = fastTimers.pop()
27      } else {
28        fastTimers.pop()
29      }
30      len -= 1
31    } else {
32      idx += 1
33    }
34  }
35
36  if (fastTimers.length > 0) {
37    refreshTimeout()
38  }
39}
40
41function refreshTimeout () {
42  if (fastNowTimeout && fastNowTimeout.refresh) {
43    fastNowTimeout.refresh()
44  } else {
45    clearTimeout(fastNowTimeout)
46    fastNowTimeout = setTimeout(onTimeout, 1e3)
47    if (fastNowTimeout.unref) {
48      fastNowTimeout.unref()
49    }
50  }
51}
52
53class Timeout {
54  constructor (callback, delay, opaque) {
55    this.callback = callback
56    this.delay = delay
57    this.opaque = opaque
58
59    //  -2 not in timer list
60    //  -1 in timer list but inactive
61    //   0 in timer list waiting for time
62    // > 0 in timer list waiting for time to expire
63    this.state = -2
64
65    this.refresh()
66  }
67
68  refresh () {
69    if (this.state === -2) {
70      fastTimers.push(this)
71      if (!fastNowTimeout || fastTimers.length === 1) {
72        refreshTimeout()
73      }
74    }
75
76    this.state = 0
77  }
78
79  clear () {
80    this.state = -1
81  }
82}
83
84module.exports = {
85  setTimeout (callback, delay, opaque) {
86    return delay < 1e3
87      ? setTimeout(callback, delay, opaque)
88      : new Timeout(callback, delay, opaque)
89  },
90  clearTimeout (timeout) {
91    if (timeout instanceof Timeout) {
92      timeout.clear()
93    } else {
94      clearTimeout(timeout)
95    }
96  }
97}
98