summaryrefslogtreecommitdiff
path: root/libguile/whippet/src/local-worklist.h
blob: 8dcd3e20d26a5b6dcfb867e232de6e0017d9c158 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#ifndef LOCAL_WORKLIST_H
#define LOCAL_WORKLIST_H

#include "assert.h"

#define LOCAL_WORKLIST_SIZE 1024
#define LOCAL_WORKLIST_MASK (LOCAL_WORKLIST_SIZE - 1)
#define LOCAL_WORKLIST_SHARE_AMOUNT (LOCAL_WORKLIST_SIZE * 3 / 4)
struct local_worklist {
  size_t read;
  size_t write;
  struct gc_ref data[LOCAL_WORKLIST_SIZE];
};

static inline void
local_worklist_init(struct local_worklist *q) {
  q->read = q->write = 0;
}
static inline void
local_worklist_poison(struct local_worklist *q) {
  q->read = 0; q->write = LOCAL_WORKLIST_SIZE;
}
static inline size_t
local_worklist_size(struct local_worklist *q) {
  return q->write - q->read;
}
static inline int
local_worklist_empty(struct local_worklist *q) {
  return local_worklist_size(q) == 0;
}
static inline int
local_worklist_full(struct local_worklist *q) {
  return local_worklist_size(q) >= LOCAL_WORKLIST_SIZE;
}
static inline void
local_worklist_push(struct local_worklist *q, struct gc_ref v) {
  ASSERT(!local_worklist_full(q));
  q->data[q->write++ & LOCAL_WORKLIST_MASK] = v;
}
static inline struct gc_ref
local_worklist_pop(struct local_worklist *q) {
  ASSERT(!local_worklist_empty(q));
  return q->data[q->read++ & LOCAL_WORKLIST_MASK];
}

static inline size_t
local_worklist_pop_many(struct local_worklist *q, struct gc_ref **objv,
                        size_t limit) {
  size_t avail = local_worklist_size(q);
  size_t read = q->read & LOCAL_WORKLIST_MASK;
  size_t contig = LOCAL_WORKLIST_SIZE - read;
  if (contig < avail) avail = contig;
  if (limit < avail) avail = limit;
  *objv = q->data + read;
  q->read += avail;
  return avail;
}

#endif // LOCAL_WORKLIST_H