]> git.feebdaed.xyz Git - 0xmirror/mongoose.git/commitdiff
Add memory management example, o1heap flavor
authorSergio R. Caprile <scaprile@cesanta.com>
Wed, 29 Oct 2025 18:51:42 +0000 (15:51 -0300)
committerSergio R. Caprile <scaprile@cesanta.com>
Wed, 29 Oct 2025 18:51:42 +0000 (15:51 -0300)
tutorials/core/memory/o1heap/Makefile [new file with mode: 0644]
tutorials/core/memory/o1heap/main.c [new file with mode: 0644]
tutorials/core/memory/o1heap/mongoose.c [new symlink]
tutorials/core/memory/o1heap/mongoose.h [new symlink]

diff --git a/tutorials/core/memory/o1heap/Makefile b/tutorials/core/memory/o1heap/Makefile
new file mode 100644 (file)
index 0000000..93d4c48
--- /dev/null
@@ -0,0 +1,33 @@
+SOURCES = main.c mongoose.c       # Source code files
+CFLAGS = -W -Wall -Wextra -g -I.  # Build options
+
+# O(1) Heap
+SOURCES += o1heap/o1heap/o1heap.c
+CFLAGS += -Io1heap/o1heap
+
+# Mongoose build options. See https://mongoose.ws/documentation/#build-options
+CFLAGS_MONGOOSE += -DMG_ENABLE_CUSTOM_CALLOC
+
+ifeq ($(OS),Windows_NT)
+  # Windows settings. Assume MinGW compiler. To use VC: make CC=cl CFLAGS=/MD
+  PROG ?= example.exe                 # Use .exe suffix for the binary
+  CC = gcc                            # Use MinGW gcc compiler
+  CFLAGS += -lws2_32                  # Link against Winsock library
+  DELETE = cmd /C del /f /q /s        # Command prompt command to delete files
+else
+  # Mac, Linux
+  PROG ?= example
+  DELETE = rm -rf
+endif
+
+all: $(PROG)
+       $(RUN) ./$(PROG) $(ARGS)
+
+$(PROG): $(SOURCES)
+       $(CC) $(SOURCES) $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) -o $@
+
+o1heap/o1heap/o1heap.c:  # O(1) Heap sources
+       git clone --depth 1 -b 2.1.0 https://github.com/pavel-kirienko/o1heap.git
+
+clean:
+       $(DELETE) $(PROG) *.o *.obj *.exe *.dSYM
diff --git a/tutorials/core/memory/o1heap/main.c b/tutorials/core/memory/o1heap/main.c
new file mode 100644 (file)
index 0000000..8bf8afe
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright (c) 2025 Cesanta Software Limited
+// All rights reserved
+
+#include "mongoose.h"
+#include "o1heap.h"
+
+#define POOL_SIZE (5 * MG_IO_SIZE)
+
+O1HeapInstance *s_mem;
+
+// memory allocation
+void *mg_calloc(size_t count, size_t size) {
+  size_t bytes = count * size;
+  void *ptr = o1heapAllocate(s_mem, bytes);
+  if (ptr != NULL) memset(ptr, 0, bytes);
+  if (ptr != NULL) MG_DEBUG(("%lu bytes @%p", bytes, ptr));
+  if (ptr == NULL) MG_ERROR(("Failed to allocate %lu bytes", bytes));
+  return ptr;
+}
+
+void mg_free(void *ptr) {
+  o1heapFree(s_mem, ptr);
+  if (ptr != NULL) MG_DEBUG(("block @%p", ptr));
+}
+
+// HTTP request callback
+static void fn(struct mg_connection *c, int ev, void *ev_data) {
+  if (ev == MG_EV_HTTP_MSG) {
+    struct mg_http_message *hm = (struct mg_http_message *) ev_data;
+    if (mg_match(hm->uri, mg_str("/hi"), NULL)) {
+      mg_http_reply(c, 200, "Host: foo.com\r\n", "hi\n");
+    } else if (mg_match(hm->uri, mg_str("/echo"), NULL)) {
+      mg_http_reply(c, 200, "", "%.*s", (int) hm->body.len, hm->body.buf);
+    } else if (mg_match(hm->uri, mg_str("/stats"), NULL)) {
+      struct mg_connection *t;
+      mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
+      mg_http_printf_chunk(c, "ID PROTO TYPE      LOCAL           REMOTE\n");
+      for (t = c->mgr->conns; t != NULL; t = t->next) {
+        mg_http_printf_chunk(c, "%-3lu %4s %s %M %M\n", t->id,
+                             t->is_udp ? "UDP" : "TCP",
+                             t->is_listening  ? "LISTENING"
+                             : t->is_accepted ? "ACCEPTED "
+                                              : "CONNECTED",
+                             mg_print_ip, &t->loc, mg_print_ip, &t->rem);
+      }
+      mg_http_printf_chunk(c, "");  // Don't forget the last empty chunk
+    } else {
+      struct mg_http_serve_opts opts;
+      memset(&opts, 0, sizeof(opts));
+      opts.root_dir = ".";
+      mg_http_serve_dir(c, ev_data, &opts);
+    }
+  }
+}
+
+int main(void) {
+  struct mg_mgr mgr;
+
+  void *pool = malloc(POOL_SIZE + O1HEAP_ALIGNMENT);
+  void *aligned = (void *) (((uintptr_t) pool) & ~(O1HEAP_ALIGNMENT - 1));
+  O1HeapDiagnostics d;
+  s_mem = o1heapInit(aligned, POOL_SIZE);
+  d = o1heapGetDiagnostics(s_mem);
+  MG_INFO(
+      ("Created aligned %lu-byte pool @%p, out of a %lu-byte allocated system "
+       "memory pool",
+       d.capacity, s_mem, POOL_SIZE));
+
+  mg_mgr_init(&mgr);        // Initialise event manager
+  mg_log_set(MG_LL_DEBUG);  // Set debug log level
+  mg_http_listen(&mgr, "http://localhost:8000", fn, NULL);  // Create listener
+  for (;;) {                                                // Event loop
+    mg_mgr_poll(&mgr, 1000);
+  }
+  mg_mgr_free(&mgr);
+  return 0;
+}
diff --git a/tutorials/core/memory/o1heap/mongoose.c b/tutorials/core/memory/o1heap/mongoose.c
new file mode 120000 (symlink)
index 0000000..7a2752c
--- /dev/null
@@ -0,0 +1 @@
+../../../../mongoose.c
\ No newline at end of file
diff --git a/tutorials/core/memory/o1heap/mongoose.h b/tutorials/core/memory/o1heap/mongoose.h
new file mode 120000 (symlink)
index 0000000..daff163
--- /dev/null
@@ -0,0 +1 @@
+../../../../mongoose.h
\ No newline at end of file