A lightweight, general-purpose C library providing essential data structures and system utilities. Originally built to power Kraken, a multi-threaded HTTP server, but designed to be used independently in any C project.
What's Inside
Collections
Singly Linked List - A type-safe linked list implementation with insertion and removal operations. Useful for dynamic data storage and efficient sequential access patterns.
Queue - A bounded FIFO queue with configurable capacity, perfect for producer-consumer patterns like HTTP request queuing and job scheduling.
Hashmap - An open-addressing hashmap using Robin Hood hashing for better cache locality and reduced clustering. Supports custom hash functions (SipHash-2-4 and MurmurHash3 included) and custom comparators. Perfect for building caches, routing tables, and fast lookups.
Threading
Thread Pool - A simple but effective thread pool for concurrent task execution. Manages worker threads and a task queue internally. Ideal for handling parallel I/O operations or computational tasks.
Utilities
Panic - Quick error handling macro that prints the error message with file/line information and exits.
Log - Convenience logging macros for formatted output.
Quick Start
Building
Compile to a static library:
makeOr build as a shared library:
make -e SHARED=1The compiled library will be available in the lib/ directory.
Using Owl
Include the main header in your project:
#include "owl.h"Example: Thread Pool
#include "owl.h"
void *process_request(void *arg) {
// Your task logic here
return NULL;
}
int main() {
owl_thread_pool_t *tp = owl_thread_pool_init(4);
owl_worker_task_t task = owl_worker_task_init(process_request, NULL);
owl_thread_pool_enqueue_task(tp, &task);
owl_thread_pool_free(tp); // Waits for all tasks to complete
}Example: Hashmap
#include "owl.h"
struct user {
char *name;
int age;
};
uint64_t user_hash(const void *item, uint64_t seed0, uint64_t seed1) {
const struct user *user = item;
return owl_hashmap_sip(user->name, strlen(user->name), seed0, seed1);
}
int user_compare(const void *a, const void *b, void *udata) {
return strcmp(((struct user *)a)->name, ((struct user *)b)->name);
}
int main() {
owl_hashmap_t *map = owl_hashmap_new(
sizeof(struct user), 0, 0, 0,
user_hash, user_compare, NULL, NULL
);
owl_hashmap_set(map, &(struct user){.name = "Alice", .age = 30});
struct user *u = owl_hashmap_get(map, &(struct user){.name = "Alice"});
owl_hashmap_free(map);
}Design Philosophy
- Type-safe: Collections work with any data type via
sizeof()and void pointers - Zero dependencies: Pure C with no external dependencies
- Memory-conscious: Explicit allocation/deallocation with manual memory management
Technical Notes
- All insert operations perform deep copies of data
- Remove operations return heap-allocated pointers (caller must free)
- Thread pool gracefully shuts down, waiting for queued tasks to complete
- Hashmap implementation currently wraps tidwall/hashmap.c (planned for rewrite)