1313#include < algorithm>
1414#include < cstring>
1515#include < pthread.h>
16+
17+ #ifdef __APPLE__
18+ #include < sys/event.h>
19+ #include < sys/time.h>
20+ #else
1621#include < sys/epoll.h>
22+ #endif
1723
1824namespace slick ::socket
1925{
@@ -204,7 +210,13 @@ inline bool TCPServerBase<DerivedT>::send_data(int client_id, const std::vector<
204210template <typename DerivedT>
205211inline void TCPServerBase<DerivedT>::close_socket(SocketT socket)
206212{
213+ #ifdef __APPLE__
214+ struct kevent ev;
215+ EV_SET (&ev, socket, EVFILT_READ, EV_DELETE, 0 , 0 , 0 );
216+ kevent (epoll_fd_, &ev, 1 , nullptr , 0 , nullptr );
217+ #else
207218 epoll_ctl (epoll_fd_, EPOLL_CTL_DEL, socket, nullptr );
219+ #endif
208220 socket_to_client_id_.erase (socket);
209221 close (socket);
210222}
@@ -226,24 +238,92 @@ void TCPServerBase<DerivedT>::server_loop()
226238 // Set CPU affinity if specified
227239 if (config_.cpu_affinity >= 0 )
228240 {
241+ #ifndef __APPLE__
229242 cpu_set_t cpuset;
230243 CPU_ZERO (&cpuset);
231244 CPU_SET (config_.cpu_affinity , &cpuset);
232-
245+
233246 pthread_t thread = pthread_self ();
234247 int result = pthread_setaffinity_np (thread, sizeof (cpu_set_t ), &cpuset);
235248 if (result != 0 )
236249 {
237- LOG_WARN (" Failed to set CPU affinity to core {}: {}" ,
250+ LOG_WARN (" Failed to set CPU affinity to core {}: {}" ,
238251 config_.cpu_affinity , std::strerror (result));
239252 }
240253 else
241254 {
242255 LOG_INFO (" Server thread pinned to CPU core {}" , config_.cpu_affinity );
243256 }
257+ #else
258+ LOG_WARN (" CPU affinity not supported on macOS" );
259+ #endif
260+ }
261+
262+ #ifdef __APPLE__
263+ // macOS: Use kqueue
264+ epoll_fd_ = kqueue ();
265+ if (epoll_fd_ < 0 )
266+ {
267+ LOG_ERROR (" Failed to create kqueue instance: {}" , std::strerror (errno));
268+ return ;
269+ }
270+
271+ // Add server socket to kqueue
272+ struct kevent ev;
273+ EV_SET (&ev, server_socket_, EVFILT_READ, EV_ADD, 0 , 0 , 0 );
274+ if (kevent (epoll_fd_, &ev, 1 , nullptr , 0 , nullptr ) < 0 )
275+ {
276+ LOG_ERROR (" Failed to add server socket to kqueue: {}" , std::strerror (errno));
277+ close (epoll_fd_);
278+ epoll_fd_ = -1 ;
279+ return ;
280+ }
281+
282+ const int MAX_EVENTS = 64 ;
283+ struct kevent events[MAX_EVENTS];
284+ std::vector<uint8_t > buffer (config_.receive_buffer_size );
285+
286+ while (running_.load ())
287+ {
288+ // Wait for events with 1 second timeout
289+ int num_events = kevent (epoll_fd_, nullptr , 0 , events, MAX_EVENTS, nullptr );
290+ if (num_events < 0 )
291+ {
292+ if (errno == EINTR)
293+ {
294+ continue ;
295+ }
296+ LOG_ERROR (" kevent failed: {}" , std::strerror (errno));
297+ break ;
298+ }
299+
300+ for (int i = 0 ; i < num_events; i++)
301+ {
302+ int fd = static_cast <int >(events[i].ident );
303+ if (fd == server_socket_)
304+ {
305+ // New connection on server socket
306+ accept_new_client ();
307+ }
308+ else
309+ {
310+ auto it = socket_to_client_id_.find (fd);
311+ if (it != socket_to_client_id_.end ())
312+ {
313+ handle_client_data (it->second , buffer);
314+ }
315+ }
316+ }
244317 }
245318
246- // Create epoll instance
319+ // Clean up
320+ if (epoll_fd_ >= 0 )
321+ {
322+ close (epoll_fd_);
323+ epoll_fd_ = -1 ;
324+ }
325+ #else
326+ // Linux: Use epoll
247327 epoll_fd_ = epoll_create1 (0 );
248328 if (epoll_fd_ < 0 )
249329 {
@@ -300,11 +380,12 @@ void TCPServerBase<DerivedT>::server_loop()
300380 }
301381
302382 // Clean up
303- if (epoll_fd_ != nullptr )
383+ if (epoll_fd_ >= 0 )
304384 {
305- epoll_close (epoll_fd_);
306- epoll_fd_ = nullptr ;
385+ close (epoll_fd_);
386+ epoll_fd_ = - 1 ;
307387 }
388+ #endif
308389}
309390
310391template <typename DerivedT>
@@ -330,7 +411,17 @@ void TCPServerBase<DerivedT>::accept_new_client()
330411 fcntl (client_socket, F_SETFL, flags | O_NONBLOCK);
331412 }
332413
333- // Add client socket to epoll
414+ // Add client socket to event system
415+ #ifdef __APPLE__
416+ struct kevent ev;
417+ EV_SET (&ev, client_socket, EVFILT_READ, EV_ADD, 0 , 0 , 0 );
418+ if (kevent (epoll_fd_, &ev, 1 , nullptr , 0 , nullptr ) < 0 )
419+ {
420+ LOG_ERROR (" Failed to add client socket to kqueue: {}" , std::strerror (errno));
421+ close (client_socket);
422+ return ;
423+ }
424+ #else
334425 struct epoll_event ev;
335426 ev.events = EPOLLIN | EPOLLET; // Edge-triggered mode
336427 ev.data .fd = client_socket;
@@ -340,6 +431,7 @@ void TCPServerBase<DerivedT>::accept_new_client()
340431 close (client_socket);
341432 return ;
342433 }
434+ #endif
343435
344436 // Get client address
345437 char addr_str[INET_ADDRSTRLEN];
0 commit comments