디시인사이드 갤러리

갤러리 이슈박스, 최근방문 갤러리

갤러리 본문 영역

러스트가 c 대체 불간응한 EU

나르시갤로그로 이동합니다. 2025.07.23 15:00:35
조회 58 추천 0 댓글 0

러스트로는 이런거 못 짠다. ㅎㅎㅎ

러빨러들한테 속지 마라


// -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*-

/*

  c-loop.c

  This file is part of Clair.

  Copyright (C) 2021-2025 Hodong Kim, All rights reserved.

  Unauthorized copying of this software, via any medium is strictly prohibited.

  Proprietary and confidential.

  Written by Hodong Kim <hodong@nimfsoft.art>

 */

#if defined(__FreeBSD__) || defined(__OpenBSD__)

  #include <sys/param.h>

  #include <sys/event.h>

  #ifdef __FreeBSD_version

    #if __FreeBSD_version >= 1400000

      #define __C_TIMER_FD__

      #include <sys/timerfd.h>

    #endif

  #endif

#elif defined(__linux__)

  #define _POSIX_C_SOURCE 199309L // CLOCK_MONOTONIC

  #define __C_TIMER_FD__

  #include <sys/timerfd.h>

  #include <sys/epoll.h>

#endif


#include "c-loop.h"

#include "c-mem.h"

#include <stdlib.h>

#include <unistd.h>

#include "c-log.h"

#include <errno.h>

#include <string.h>

#include <assert.h>


static CLoop* c_loop;


CSource* c_source_new ()

{

  CSource* source = c_calloc (1, sizeof (CSource));


  return source;

}


void c_source_free (CSource* source)

{

  free (source);

}


CLoop* c_loop_get_default ()

{

  if (!c_loop)

    c_loop = c_loop_new ();


  return c_loop;

}


static uintptr_t idle_key_hash (const uintptr_t* key, uint32_t seed)

{

  return c_murmur3_32 ((const uint8_t*) key, 2 * sizeof (uintptr_t), seed);

}


static bool idle_key_equal (const uintptr_t* a, const uintptr_t* b)

{

  return !memcmp (a, b, 2 * sizeof (uintptr_t));

}


static void idle_key_free (void* key)

{

  free (key);

}


CLoop* c_loop_new ()

{

#if defined(__FreeBSD__) || defined(__OpenBSD__)

  int fd = kqueue ();

#elif defined __linux__

  int fd = epoll_create1 (EPOLL_CLOEXEC);

#else

  #error "This platform is not supported"

#endif

  if (fd == -1)

  {

    c_log_warning ("%s", strerror (errno));

    return nullptr;

  }


  CLoop* loop = c_calloc (1, sizeof (CLoop));

  loop->timeout = -1;

  loop->timeout_idle = 250;

  loop->capa = 4;

#if defined(__FreeBSD__) || defined(__OpenBSD__)

  loop->kq = fd;

  loop->events = c_calloc (1, loop->capa * sizeof (struct kevent));

#elif defined __linux__

  loop->epfd = fd;

  loop->events = c_calloc (1, loop->capa * sizeof (struct epoll_event));

#else

  #error "This platform is not supported"

#endif

  loop->sources = c_hash_map_new (c_ptr_hash, c_ptr_equal, nullptr, nullptr);

  loop->idles   = c_hash_map_new ((CHashFunc)  idle_key_hash,

                                  (CEqualFunc) idle_key_equal,

                                  (CFreeFunc)  idle_key_free,

                                  nullptr);

  return loop;

}


void c_loop_free (CLoop* loop)

{

  if (!loop)

    return;


  c_hash_map_free (loop->idles);

  c_hash_map_free (loop->sources);

#if defined(__FreeBSD__) || defined(__OpenBSD__)

  free (loop->events);

  close (loop->kq);

#elif defined __linux__

  free (loop->events);

  close (loop->epfd);

#else

  #error "This platform is not supported"

#endif

  free (loop);

}


void c_loop_quit (CLoop* loop)

{

  loop->run = false;

}


int c_loop_iteration (CLoop* loop)

