hop-2012/node.c

122 lines
2.6 KiB
C

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include "cmsg_private.h"
#include "ref.h"
#include "sexp.h"
#include "hashtable.h"
#include "node.h"
static hashtable_t node_class_table;
static hashtable_t directory;
static void *node_incref(void *arg) {
return INCREF((node_t *) arg);
}
static void node_decref(void *arg) {
DECREF((node_t *) arg, node_destructor);
}
void init_node(void) {
init_hashtable(&node_class_table,
31,
NULL,
NULL);
init_hashtable(&directory,
10007,
node_incref,
node_decref);
}
void register_node_class(node_class_t *nc) {
cmsg_bytes_t key = cmsg_cstring_bytes(nc->name);
if (hashtable_contains(&node_class_table, key)) {
die("Duplicate node class name %s\n", nc->name);
}
hashtable_put(&node_class_table, key, nc);
}
node_class_t *lookup_node_class(cmsg_bytes_t name) {
node_class_t *nc = NULL;
hashtable_get(&node_class_table, name, (void **) &nc);
return nc;
}
node_t *new_node(node_class_t *nc, sexp_t *args) {
node_t *n = nc->construct(nc, args);
n->refcount = ZERO_REFCOUNT();
n->node_class = nc;
init_hashtable(&n->names, 5, NULL, NULL);
return n;
}
void unbind_on_destroy(void *context, cmsg_bytes_t key, void *value) {
unbind_node(key);
}
void node_destructor(node_t *n) {
hashtable_foreach(&n->names, unbind_on_destroy, NULL);
destroy_hashtable(&n->names);
n->node_class->destroy(n);
}
node_t *lookup_node(cmsg_bytes_t name) {
node_t *n = NULL;
hashtable_get(&directory, name, (void **) &n);
return n;
}
int bind_node(cmsg_bytes_t name, node_t *n) {
if (hashtable_contains(&directory, name)) {
return 0;
}
hashtable_put(&directory, name, n);
hashtable_put(&n->names, name, NULL);
return 1;
}
int unbind_node(cmsg_bytes_t name) {
node_t *n = NULL;
hashtable_get(&directory, name, (void **) &n);
if (n == NULL) {
return 0;
} else {
hashtable_erase(&n->names, name);
hashtable_erase(&directory, name);
return 1;
}
}
int post_node(cmsg_bytes_t node, cmsg_bytes_t name, sexp_t *body) {
static sexp_t *post_atom = NULL;
sexp_t *msg = NULL;
int result;
if (post_atom == NULL) {
post_atom = INCREF(sexp_bytes(cmsg_cstring_bytes("post")));
}
msg = sexp_cons(body, msg);
msg = sexp_cons(sexp_bytes(name), msg);
msg = sexp_cons(post_atom, msg);
INCREF(msg);
result = send_node(node, msg);
DECREF(msg, sexp_destructor);
return result;
}
int send_node(cmsg_bytes_t node, sexp_t *message) {
node_t *n = lookup_node(node);
if (n == NULL) {
return 0;
}
n->node_class->handle_message(n, message);
return 1;
}