futhark-0.25.32: rts/c/event_list.h
// Start of event_list.h
typedef int (*event_report_fn)(struct str_builder*, void*);
// A collection of key-value associations. Used to associate extra data with
// events.
struct kvs {
// A buffer that contains all value data. Must be freed when the struct kvs is
// no longer used.
char *buf;
// Size of buf in bytes.
size_t buf_size;
// Number of bytes used in buf.
size_t buf_used;
// Number of associations stored.
size_t n;
// Capacity of vals.
size_t vals_capacity;
// An array of keys.
const char* *keys;
// Indexes into 'buf' that contains the values as zero-terminated strings.
size_t *vals;
};
static const size_t KVS_INIT_BUF_SIZE = 128;
static const size_t KVS_INIT_NUMKEYS = 8;
void kvs_init(struct kvs* kvs) {
kvs->buf = malloc(KVS_INIT_BUF_SIZE);
kvs->buf_size = KVS_INIT_BUF_SIZE;
kvs->buf_used = 0;
kvs->vals_capacity = KVS_INIT_NUMKEYS;
kvs->keys = calloc(kvs->vals_capacity, sizeof(const char*));
kvs->vals = calloc(kvs->vals_capacity, sizeof(size_t));
kvs->n = 0;
}
struct kvs* kvs_new(void) {
struct kvs *kvs = malloc(sizeof(struct kvs));
kvs_init(kvs);
return kvs;
}
void kvs_printf(struct kvs* kvs, const char* key, const char* fmt, ...) {
va_list vl;
va_start(vl, fmt);
size_t needed = 1 + (size_t)vsnprintf(NULL, 0, fmt, vl);
while (kvs->buf_used+needed > kvs->buf_size) {
kvs->buf_size *= 2;
kvs->buf = realloc(kvs->buf, kvs->buf_size * sizeof(const char*));
}
if (kvs->n == kvs->vals_capacity) {
kvs->vals_capacity *= 2;
kvs->vals = realloc(kvs->vals, kvs->vals_capacity * sizeof(size_t));
kvs->keys = realloc(kvs->keys, kvs->vals_capacity * sizeof(char*));
}
kvs->keys[kvs->n] = key;
kvs->vals[kvs->n] = kvs->buf_used;
kvs->buf_used += needed;
va_start(vl, fmt); // Must re-init.
vsnprintf(&kvs->buf[kvs->vals[kvs->n]], needed, fmt, vl);
kvs->n++;
}
void kvs_free(struct kvs* kvs) {
free(kvs->vals);
free(kvs->keys);
free(kvs->buf);
}
// Assumes all of the values are valid JSON objects.
void kvs_json(const struct kvs* kvs, struct str_builder *sb) {
str_builder_char(sb, '{');
for (size_t i = 0; i < kvs->n; i++) {
if (i != 0) {
str_builder_str(sb, ",");
}
str_builder_json_str(sb, kvs->keys[i]);
str_builder_str(sb, ":");
str_builder_str(sb, &kvs->buf[kvs->vals[i]]);
}
str_builder_char(sb, '}');
}
void kvs_log(const struct kvs* kvs, const char* prefix, FILE* f) {
for (size_t i = 0; i < kvs->n; i++) {
fprintf(f, "%s%s: %s\n",
prefix,
kvs->keys[i],
&kvs->buf[kvs->vals[i]]);
}
}
struct event {
void* data;
event_report_fn f;
const char* name;
const char *provenance;
// Key-value information that is also to be printed.
struct kvs *kvs;
};
struct event_list {
struct event *events;
int num_events;
int capacity;
};
static void event_list_init(struct event_list *l) {
l->capacity = 100;
l->num_events = 0;
l->events = calloc(l->capacity, sizeof(struct event));
}
static void event_list_free(struct event_list *l) {
free(l->events);
}
static void add_event_to_list(struct event_list *l,
const char* name,
const char* provenance,
struct kvs *kvs,
void* data,
event_report_fn f) {
if (l->num_events == l->capacity) {
l->capacity *= 2;
l->events = realloc(l->events, l->capacity * sizeof(struct event));
}
l->events[l->num_events].name = name;
l->events[l->num_events].provenance =
provenance ? provenance : "unknown";
l->events[l->num_events].kvs = kvs;
l->events[l->num_events].data = data;
l->events[l->num_events].f = f;
l->num_events++;
}
static int report_events_in_list(struct event_list *l,
struct str_builder* sb) {
int ret = 0;
for (int i = 0; i < l->num_events; i++) {
if (i != 0) {
str_builder_str(sb, ",");
}
str_builder_str(sb, "{\"name\":");
str_builder_json_str(sb, l->events[i].name);
str_builder_str(sb, ",\"provenance\":");
str_builder_json_str(sb, l->events[i].provenance);
if (l->events[i].f(sb, l->events[i].data) != 0) {
ret = 1;
break;
}
str_builder_str(sb, ",\"details\":");
if (l->events[i].kvs) {
kvs_json(l->events[i].kvs, sb);
kvs_free(l->events[i].kvs);
} else {
str_builder_str(sb, "{}");
}
str_builder(sb, "}");
}
event_list_free(l);
event_list_init(l);
return ret;
}
// End of event_list.h