{

  loop->depth++;

  // dispatch pending events

  CHashMapIter iter;

  c_hash_map_iter_init (&iter, loop->sources);

  CSource* source;


  while (c_hash_map_iter_next (&iter, NULL, (void**) &source))

    if (source->pending && source->pending (source) && source->dispatch)

    {

      source->dispatch (source);

      loop->depth--;

      return 1;

    }


  int timeout;


  if (loop->idles && c_hash_map_size (loop->idles))

  {

    if (loop->timeout > -1)

      timeout = C_MIN (loop->timeout, loop->timeout_idle);

    else

      timeout = loop->timeout_idle;

  }

  else

  {

    timeout = loop->timeout;

  }


  int retval;


  do {

#if defined(__FreeBSD__) || defined(__OpenBSD__)

    struct timespec* ts;

    struct timespec ts2;

    if (timeout == -1)

    {

      ts = nullptr;

    }

    else

    {

      ts2.tv_sec  = timeout * 1000000 / 1000000000;

      ts2.tv_nsec = timeout * 1000000 % 1000000000;

      ts = &ts2;

    }


    loop->n_revents = kevent (loop->kq, nullptr, 0, loop->events, loop->n_events, ts);

#elif defined __linux__

    loop->n_revents = epoll_wait (loop->epfd, loop->events, loop->n_events, timeout);

#else

  #error "This platform is not supported"

#endif

    retval = loop->n_revents;

  } while (loop->n_revents == -1 && errno == EINTR && loop->run);


  while (loop->n_revents > 0)

  {

    loop->n_revents--;

    int i = loop->n_revents;

    short revents = 0;

#if defined(__FreeBSD__) || defined(__OpenBSD__)

    if (loop->events[i].flags & EV_EOF)

      revents |= POLLHUP;

    if (loop->events[i].flags & EV_ERROR)

      revents |= POLLERR;

    if (loop->events[i].filter == EVFILT_READ)

      revents |= POLLIN;

    else if (loop->events[i].filter == EVFILT_WRITE)

      revents |= POLLOUT;

#elif defined(__linux__)

    if (loop->events[i].events & EPOLLHUP)

      revents |= POLLHUP;

    if (loop->events[i].events & EPOLLERR)

      revents |= POLLERR;

    if (loop->events[i].events & EPOLLIN)

      revents |= POLLIN;

    else if (loop->events[i].events & EPOLLOUT)

      revents |= POLLOUT;

#else

  #error "This platform is not supported"

#endif

    if (revents)

    {

      if ((source = c_hash_map_lookup (loop->sources,

#if defined(__FreeBSD__) || defined(__OpenBSD__)

                                       C_INT_TO_VOIDP (loop->events[i].ident))))

#elif defined(__linux__)

                                       C_INT_TO_VOIDP (loop->events[i].data.fd))))

#else

  #error "This platform is not supported"

#endif

      {

        source->revents = revents;


        if (source->dispatch)

          source->dispatch (source);

      }

    }

  }


  if (loop->depth == 1 && loop->idles && c_hash_map_size (loop->idles))

  {

    uintptr_t* key;

    void* user_data;


    c_hash_map_iter_init (&iter, loop->idles);


    while (c_hash_map_iter_next (&iter, (void**) &key, &user_data))

    {

      CCallback1 callback = (CCallback1) key[0];

      callback (user_data);

    }

  }


  loop->depth--;

  return retval;

}


bool c_loop_run (CLoop* loop)

{

  loop->run = true;


  while (loop->run)

  {

    if (c_loop_iteration (loop) == -1)

    {

      if (errno == EINTR)

        c_log_info ("%s", strerror (errno));

      else

        c_log_critical ("%s", strerror (errno));


      return false;

    }

  }


  return true;

}


void c_loop_add_source (CLoop* loop, CSource* source)

