From 016c35efd069a94cd732143e7a9d8b1769963e38 Mon Sep 17 00:00:00 2001 From: theMackabu Date: Fri, 1 May 2026 15:21:51 -0700 Subject: [PATCH] add embedding demo --- demos/embed.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++ meson.build | 1 + 2 files changed, 160 insertions(+) create mode 100644 demos/embed.c diff --git a/demos/embed.c b/demos/embed.c new file mode 100644 index 0000000..c73ef16 --- /dev/null +++ b/demos/embed.c @@ -0,0 +1,159 @@ +#include "rpc/client.h" +#include "rpc/server.h" + +#include +#include +#include +#include + +typedef struct embed_alloc_stats { + size_t allocs; + size_t reallocs; + size_t frees; +} embed_alloc_stats; + +typedef struct embed_state { + const char *name; + int64_t bias; + embed_alloc_stats *stats; +} embed_state; + +typedef struct embed_server { + rpc_server *rpc; + pthread_t thread; +} embed_server; + +static void *embed_alloc(void *ctx, size_t size) { + embed_alloc_stats *stats = ctx; + stats->allocs++; + return malloc(size); +} + +static void *embed_realloc(void *ctx, void *ptr, size_t size) { + embed_alloc_stats *stats = ctx; + stats->reallocs++; + return realloc(ptr, size); +} + +static void embed_free(void *ctx, void *ptr) { + embed_alloc_stats *stats = ctx; + stats->frees++; + free(ptr); +} + +static embed_state *state_new(embed_alloc_stats *stats, const char *name, int64_t bias) { + embed_state *state = embed_alloc(stats, sizeof(*state)); + if (!state) return NULL; + *state = (embed_state){ + .name = name, + .bias = bias, + .stats = stats, + }; + return state; +} + +static void state_finalizer(void *user_data) { + embed_state *state = user_data; + if (!state) return; + printf("finalize route state: %s\n", state->name); + embed_free(state->stats, state); +} + +static int add_with_bias(rpc_ctx *ctx, const rpc_value *args, size_t argc, rpc_writer *out, void *user_data) { + (void)ctx; + embed_state *state = user_data; + if (!state || argc != 2 || args[0].type != RPC_TYPE_I64 || args[1].type != RPC_TYPE_I64) return -1; + return rpc_writer_i64(out, args[0].as.i64 + args[1].as.i64 + state->bias); +} + +static void *server_main(void *arg) { + embed_server *server = arg; + (void)rpc_server_run(server->rpc); + return NULL; +} + +int main(void) { + embed_alloc_stats stats = {0}; + rpc_allocator allocator = { + .ctx = &stats, + .alloc = embed_alloc, + .realloc = embed_realloc, + .free = embed_free, + }; + + if (rpc_set_allocator(&allocator) != 0) { + fprintf(stderr, "allocator install failed\n"); + return 1; + } + + embed_server server = {0}; + embed_state *first = state_new(&stats, "add/bias=1", 1); + embed_state *second = state_new(&stats, "add/bias=100", 100); + if (!first || !second) { + fprintf(stderr, "state allocation failed\n"); + state_finalizer(first); + state_finalizer(second); + rpc_set_allocator(NULL); + return 1; + } + + if (rpc_server_init(&server.rpc) != 0 || rpc_server_set_workers(server.rpc, 1) != 0 || + rpc_server_add_route_name_ex(server.rpc, "add", add_with_bias, first, state_finalizer) != 0 || + rpc_server_add_route_name_ex(server.rpc, "add", add_with_bias, second, state_finalizer) != 0 || + rpc_server_bind(server.rpc, "127.0.0.1", "0") != 0 || rpc_server_listen(server.rpc) != 0) { + fprintf(stderr, "server setup failed\n"); + rpc_server_destroy(server.rpc); + rpc_set_allocator(NULL); + return 1; + } + + char port[16]; + snprintf(port, sizeof(port), "%u", rpc_server_port(server.rpc)); + if (pthread_create(&server.thread, NULL, server_main, &server) != 0) { + fprintf(stderr, "server thread failed\n"); + rpc_server_destroy(server.rpc); + rpc_set_allocator(NULL); + return 1; + } + + rpc_client *client = NULL; + rpc_writer args; + rpc_writer_init(&args); + rpc_value *values = NULL; + size_t value_count = 0; + int rc = 1; + + if (rpc_client_connect(&client, "127.0.0.1", port) != 0) { + fprintf(stderr, "connect failed\n"); + goto done; + } + if (rpc_writer_i64(&args, 20) != 0 || rpc_writer_i64(&args, 22) != 0) { + fprintf(stderr, "argument encode failed\n"); + goto done; + } + if (rpc_client_call_name(client, "add", &args, &values, &value_count) != 0) { + fprintf(stderr, "call failed: %s\n", rpc_client_error(client)); + goto done; + } + if (value_count != 1 || values[0].type != RPC_TYPE_I64) { + fprintf(stderr, "unexpected response\n"); + goto done; + } + + printf("20 + 22 + embedded bias = %lld\n", (long long)values[0].as.i64); + rc = 0; + +done: + rpc_values_free(values); + rpc_writer_free(&args); + rpc_client_close(client); + + (void)rpc_server_remove_route_name(server.rpc, "add"); + rpc_server_stop(server.rpc); + pthread_join(server.thread, NULL); + rpc_server_destroy(server.rpc); + + printf("allocator stats: alloc=%zu realloc=%zu free=%zu\n", stats.allocs, stats.reallocs, stats.frees); + rpc_set_allocator(NULL); + return rc; +} diff --git a/meson.build b/meson.build index 7128512..a1eacd4 100644 --- a/meson.build +++ b/meson.build @@ -34,6 +34,7 @@ rpc_dep = declare_dependency( ) executable('rpc-bench', 'demos/bench.c', dependencies: rpc_dep) +executable('rpc-embed', 'demos/embed.c', dependencies: rpc_dep) executable('rpc-server', 'demos/server.c', dependencies: rpc_dep) executable('rpc-client', 'demos/client.c', dependencies: rpc_dep) -- 2.51.2