view seobeo/os/s_macos_edge.c @ 67:6626ec933933

[Seobeo] Separated out Client Server logic. Created test tools.
author June Park <parkjune1995@gmail.com>
date Wed, 24 Dec 2025 09:15:55 -0800
parents a0f0ad5e42eb
children 75de5903355c
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,
    Dowa_HashMap  *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;
}