{

  if (source->fd < 0)

  {

    c_log_warning ("c_loop_add_source failed: source->fd: %d", source->fd);

    return;

  }


#if defined(__FreeBSD__) || defined(__OpenBSD__)

  struct kevent kevents[2];

  int status;

  int n_events = 0;


  if (source->events & POLLIN)

  {

    EV_SET (&kevents[n_events], source->fd, EVFILT_READ, EV_ADD, 0, 0, 0);

    n_events++;

  }


  if (source->events & POLLOUT)

  {

    EV_SET (&kevents[n_events], source->fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);

    n_events++;

  }


  status = kevent (loop->kq, kevents, n_events, NULL, 0, NULL);

  if (status == -1)

  {

    c_log_warning ("kevent (loop->kq, kevents, %d, NULL, 0, NULL) failed: %s",

                   n_events, strerror (errno));

    return;

  }

#elif defined __linux__

  struct epoll_event eevent = { 0 };

  int status;

  int n_events = 1;

  eevent.events = 0;

  eevent.data.fd = source->fd;


  if (source->events & POLLIN)

    eevent.events |= EPOLLIN;


  if (source->events & POLLOUT)

    eevent.events = EPOLLOUT;


  status = epoll_ctl (loop->epfd, EPOLL_CTL_ADD, source->fd, &eevent);

  if (status == -1)

  {

    c_log_warning ("epoll_ctl EPOLL_CTL_ADD %d  failed: %s",

                   source->fd, strerror (errno));

    return;

  }

#else

  #error "This platform is not supported"

#endif


#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__linux__)

  loop->n_events += n_events;


  if (loop->n_events == loop->capa)

#else

  #error "This platform is not supported"

#endif

  {

    loop->capa *= 2;

#if defined(__FreeBSD__) || defined(__OpenBSD__)

    loop->events = c_realloc (loop->events,

                              loop->capa * sizeof (struct kevent));

#elif defined __linux__

    loop->events = c_realloc (loop->events,

                              loop->capa * sizeof (struct epoll_event));

#else

  #error "This platform is not supported"

#endif

  }


  c_hash_map_insert (loop->sources, C_INT_TO_VOIDP (source->fd), source);

}


void c_loop_remove_source (CLoop* loop, CSource* source)

{

  int status;

  int n_events = 0;

#if defined(__FreeBSD__) || defined(__OpenBSD__)

  struct kevent kevents[2];


  if (source->events & POLLIN)

  {

    EV_SET (&kevents[n_events], source->fd, EVFILT_READ, EV_DELETE, 0, 0, 0);

    n_events++;

  }


  if (source->events & POLLOUT)

  {

    EV_SET (&kevents[n_events], source->fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0);

    n_events++;

  }


  status = kevent (loop->kq, kevents, n_events, NULL, 0, NULL);

  if (status == -1)

  {

    c_log_warning ("kevent (loop->kq, kevents, 1, NULL, 0, NULL) failed: %s",

                   strerror (errno));

    return;

  }


  for (int i = 0; i < loop->n_revents; i++)

  {

    if (loop->events[i].ident == source->fd)

    {

      loop->events[i].ident  = -1;

      loop->events[i].filter = 0;

      loop->events[i].flags  = 0;

    }

  }

#elif defined __linux__

  n_events = 1;


  status = epoll_ctl (loop->epfd, EPOLL_CTL_DEL, source->fd, nullptr);

  if (status == -1)

  {

    c_log_warning ("epoll_ctl EPOLL_CTL_DEL %d  failed: %s",

                   source->fd, strerror (errno));

    return;

  }


  for (int i = 0; i < loop->n_revents; i++)

  {

    if (loop->events[i].data.fd == source->fd)

    {

      loop->events[i].events  = 0;

      loop->events[i].data.fd = -1;

      break;

    }

  }

#else

  #error "This platform is not supported"

#endif


  loop->n_events -= n_events;


  if (loop->n_events < loop->capa / 4)

  {

    loop->capa /= 2;

#if defined(__FreeBSD__) || defined(__OpenBSD__)

    loop->events = c_realloc (loop->events,

                              loop->capa * sizeof (struct kevent));

#elif defined __linux__

    loop->events = c_realloc (loop->events,

                              loop->capa * sizeof (struct epoll_event));

#else

  #error "This platform is not supported"

#endif

  }


  c_hash_map_remove (loop->sources, C_INT_TO_VOIDP (source->fd));

}


static void fd_dispatch (CSource* source)

{

  if (source->callback)

  {

    CFdCallback callback = (CFdCallback) source->callback;

    callback (source->fd, source->revents, source->user_data);

  }

}


void c_loop_add_fd (CLoop*      loop,

                    int         fd,

                    short       events,

                    CFdCallback callback,

                    void*       user_data)

{

  if (fd < 0)

  {

    c_log_warning ("c_loop_add_fd failed: fd: %d", fd);

    return;

  }


  CSource* source   = c_source_new ();

  source->fd        = fd;

  source->events    = events;

  source->dispatch  = fd_dispatch;

  source->callback  = (CCallback) callback;

  source->user_data = user_data;

  c_loop_add_source (loop, source);

}


void c_loop_remove_fd (CLoop* loop, int fd)

{

  if (fd < 0)

  {

    c_log_warning ("c_loop_remove_fd failed: %d", fd);

    return;

  }


  CSource* source = c_hash_map_lookup (loop->sources, C_INT_TO_VOIDP (fd));

  c_loop_remove_source (loop, source);

  c_source_free (source);

}


