Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

fuel.gno

1.83 Kb · 58 lines
 1package vmkit
 2
 3// Unmetered is the fuel value that disables the budget: a [Meter] built with
 4// it never reports exhaustion. It exists so a benchmark can measure the
 5// dispatch loop without the meter in it, and so a trusted caller can run a
 6// program to completion in one slice. Gas remains the real backstop.
 7const Unmetered int64 = -1
 8
 9// Meter is a fuel budget being spent. It allocates nothing after
10// construction, because it sits in the hot path of every guest instruction.
11type Meter struct {
12	budget int64 // Unmetered, or the number of units this slice may spend
13	used   int64
14}
15
16// NewMeter returns a meter good for `budget` units, or an unmetered one when
17// budget is [Unmetered]. A budget of zero is a meter with nothing to spend,
18// which is a legitimate way to ask "is this instance still runnable".
19func NewMeter(budget int64) *Meter {
20	if budget < 0 {
21		budget = Unmetered
22	}
23	return &Meter{budget: budget}
24}
25
26// Charge spends n units and reports whether they were available. On false
27// nothing is spent, so the caller can stop before executing the instruction
28// it could not pay for. That ordering is what makes a resumed machine
29// re-execute exactly the instruction it stopped at, and no other.
30func (m *Meter) Charge(n int64) bool {
31	if m.budget == Unmetered {
32		m.used += n
33		return true
34	}
35	if m.used+n > m.budget {
36		return false
37	}
38	m.used += n
39	return true
40}
41
42// Used reports how much fuel has been spent.
43func (m *Meter) Used() int64 { return m.used }
44
45// Remaining reports what is left, or [Unmetered].
46func (m *Meter) Remaining() int64 {
47	if m.budget == Unmetered {
48		return Unmetered
49	}
50	return m.budget - m.used
51}
52
53// Exhausted reports whether the next single unit would fail.
54func (m *Meter) Exhausted() bool { return !m.affordable(1) }
55
56func (m *Meter) affordable(n int64) bool {
57	return m.budget == Unmetered || m.used+n <= m.budget
58}