view seobeo/os/s_macos_edge.c @ 71:75de5903355c

Giagantic changes that update Dowa library to be more align with stb style array and hashmap. Updated Seobeo to be caching on server side instead of file level caching. Deleted bunch of things I don't really use.
author June Park <parkjune1995@gmail.com>
date Sun, 28 Dec 2025 20:34:22 -0800
parents a0f0ad5e42eb
children a8976a008a9d
line wrap: on
line source

#include <sys/event.h>
#include "seobeo/seobeo.h"


void *Seobeo_Web_Edge_Worker(void *vargs)
{
  WorkerArgs *args = vargs;
  struct kevent evlist[64];

  // Each thread creates its own kqueue to avoid race conditions
  int kq = kqueue();
  if (kq < 0) {
    perror("kqueue");
    return NULL;
  }

  // Add server socket to this thread's kqueue
  struct kevent kev = {
    .ident  = args->srv->socket,
    .filter = EVFILT_READ,
    .flags  = EV_ADD,
    .udata  = args->srv
  };
  kevent(kq, &kev, 1, NULL, 0, NULL);

  while (1)
  {
    int ne = kevent(kq, NULL, 0, evlist, 64, NULL);
    if (ne < 0) {
      if (errno == EINTR) continue;
      perror("kevent");
      continue;
    }

    for (int i = 0; i < ne; i++)
    {
      Seobeo_Handle *h = evlist[i].udata;
      if (h == args->srv)
      {
        // Accept new connections in a loop (for edge-triggered behavior)
        while (1) {
          Seobeo_Handle *cli = Seobeo_Stream_Handle_Server_Accept(args->srv);
          if (!cli) break;

          struct kevent client_kev = {
            .ident  = cli->socket,
            .filter = EVFILT_READ,
            .flags  = EV_ADD | EV_ONESHOT,
            .udata  = cli
          };
          kevent(kq, &client_kev, 1, NULL, 0, NULL);
        }
      } else {
        // Remove from kqueue first
        struct kevent del_kev = {
          .ident  = h->socket,
          .filter = EVFILT_READ,
          .flags  = EV_DELETE,
        };
        kevent(kq, &del_kev, 1, NULL, 0, NULL);

        // Handle request (this function destroys the handle internally)
        Seobeo_Web_HandleClientRequest(h, args->cache);
      }
    }
  }

  close(kq);
  return NULL;
}

void  Seobeo_Web_Edge(
    Seobeo_Handle *p_server_handle,
    int            thread_count,
    Seobeo_Cache_Entry *p_html_cache)
{
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setstacksize(&attr, 5 * 1024 * 1024); // 5 MB

  pthread_t  threads[thread_count];
  for (int i = 0; i < thread_count; i++)
  {
    WorkerArgs *args = malloc(sizeof(WorkerArgs));
    *args = (WorkerArgs){ p_server_handle, p_html_cache };

    pthread_create(&threads[i], &attr, Seobeo_Web_Edge_Worker, args);
  }
  for (int i = 0; i < thread_count; i++)
  {
    pthread_join(threads[i], NULL);
  }

  pthread_attr_destroy(&attr);
  return;
}