void c_loop_mod_fd (CLoop* loop, int fd, short events)

{

  CSource* source = c_hash_map_lookup (loop->sources, C_INT_TO_VOIDP (fd));


#if defined(__FreeBSD__) || defined(__OpenBSD__)

  struct kevent kevents[2];

  int i = 0;


  if ((source->events & POLLIN) - (events & POLLIN) > 0)

  {

    EV_SET (&kevents[i], fd, EVFILT_READ, EV_DELETE, 0, 0, 0);

    i++;

  }

  else if ((source->events & POLLIN) - (events & POLLIN) < 0)

  {

    EV_SET (&kevents[i], fd, EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, 0);

    i++;

  }


  if ((source->events & POLLOUT) - (events & POLLOUT) > 0)

  {

    EV_SET (&kevents[i], fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0);

    i++;

  }

  else if ((source->events & POLLOUT) - (events & POLLOUT) < 0)

  {

    EV_SET (&kevents[i], fd, EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, 0);

    i++;

  }


  if (i > 0)

  {

    int status = kevent (loop->kq, kevents, i, NULL, 0, NULL);

    if (status == -1)

    {

      c_log_warning ("kevent (loop->kq, kevents, i, NULL, 0, NULL) failed: %s",

                     i, strerror (errno));

    }

  }

#elif defined __linux__

  struct epoll_event eevent = { 0 };


  if (events & POLLIN)

    eevent.events = EPOLLIN;

  if (events & POLLOUT)

    eevent.events = EPOLLOUT;


  eevent.data.fd = fd;

  int status = epoll_ctl (loop->epfd, EPOLL_CTL_MOD, fd, &eevent);

  if (status == -1)

    c_log_warning ("epoll_ctl EPOLL_CTL_MOD %d %u failed: %s",

                   fd, eevent.events, strerror (errno));

#else

  #error "This platform is not supported"

#endif


  source->events = events;

}


void* c_loop_add_idle (CLoop* loop, CCallback1 callback, void* user_data)

{

  uintptr_t* key = c_malloc (2 * sizeof (uintptr_t));

  key[0] = (uintptr_t) callback;

  key[1] = (uintptr_t) user_data;

  c_hash_map_insert (loop->idles, key, user_data);

  return callback;

}


void c_loop_remove_idle (CLoop* loop, CCallback1 callback, void* user_data)

{

  uintptr_t key[2] = { (uintptr_t) callback, (uintptr_t) user_data };

  c_hash_map_remove (loop->idles, key);

}


static void timer_dispatch (CSource* source)

{

  c_log_debug ("timer_dispatch: source->fd: %d", source->fd);


  int status;


#if defined(__C_TIMER_FD__)

  uint64_t n_expirations;

  do {

    status = read (source->fd, &n_expirations, sizeof (uint64_t));

  } while (status == -1 && errno == EINTR);

#else

  struct kevent event;

  status = kevent (source->fd, NULL, 0, &event, 1, NULL);

#endif


  if (status == -1)

  {

    c_log_critical ("%s", strerror (errno));

    return;

  }

  else if (status > 0 && source->callback)

  {

    CCallback1 callback = (CCallback1) source->callback;

    callback (source->user_data);

  }


  return;

}


int c_loop_add_timer (CLoop* loop, int ms, CCallback1 callback, void* user_data)

{

#if defined(__C_TIMER_FD__)

  int fd = timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC);

#else

  int fd = kqueue ();

#endif


  if (fd == -1)

  {

    c_log_warning ("%s", strerror (errno));

    return -1;

  }


  if (!c_loop_mod_timer (loop, fd, ms))

  {

    close (fd);

    return -1;

  }


  CSource* source   = c_source_new ();

  source->fd        = fd;

  source->events    = POLLIN;

  source->dispatch  = timer_dispatch;

  source->callback  = (CCallback) callback;

  source->user_data = user_data;

  c_loop_add_source (loop, source);


  return fd;

}


void c_loop_remove_timer (CLoop* loop, int fd)

{

  if (fd < 0)

  {

    c_log_warning ("fd is less than 0: i%d", fd);

    return;

  }


  CSource* source = c_hash_map_lookup (loop->sources, C_INT_TO_VOIDP (fd));


  if (source)

  {

#if defined(__C_TIMER_FD__)

    struct itimerspec ts = { { 0, 0 }, { 0, 0 } };

    if (timerfd_settime (fd, 0, &ts, nullptr))

      c_log_warning ("%s", strerror (errno));

#else

    struct kevent event;

    EV_SET (&event, fd, EVFILT_TIMER, EV_DELETE | EV_DISABLE, 0, 0, 0);

    int status = kevent (source->fd, &event, 1, NULL, 0, NULL);

    if (status == -1)

    {

      c_log_warning ("kevent (%d, &event, 1, NULL, 0, NULL) failed: %s", fd,

                     strerror (errno));

    }

#endif


    c_loop_remove_source (loop, source);

    c_source_free (source);


    if (fd > -1)

      close (fd);

  }

}


bool c_loop_mod_timer (CLoop* loop, int fd, int ms)

{

  if (fd < 0)

  {

    c_log_warning ("fd < 0: %d", fd);

    return false;

  }


#if defined(__C_TIMER_FD__)

  long nsec;


  if (ms > 0)

    nsec = (long) ms * 1000000;

  else if (ms == 0)

    nsec = 1;

  else

    nsec = 0;


  struct itimerspec its;

  // 1000000000 ns = 1 sec

  its.it_value.tv_sec     = nsec / 1000000000;

  its.it_value.tv_nsec    = nsec % 1000000000;

  its.it_interval.tv_sec  = its.it_value.tv_sec;

  its.it_interval.tv_nsec = its.it_value.tv_nsec;


  if (timerfd_settime (fd, 0, &its, nullptr))

  {

    c_log_warning ("timerfd_settime failed: %s", strerror (errno));

    return false;

  }

#else

  struct kevent event;

  int status;


  if (ms < 0)

    EV_SET (&event, fd, EVFILT_TIMER, EV_ADD | EV_DISABLE, 0, 0, 0);

  else

    EV_SET (&event, fd, EVFILT_TIMER, EV_ADD | EV_ENABLE, 0, ms, 0);


  status = kevent (fd, &event, 1, NULL, 0, NULL);

  if (status == -1)

  {

    c_log_warning ("kevent (fd, &event, 1, NULL, 0, NULL) failed: %s",

                   strerror (errno));

    return false;

  }

#endif


  return true;

}




추천 비추천

0

고정닉 0

0

댓글 영역

전체 댓글 0
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 의외로 연애 못할 것 같은 연애 하수 스타는? 운영자 25/08/04 - -
2877905 신도 종교도 저의 탄생으로 부정됩니다. 프갤러(220.84) 08.04 27 0
2877904 루비대머리 어디갔나 했더니 나르시였음? 프갤러(121.139) 08.04 38 0
2877903 취업할려면 대학원까지가야되는데 왜 해킹보안학과 가는거임?? 뒷통수한방(1.213) 08.04 28 0
2877902 넥도리아 > ㅆㅇㅆ 프갤러(121.139) 08.04 35 1
2877901 혼에 꽂힌 비수 덕분에 수년째 밥을 똑바로 못먹습니다. 프갤러(220.84) 08.04 30 0
2877900 해킹보안학과 가면 취업 쉬움?? [4] 뒷통수한방(1.213) 08.04 63 0
2877899 부모쯤은 맡겨도 된다고 착각했습니다. 그래요. 프갤러(220.84) 08.04 26 0
2877898 나는 코딩하는 원숭이당당당 통암기원숭(61.253) 08.04 39 0
2877897 어도비 프리미어 비슷한 올리브 비디오 에디터 개발 중단 발명도둑잡기갤로그로 이동합니다. 08.04 32 0
2877896 믿음직하지도 않았구요 활로가 없네요 프갤러(220.84) 08.04 31 0
2877895 치킨먹는다. [1] 넥도리아(223.38) 08.04 38 0
2877894 이준석... 지지 넥도리아(223.38) 08.04 46 0
2877892 우끼익! 통암기원숭(61.253) 08.04 37 0
2877891 나는 강하다. 프갤러(121.139) 08.04 40 1
2877890 곽튜브도 20대에 연애3번했는데 모쏠들은 정체가 뭐냐?? [2] 뒷통수한방(1.213) 08.04 55 0
2877889 나님.. 분명히 봤어.. 가슴.. 가슴에.. 점이 있었다고..!! [1] ♥꽃보다냥덩♥갤로그로 이동합니다. 08.04 61 0
2877888 학교 커리큘럼 안좋은 편이야? [2] 프갤러(14.7) 08.04 59 0
2877887 운영체제 들으려고 하는데 [2] 프갤러(118.217) 08.04 56 0
2877886 일본 외노자 7월 급여가 나왔습니다 [5] 프로외노자갤로그로 이동합니다. 08.04 147 0
2877885 영혼이 뜯어먹히는 고문! 프갤러(220.84) 08.04 27 0
2877884 하이닉스 직원 25년 1월 월급명세서 [3] 발명도둑잡기(118.216) 08.04 71 0
2877883 월요일 비 온다며 왜 안 와 발명도둑잡기(118.216) 08.04 22 0
2877882 운영체제 들으려는데 선수과목 뭐 있음? [7] 프갤러(118.217) 08.04 61 0
2877880 해킹공부까지 갈필요도 없고 그냥 그누보드 취약점널렸는데 프갤러(183.101) 08.04 39 0
2877879 사라진 인간의 환영이 아른거리네요. 프갤러(220.84) 08.04 28 0
2877878 나도 20살때 개발공부하고싶었어 밀우갤로그로 이동합니다. 08.04 32 0
2877877 러스트로 하자는 주장요즘 많이 사라짐 프갤러(183.101) 08.04 36 0
2877876 러스트의 '견고함'이 대규모 리팩토링의 덫이 될 때 나르시갤로그로 이동합니다. 08.04 36 0
2877875 남걱정할시간에 내인생이나 잘돌봐야지 프갤러(183.101) 08.04 29 1
2877874 항상 프로그래밍에 감사한다. 재능도 없고 지식도 일천한 나에게 [1] ㅆㅇㅆ(124.216) 08.04 58 0
2877872 재작년에 취업 못해서 벌을 받아요. [2] 프갤러(220.84) 08.04 56 0
2877871 이벤트 루프, 어떤 구성이 최선일까? (4+1가지 아키텍처) [3] 나르시갤로그로 이동합니다. 08.04 51 0
2877870 oecd 기준 우울증 압도적 1위국가 대한민국 프갤러(183.101) 08.04 24 0
2877869 러스트는 선택받은 소수만이 할만한 언어다. [1] 프갤러(218.154) 08.04 46 0
2877868 자유마저 저절로는 안 옵니다. 프갤러(220.84) 08.04 23 0
2877867 유튜브 자막 보는 웹브라우저 확장기능 발명도둑잡기갤로그로 이동합니다. 08.04 18 0
2877866 이렇게 더운날 [2] 개멍청한유라갤로그로 이동합니다. 08.04 41 0
2877865 크롬 열린 탭 저장 확장기능 비교 [1] 발명도둑잡기갤로그로 이동합니다. 08.04 27 0
2877864 해킹 공부하면 현타온다 [5] 루도그담당(118.235) 08.04 58 0
2877863 그나저나 자동차 업계 임베디드 사람들이 걱정이네 네오커헠(1.237) 08.04 76 0
2877862 면목이 없어요. 늘 죄송합니다. 프갤러(220.84) 08.04 24 0
2877861 언젠가 러스트도 완전히 떼야하는데 아직 러스트 코드는 작성 안해봄 ㅆㅇㅆ(124.216) 08.04 36 0
2877860 주변에 꽃 나무 숲 등 자연 있으면 정신건강 좋아지고 발명도둑잡기(118.216) 08.04 24 0
2877859 비동기는 실행 모델 개념으로 접근해야함. 컨트롤 플로우 흐름으로 봐야함 [4] ㅆㅇㅆ(124.216) 08.04 53 0
2877858 매일 반복되는 삶이라는 여정이 너무 기대되고 두근거려요... ㅇㅇ(223.39) 08.04 34 0
2877857 비동기 매커니즘은 언어마다 구현이 다름 [4] ㅆㅇㅆ(124.216) 08.04 67 0
2877856 이벤트루프는 비동기를 구현하는 방법일뿐이고 [1] 루도그담당(118.235) 08.04 35 0
2877855 이정도면 부모님 노후걱정 안해도 되냐 [2] 아스카영원히사랑해갤로그로 이동합니다. 08.04 53 1
2877854 과거도 현재도 미래도 없었습니다. 프갤러(220.84) 08.04 26 0
2877853 Cursor IDE + Gemini CLI 가 현 웹앱개발 작업환경이네 [4] 네오커헠(1.237) 08.04 91 0
뉴스 에스파, 9월 5일 미니 6집 '리치맨' 발매 디시트렌드 08.04
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2