è² è·ã®é«ããã«ãã¹ã¬ãããŸãã¯åæ£ã¢ããªã±ãŒã·ã§ã³ã®éçºåéã§ã¯ãéåæããã°ã©ãã³ã°ã«é¢ããè°è«ããã°ãã°çºçããŸãã ä»æ¥ã¯éåæã®è©³çŽ°ãæãäžãããããçºçãããšãã®ç¶æ
ã䜿çšããã³ãŒããšããã°ã©ãã³ã°èšèªã«ã©ã®ããã«åœ±é¿ããããåŠã³ãŸãã FuturesãšPromisesãå¿
èŠãªçç±ãç解ããã³ã«ãŒãã³ãšãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã«è§ŠããŸãã ããã«ããããœãããŠã§ã¢éçºäžã«çãããã¬ãŒããªããããæ確ã«ãªããŸãã
ãã®è³æã¯ãYandex Data Analysis Schoolã®æåž«ã§ããIvan Puzyrevskyã®å ±åæžã«åºã¥ããŠããŸãã
ãããªé²ç»
1.ã³ã³ãã³ã
2.ã¯ããã«
ã¿ãªãããããã«ã¡ã¯ãç§ã®ååã¯ã€ãŽã¡ã³ã»ããžã¬ãã¹ããŒãã€ã³ããã¯ã¹ã§åããŠããŸãã éå»6幎éãããŒã¿ã¹ãã¬ãŒãžãšããŒã¿åŠçã®ã€ã³ãã©ã¹ãã©ã¯ãã£ã«æºãã£ãŠããŸããããä»ã§ã¯ãæ
è¡ãããã«ããã±ãããæ±ããŠè£œåã«åãæ¿ããŸããã ç§ã¯ã€ã³ãã©ã¹ãã©ã¯ãã£ã§é·ãéåããŠããã®ã§ãããŸããŸãªããŒãæžã¿ã¢ããªã±ãŒã·ã§ã³ãäœæããæ¹æ³ã«ã€ããŠå€ãã®çµéšãç©ãã§ããŸãã åœç€Ÿã®ã€ã³ãã©ã¹ãã©ã¯ãã£ã¯ãæ¯æ¥24*7*365
ãæ°åå°ã®ãã·ã³ã§ç¶ç¶çã«çšŒåããŠããŸãã åœç¶ãä¿¡é Œæ§ãé«ãå¹ççã«æ©èœããäŒç€Ÿã課ãã¿ã¹ã¯ã解決ããããã«ã³ãŒããèšè¿°ããå¿
èŠããããŸãã
ä»æ¥ã¯éåæã«ã€ããŠã話ããŸãã éåæãšã¯äœã§ããïŒ ããã¯ãäœããšæéå
ã®äœãã®äžäžèŽã§ãã ãã®èª¬æãããä»æ¥è©±ãããšã¯äžè¬çã«æ確ã§ã¯ãããŸããã ãã®åé¡ãã©ããããããæ確ã«ããããã«ããHelloãworldïŒããšããäŸãå¿
èŠã§ãã éåææ§ã¯éåžžããããã¯ãŒã¯ã¢ããªã±ãŒã·ã§ã³ãäœæããã³ã³ããã¹ãã§çºçããããããHelloãworldïŒãã«é¡äŒŒãããããã¯ãŒã¯ãäœæããŸãã ããã¯ãã³ãã³ã¢ããªã§ãã ã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
socket s; string x; x = read_from_socket(s, 4); if (x == "ping") { write_to_socket(s, "pong"); } return;
ãœã±ãããäœæããããããè¡ãèªã¿åããpingã§ãããã©ããã確èªããŠãããå¿çãšããŠpongãæžã蟌ã¿ãŸãã éåžžã«ã·ã³ãã«ã§æ確ã ã³ã³ãã¥ãŒã¿ãŒç»é¢ã«ãã®ãããªã³ãŒãã衚瀺ããããšã©ããªããŸããïŒ ãã®ã³ãŒãã¯ããããã®æé ã®ã·ãŒã±ã³ã¹ãšèããŠããŸãã
å®éã®ç©ççãªæéã®èŠ³ç¹ããããã¹ãŠã¯å°ãåã£ãŠããŸãã
ãã®ãããªã³ãŒããå®éã«æžããŠå®è¡ãã人ã¯ãèªã¿åãã¹ãããã®åŸãšã¹ãããã®åŸ
æžã蟌ã¿ã¯ãããã°ã©ã ãã³ãŒãã®èŠ³ç¹ããã¯äœãããŠããªãããã«èŠããããªã泚ç®ãã¹ãæéééã§ãããå
éšã§ã¯ãå
¥åºåããšåŒã°ããæ©æ¢°ãåäœããŸãã
I / Oã®éããã±ããã¯ãããã¯ãŒã¯ãä»ããŠäº€æããããã¹ãŠã®ä»éããäœã¬ãã«ã®äœæ¥ãè¡ãããŸãã æèå®éšãè¡ã£ãŠã¿ãŸãããããã®ãããªããã°ã©ã ã1ã€ååŸãã1ã€ã®ç©çããã»ããµã§å®è¡ãããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ããªããšæ³å®ããŠãã©ããªããŸããïŒ ããã»ããµã¯åæ¢ã§ãããåœä»€ã«åŸããã«ãµã€ã¯ã«ãç¶ããç¡é§ãªãšãã«ã®ãŒãç¡é§ã«ããŸãã
ãã®æéäžã«äœã圹ã«ç«ã€ããšãã§ãããã©ãããšããçåãçããŸãã ç§ãã¡ã®ã¢ããªã±ãŒã·ã§ã³ã¯äœãããŠããªãããã«èŠããŸãããéåžžã«èªç¶ãªè³ªåã§ããããã«å¯Ÿããçãã¯ãããã»ããµã®é»åãç¯çŽããæçšãªãã®ã«äœ¿çšããããšãå¯èœã«ããŸãã
3.åºæ¬ã³ã³ã»ãã
3.1ã å®è¡ã®ã¹ã¬ãã
ãã®ã¿ã¹ã¯ã«ã©ã®ããã«ã¢ãããŒãã§ããŸããïŒ æŠå¿µã調æŽããŸãããã åºæ¬çãªæäœãŸãã¯ã¹ãããã®æå³ã®ããã·ãŒã±ã³ã¹ãåç
§ããŠããå®è¡ã®ãããŒããšèšããŸãã æå³ã®ãããã®ã¯ãç§ãå®è¡ã®æµãã«ã€ããŠè©±ãæèã«ãã£ãŠæ±ºãŸããŸãã ã€ãŸããã·ã³ã°ã«ã¹ã¬ããã¢ã«ãŽãªãºã ïŒAho-Korasikãã°ã©ãã«ããæ€çŽ¢ïŒã«ã€ããŠè©±ããŠããå Žåããã®ã¢ã«ãŽãªãºã èªäœã¯æ¢ã«å®è¡ã®ã¹ã¬ããã§ãã 圌ã¯åé¡ã解決ããããã«ããã€ãã®ã¹ããããèžã¿ãŸãã
ç§ãããŒã¿ããŒã¹ã«ã€ããŠè©±ããŠããå Žåãå®è¡ã®1ã€ã®ã¹ã¬ããã¯ã1ã€ã®çä¿¡èŠæ±ãåŠçããããã«ããŒã¿ããŒã¹ã«ãã£ãŠå®è¡ãããã¢ã¯ã·ã§ã³ã®äžéšã§ããå¯èœæ§ããããŸãã WebãµãŒããŒã«ã€ããŠãåãããšãèšããŸãã äœããã®ã¢ãã€ã«ã¢ããªã±ãŒã·ã§ã³ãŸãã¯Webã¢ããªã±ãŒã·ã§ã³ãäœæããŠããå Žåã1ã€ã®ãŠãŒã¶ãŒæäœïŒããšãã°ããã¿ã³ã®ã¯ãªãã¯ããããã¯ãŒã¯ã®çžäºäœçšãããŒã«ã«ã¹ãã¬ãŒãžãšã®çžäºäœçšãªã©ïŒãæäŸããŸãã ã¢ãã€ã«ã¢ããªã±ãŒã·ã§ã³ã®èŠ³ç¹ããèŠããããã®ã¢ã¯ã·ã§ã³ã®ã·ãŒã±ã³ã¹ã¯ãå®è¡ã®å¥ã®æå³ã®ãããããŒã«ããªããŸãã ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®èŠ³ç¹ããèŠããšãããã»ã¹ãŸãã¯ããã»ã¹ã¹ã¬ããã¯æå³ã®ããå®è¡ã¹ã¬ããã§ããããŸãã
3.2ã ãã«ãã¿ã¹ã¯ãšåæå®è¡
ããã©ãŒãã³ã¹ã®åºç€ã¯ããã®ãããªããªãã¯ãå®è¡ããèœåã§ããç©çã¿ã€ã ããŒã¹ã«ãã€ããå«ãå®è¡ã¹ã¬ããã1ã€ããå Žåããããã®ãã€ããäœãæçšãªãã®ã§åããŸã-ä»ã®å®è¡ã¹ã¬ããã®æé ã«åŸããŸãã
ããŒã¿ããŒã¹ã¯éåžžãåæã«å€ãã®ã¯ã©ã€ã¢ã³ãã«ãµãŒãã¹ãæäŸããŸãã ããé«ãã¬ãã«ã®1ã€ã®å®è¡ã¹ã¬ããã®ãã¬ãŒã ã¯ãŒã¯å
ã§è€æ°ã®å®è¡ã¹ã¬ããã®äœæ¥ãçµã¿åãããããšãã§ããå Žåãããã¯ãã«ãã¿ã¹ã¯ãšåŒã°ããŸãã ã€ãŸãããã«ãã¿ã¹ã¯ãšã¯ãå°ããªã¿ã¹ã¯ã®è§£æ±ºã«åŸå±ãã1ã€ã®å€§ããªå®è¡ãããŒã®ãã¬ãŒã ã¯ãŒã¯å
ã§ã¢ã¯ã·ã§ã³ãå®è¡ããããšã§ãã
ãã«ãã¿ã¹ã¯ã®æŠå¿µãšäžŠååŠçãæ··åããªãããã«ããããšãéèŠã§ãã 䞊è¡æ§-
ãããã¯ã©ã³ã¿ã€ã ç°å¢ã®ããããã£ã§ããã1ã€ã®ã¹ãããã§ã1ã€ã®ã¹ãããã§ãç°ãªãå®è¡ã¹ã¬ããã§é²è¡ããããšãã§ããŸãã 2ã€ã®ç©çããã»ããµãããå Žåã1ã¯ããã¯ãµã€ã¯ã«ã§2ã€ã®åœä»€ãå®è¡ã§ããŸãã ããã°ã©ã ã1ã€ã®ããã»ããµã§å®è¡ãããŠããå Žåãåã2ã€ã®åœä»€ãå®è¡ããã«ã¯2ã¯ããã¯ãµã€ã¯ã«ããããŸãã
ãããã®æŠå¿µã¯ç°ãªãã«ããŽãªã«åé¡ããããããæ··åããªãããã«ããããšãéèŠã§ãã ãã«ãã¿ã¹ã¯ã¯ãããã°ã©ã ã®æ©èœã§ãããããŸããŸãªã¿ã¹ã¯ã®å¯å€äœæ¥ãšããŠå
éšçã«æ§æãããŸãã 䞊è¡æ§ã¯ã©ã³ã¿ã€ã ç°å¢ã®ããããã£ã§ããã1ã¯ããã¯ãµã€ã¯ã«ã§è€æ°ã®ã¿ã¹ã¯ãåŠçã§ããŸãã
å€ãã®ç¹ã§ãéåæã³ãŒããšéåæã³ãŒãã®äœæã¯ãã«ãã¿ã¹ã¯ã³ãŒãã®äœæã§ãã äž»ãªå°é£ã¯ãã¿ã¹ã¯ã®ãšã³ã³ãŒãæ¹æ³ãšãããã®ç®¡çæ¹æ³ã§ãã ãããã£ãŠãä»æ¥ã¯ããã«ã€ããŠè©±ããŸã-ãã«ãã¿ã¹ã¯ã³ãŒãã®èšè¿°ã
4.ãããã¯ãšåŸ
æ©
ããã€ãã®ç°¡åãªäŸããå§ããŸãããã ãã³ãã³ã«æ»ãïŒ
socket s; string x; x = read_from_socket(s, 4); if (x == "ping") { write_to_socket(s, "pong"); } return;
ãã§ã«èª¬æããããã«ãèªã¿åããšçœç·ãå®è¡ãããåŸãå®è¡ã¹ã¬ããã¯ã¹ãªãŒãç¶æ
ã«ãªãããããã¯ãããŸãã éåžžãããããŒã¯ãããã¯ãããŸãããšèšããŸãã
socket s; string x; x = read_from_socket(s, 4); if (x == "ping") { write_to_socket(s, "pong"); } return;
ããã¯ãå®è¡ã®ãããŒããã€ãã³ããç¶ç¶ããããã«ã€ãã³ããå¿
èŠã«ãªããã€ã³ãã«å°éããããšãæå³ããŸãã ç¹ã«ããããã¯ãŒã¯ã¢ããªã±ãŒã·ã§ã³ã®å ŽåãããŒã¿ããããã¯ãŒã¯ãä»ããŠå°çããå¿
èŠããããŸããéã«ãããŒã¿ããããã¯ãŒã¯ã«æžã蟌ãããã®ãããã¡ã解æŸããŸããã ã€ãã³ãã¯ç°ãªãå ŽåããããŸãã æéã®åŽé¢ã«ã€ããŠè©±ããŠããå Žåã¯ãã¿ã€ããŒãèµ·åããããå¥ã®ããã»ã¹ãå®äºããã®ãåŸ
ã€ããšãã§ããŸãã ããã§ã®ã€ãã³ãã¯äžçš®ã®æœè±¡çãªãã®ã§ããããããã«ã€ããŠæåŸ
ã§ããããšãç解ããããšãéèŠã§ãã
åçŽãªã³ãŒããèšè¿°ãããšããã€ãã³ãã®æåŸ
å€ã®å¶åŸ¡ãããé«ãã¬ãã«ã«æé»çã«äžããŸãã ç§ãã¡ã®å Žåããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã 圌女ã¯ãããé«ãã¬ãã«ã®ãšã³ãã£ãã£ãšããŠã次ã«å®è¡ããã¿ã¹ã¯ãéžæãã責任ããããã€ãã³ãã®çºçã远跡ãã責任ããããŸãã
éçºè
ãšããŠèšè¿°ããã³ãŒãã¯ã1ã€ã®ã¿ã¹ã¯ã®äœæ¥ã«é¢ããŠåæã«æ§é åãããŸãã äŸã®ã³ãŒãã¹ããããã¯1ã€ã®æ¥ç¶ãåŠçããŸãã1ã€ã®æ¥ç¶ããpingãèªã¿åãã1ã€ã®æ¥ç¶ã«pongãæžã蟌ã¿ãŸãã
ã³ãŒãã¯æ確ã§ãã ãããèªãã§ããããäœãããã®ããã©ã®ããã«æ©èœããã®ããã©ã®åé¡ã解決ããã®ããã©ããªäžå€æ¡ä»¶ãæã£ãŠããã®ããªã©ãç解ã§ããŸãã åæã«ããã®ãããªã¢ãã«ã§ã¯ãã¿ã¹ã¯ãã©ã³ãã³ã°ã®ç®¡çãéåžžã«äžååã§ãã äžè¬ã«ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã«ã¯åªå
é äœã®æŠå¿µããããŸããããœãããªã¢ã«ã¿ã€ã ã·ã¹ãã ãèšè¿°ããå ŽåãLinuxã§å©çšå¯èœãªããŒã«ã§ã¯ååãªå¥å
šãªãªã¢ã«ã¿ã€ã ã·ã¹ãã ãäœæããã«ã¯äžååã§ããããšãããããŸãã
ããã«ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã¯è€éãªãã®ã§ãããã¢ããªã±ãŒã·ã§ã³ããã«ãŒãã«ãžã®ã³ã³ããã¹ãã®åãæ¿ãã«ã¯æ°ãã€ã¯ãç§ããããŸããããã¯ãããã€ãã®ç°¡åãªèšç®ã§ã1ç§ãããçŽ20ã10äžã®ã³ã³ããã¹ãã¹ã€ããã®æšå®å€ã«ãªããŸãã ã€ãŸããWebãµãŒããŒãèšè¿°ããå Žåããªã¯ãšã¹ãã®åŠçã¯ã·ã¹ãã ã®10åã®è²»çšãããããšä»®å®ããŠã1ç§ã§çŽ2äžä»¶ã®ãªã¯ãšã¹ããåŠçã§ããŸãã
4.1ã ãã³ããããã³ã°åŸ
æ©
ãããã¯ãŒã¯ãããå¹ççã«äœ¿çšããå¿
èŠãããå Žåã¯ãã€ã³ã¿ãŒãããã§ãã«ããæ¢ãå§ããselect / epollã䜿çšããŸãã ã€ã³ã¿ãŒãããã§ã¯ãæ°åã®æ¥ç¶ãåæã«æäŸããå Žåãepollãå¿
èŠã§ãããšæžãããŠããŸããããã¯åªããã¡ã«ããºã ãªã©ã§ããããã§ãã ããã¥ã¡ã³ããéããšã次ã®ãããªãã®ã衚瀺ãããŸãã
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout); void FD_CLR(int fd, fd_set* set); int FD_ISSET(int fd, fd_set* set); void FD_SET(int fd, fd_set* set); void FD_ZERO(fd_set* set); int epoll_ctl(int epfd, int op, int fd, struct epoll_event* event); int epoll_wait(int epfd, struct epoll_event* events, int maxevents, int timeout);
ã€ã³ã¿ãŒãã§ãŒã¹ã«äœ¿çšããèšè¿°åïŒselectã®å ŽåïŒãŸãã¯ééããã€ãã³ãã®å€ããå«ãŸããé¢æ°
ã¢ããªã±ãŒã·ã§ã³ã®å¢çãè¶ããŠãåŠçããå¿
èŠããããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®ã«ãŒãã«ïŒepollã®å ŽåïŒã
ãŸããselect / epollã§ã¯ãªããlibuvãªã©ã®ã©ã€ãã©ãªã«ã¢ã¯ã»ã¹ã§ããããšãè¿œå ãã䟡å€ããããŸããlibuvã«ã¯APIã«ã€ãã³ãã¯ãããŸããããå€ãã®ã³ãŒã«ããã¯ããããŸãã ã©ã€ãã©ãªã€ã³ã¿ãŒãã§ã€ã¹ã¯ãã芪æãªãåãããœã±ãããèªã¿åãããã®ã³ãŒã«ããã¯ãæäŸããŸããããã¯ãããŒã¿ã衚瀺ããããšãã«åŒã³åºããŸããã
int uv_timer_start(uv_timer_t* handle, uv_timer_cb cb, uint64_t timeout, uint64_t repeat); typedef void (*uv_timer_cb)(uv_timer_t* handle); int uv_read_start(uv_stream_t* stream, uv_alloc_cb alloc_cb, uv_read_cb read_cb); int uv_read_stop(uv_stream_t*); typedef void (*uv_read_cb)(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf); int uv_write(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); typedef void (*uv_write_cb)(uv_write_t* req, int status);
åç« ã®åæã³ãŒããšæ¯ã¹ãŠäœãå€ãã£ãã®ã§ããïŒ ã³ãŒãã¯éåæã«ãªããŸããã ããã¯ãã€ãã³ããç£èŠããæç¹ã決å®ããããã«ã¢ããªã±ãŒã·ã§ã³ã«ããžãã¯ãåãå
¥ããããšãæå³ããŸãã select / epollãžã®æ瀺çãªåŒã³åºãã¯ãçºçããã€ãã³ãã«é¢ããæ
å ±ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã«èŠæ±ãããã€ã³ãã§ãã ãŸãã次ã«å®è¡ããã¿ã¹ã¯ã®éžæãã¢ããªã±ãŒã·ã§ã³ã³ãŒãã«åãå
¥ããŸããã
ã€ã³ã¿ãŒãã§ã€ã¹ã®äŸããããã«ãã¿ã¹ã¯ãå°å
¥ããããã®åºæ¬çã«2ã€ã®ã¡ã«ããºã ãããããšãããããŸãã ããçš®ã®ããã«ãã¯
åŸ
ã£ãŠããã€ãã³ãã®å€ããåŒãåºããŠãäœããã®åœ¢ã§ãããã«åå¿ããŸãã ãã®ã¢ãããŒãã§ã¯ããªãŒããŒãããã1ã€ã§ç°¡åã«ååŽã§ããŸã
ã€ãã³ãã§ãããããçºçããã€ãã³ãã®ã»ããã«é¢ããéä¿¡ã§é«ãã¹ã«ãŒããããéæããŸãã éåžžãã«ãŒãã«ãšãããã¯ãŒã¯ã«ãŒãã®çžäºäœçšãããŠãŒã¶ãŒãšãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®çžäºäœçšãªã©ããã¹ãŠã®ãããã¯ãŒã¯èŠçŽ ã¯ãããŒãªã³ã°ã¡ã«ããºã ã«åºã¥ããŠæ§ç¯ãããŸãã
2çªç®ã®æ¹æ³ã¯ããããã·ã¥ãã¡ã«ããºã ã§ããç¹å®ã®å€éšãšã³ãã£ãã£ãæããã«å
¥ã£ãŠãããšãå®è¡ã®ãããŒãäžæãããä»ãå°çããã€ãã³ããåŠçããŠãã ããããšèšããŸãã ããã¯ãå€éšãšã³ãã£ãã£ãå®è¡ã¹ã¬ããã«æããã«äŸµå
¥ãããä»ããã®ã€ãã³ãã«åãçµãã§ããŸããããšèšããšããã³ãŒã«ããã¯ãUnixã·ã°ãã«ãããã»ããµã¬ãã«ã§ã®å²ã蟌ã¿ã䜿çšããã¢ãããŒãã§ãã ãã®ã¢ãããŒãã¯ãã€ãã³ãã®çºçãšããã«å¯Ÿããåå¿ã®éã®é
延ãæžããããã«ç»å ŽããŸããã
ç¹å®ã®ã¢ããªã±ãŒã·ã§ã³ã®åé¡ãèšè¿°ããŠè§£æ±ºããC ++éçºè
ããã€ãã³ãã¢ãã«ãã³ãŒãã«ãã©ãã°ããå¿
èŠãããã®ã¯ãªãã§ããïŒ å€ãã®ã¿ã¹ã¯ã®äœæ¥ãã³ãŒãã«ãã©ãã°ã¢ã³ãããããããŠç®¡çãããšãã«ãŒãã«ãžã®ç§»è¡ããªãããããŸããã®éã®å Žåãåäœæéãããã®äœæ¥ãå°ãéããªãããã䟿å©ãªã¢ã¯ã·ã§ã³ãå®è¡ã§ããŸãã
ããã¯ãç§ãã¡ãæžããã³ãŒãã«é¢ããŠäœã«ã€ãªãããŸããïŒ ããšãã°ãéåžžã«äžè¬çãªé«æ§èœHTTPãµãŒããŒã§ããnginxãåãäžããŸãã ã³ãŒããèªããšãéåæã¢ãã«ã«åºã¥ããŠæ§ç¯ãããŠããŸãã ã³ãŒãã¯èªã¿ã«ããã§ãã åäžã®HTTPãªã¯ãšã¹ããåŠçãããšãã«æ£ç¢ºã«äœãèµ·ããããèªåãããšãã³ãŒãããŒã¹ã®ããŸããŸãªè§åºŠã§ãããŸããŸãªãã¡ã€ã«ã«åºåãããã³ãŒãå
ã®ãã©ã°ã¡ã³ããããããããããšãããããŸãã åãã©ã°ã¡ã³ãã¯ãHTTPãªã¯ãšã¹ãå
šäœã®åŠçã®äžéšãšããŠå°éã®äœæ¥ãè¡ããŸãã äŸïŒ
static void ngx_http_request_handler(ngx_event_t *ev) { ⊠if (c->close) { ngx_http_terminate_request(r, 0); return; } if (ev->write) { r->write_event_handler(r); } else { r->read_event_handler(r); } ... } typedef void (*ngx_http_event_handler_pt)(ngx_http_request_t *r); struct ngx_http_request_s { ngx_http_event_handler_pt read_event_handler; }; r->read_event_handler = ngx_http_request_empty_handler; r->read_event_handler = ngx_http_block_reading; r->read_event_handler = ngx_http_test_reading; r->read_event_handler = ngx_http_discarded_request_body_handler; r->read_event_handler = ngx_http_read_client_request_body_handler; r->read_event_handler = ngx_http_upstream_rd_check_broken_connection; r->read_event_handler = ngx_http_upstream_read_request_handler;
èŠæ±æ§é ããããŸããããã¯ããœã±ãããèªã¿åããŸãã¯æžã蟌ã¿ã¢ã¯ã»ã¹ãéç¥ãããšãã«ã€ãã³ããã³ãã©ãŒã«è»¢éãããŸãã ããã«ããã®ãã³ãã©ãŒã¯ãèŠæ±åŠçã®ç¶æ
ã«å¿ããŠãããã°ã©ã ã®éçšã§åžžã«åãæ¿ãããŸãã ããããŒãèªã¿åããããªã¯ãšã¹ãã®æ¬æãèªã¿åãããã¢ããã¹ããªãŒã ã«ããŒã¿ãèŠæ±ããŸããäžè¬çã«ãããŸããŸãªç¶æ
ããããŸãã
ãã®ãããªã³ãŒãã¯ãæ¬è³ªçã«ãã€ãã³ãã«å¯Ÿããåå¿ã®èŠ³ç¹ããèšè¿°ãããŠãããããèªã¿ã«ããã§ãã ç§ãã¡ã¯ãã®ãããªç¶æ
ã«ãããæ¥ãåºæ¥äºã«ç¹å®ã®æ¹æ³ã§åå¿ããŸãã HTTPèŠæ±ãåŠçããããã»ã¹å
šäœã®å
šäœåã¯ãããŸããã
JavaScriptã§ãã䜿çšããããã1ã€ã®ãªãã·ã§ã³ã¯ãã³ãŒã«ããã¯ãã€ã³ã¿ãŒãã§ã€ã¹ã³ãŒã«ã«è»¢éãããšãã«ã³ãŒã«ããã¯ããŒã¹ã®ã³ãŒããæ§ç¯ããããšã§ããéåžžãã€ãã³ãã«ã¯ä»ã®ãã¹ããããã³ãŒã«ããã¯ãªã©ããããŸãã
int LibuvStreamWrap::ReadStart() { return uv_read_start(stream(), [](uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { static_cast<LibuvStreamWrap*>(handle->data)->OnUvAlloc(suggested_size, buf); }, [](uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { static_cast<LibuvStreamWrap*>(stream->data)->OnUvRead(nread, buf); }); } for (p=data; p != data + len; p++) { ch = *p; reexecute: switch (CURRENT_STATE()) { case s_start_req_or_res: case s_res_or_resp_H: case s_res_HT: case s_res_HTT: case s_res_HTTP: case s_res_http_major: case s_res_http_dot:
ããã§ãã³ãŒãã¯éåžžã«æçåãããŠããããªã¯ãšã¹ãã«å¯ŸããçŸåšã®ç¶æ
ãç解ããããšã¯ã§ããŸããã å€ãã®æ
å ±ãã¯ããŒãžã£ãä»ããŠéä¿¡ãããåäžã®ãªã¯ãšã¹ããåŠçããããžãã¯ãåæ§ç¯ããããã«ç²Ÿç¥çãªåªåãå¿
èŠã§ãã
ãããã£ãŠããã«ãã¿ã¹ã¯åŠçãã³ãŒãã«å°å
¥ãããšïŒäœæ¥ã¿ã¹ã¯ãéžæããŠå€éåããããžãã¯ïŒãå¹æçãªã³ãŒããååŸããã¿ã¹ã¯ã®åªå
é äœä»ããå¶åŸ¡ã§ããŸãããèªã¿ãããã®ç¹ã§å€ãã倱ãããŸãã ãã®ã³ãŒãã¯èªã¿ã«ãããä¿å®ãå°é£ã§ãã
ãªãã§ïŒ ããšãã°ããã¡ã€ã«ãèªã¿åã£ãŠãããã¯ãŒã¯çµç±ã§è»¢éãããªã©ãåçŽãªã±ãŒã¹ããããšããŸãã éããããã³ã°ããŒãžã§ã³ã§ã¯ããã®ã±ãŒã¹ã¯ãã®ãããªç·åœ¢ç¶æ
ãã·ã³ã«å¯Ÿå¿ããŸãã
- åæç¶æ
- ãã¡ã€ã«ã®èªã¿åããéå§ãã
- ãã¡ã€ã«ã·ã¹ãã ããã®å¿çãåŸ
ã£ãŠã
- ãã¡ã€ã«ããœã±ããã«æžã蟌ãã
- æçµç¶æ
ã
ããã§ãããŒã¿ããŒã¹ãããã®ãã¡ã€ã«ã«æ
å ±ãè¿œå ãããšããŸãã ç°¡åãªãªãã·ã§ã³ïŒ
- åæç¶æ
- ãã¡ã€ã«ãèªã
- ãã¡ã€ã«ãèªã
- ããŒã¿ããŒã¹ããèªã¿åããŸã
- ããŒã¿ããŒã¹ããèªã¿åã
- ãœã±ããã§ã®äœæ¥
- ãœã±ããã«æžã蟌ã¿ãŸããã
ç·åœ¢ã³ãŒãã®ããã«èŠããŸãããç¶æ
ã®æ°ãå¢ããŠããŸãã
次ã«ããã¡ã€ã«ãšããŒã¿ããŒã¹ããã®èªã¿åããšãã2ã€ã®ã¹ãããã䞊ååãããšãããšèãå§ããŸãã çµã¿åããè«ã®å¥è·¡ãå§ãŸããŸããããªãã¯åæç¶æ
ã«ãããããŒã¿ããŒã¹ãããã¡ã€ã«ãšããŒã¿ãèªã¿åãããšãèŠæ±ããŠããŸãã 次ã«ãããŒã¿ããŒã¹ããã®ããŒã¿ã¯ãããããã¡ã€ã«ããªãç¶æ
ããŸãã¯ãã®éã®ç¶æ
ã«ãªããŸãããã¡ã€ã«ããã¯ããŒã¿ããããããŒã¿ããŒã¹ããã¯ããŒã¿ããããŸããã 次ã«ã次ã®2ã€ã®ããããã®ç¶æ
ã«ãªãå¿
èŠããããŸãã ç¹°ãè¿ããŸããããããã¯2ã€ã®ç¶æ
ã§ãã 次ã«ãäž¡æ¹ã®æåãå«ãŸããŠããç¶æ
ã«ããå¿
èŠããããŸãã 次ã«ããããããœã±ãããªã©ã«æžã蟌ã¿ãŸãã
ã¢ããªã±ãŒã·ã§ã³ãè€éã«ãªãã»ã©ãç¶æ
ãå¢ããã»ã©ãé ã®äžã§çµã¿åãããå¿
èŠã®ããã³ãŒããã©ã°ã¡ã³ããå¢ããŸãã äžäŸ¿ã ãŸãã¯ãã³ãŒã«ããã¯ããŒãã«ãæžããŠããã®ã§ãèªãã®ãäžäŸ¿ã§ãã åå²ã·ã¹ãã ãäœæãããŠããå Žåãããæ¥ãããã蚱容ã§ããªããªãææãæ¥ãŸãã
5.å
ç©/çŽæ
åé¡ã解決ããã«ã¯ãç¶æ³ãç°¡åã«èª¿ã¹ãå¿
èŠããããŸãã
ããã°ã©ã ããããé»ãšèµ€ã®åããããŸãã å®è¡ã®æµãã¯é»äžžã§ãã ã¹ããªãŒã ãäœæ¥ãç¶è¡ã§ããªãå Žåãèµ€ã§äº€äºã«è¡šç€ºãããããšããããŸãã åé¡ã¯ãå®è¡ã®é»ãã¹ã¬ããã®ããã«ã次ã®é»ãåã«å
¥ãå¿
èŠãããããšã§ãã
åé¡ã¯ãããã°ã©ãã³ã°èšèªã§ã³ãŒããæžããšããä»äœããã¹ãããã³ã³ãã¥ãŒã¿ãŒã«èª¬æããããšã§ãã ã³ã³ãã¥ãŒã¿ãŒã¯æ¯èŒçåçŽãªãã®ã§ãããã°ã©ãã³ã°èšèªã§èšè¿°ãããåœä»€ãå¿
èŠãšããŸãã 圌女ã¯æ¬¡ã®ãµãŒã¯ã«ã®æ瀺ãåŸ
ã£ãŠããŸããç§ãã¡ã®ããã°ã©ãã³ã°èšèªã§ã¯ããå°æ¥ãäœããèµ·ãã£ãããäœããããŠãã ããããšèšãã ãã®ãéããããŸããã
ããã°ã©ãã³ã°èšèªã§ã¯ãé¢æ°ã®åŒã³åºããç®è¡æŒç®ãªã©ãç解ã§ããç¬éçãªã¢ã¯ã·ã§ã³ã§åäœããŸãã 次ã®ç¹å®ã®æ¬¡ã®ã¹ãããã«ã€ããŠèª¬æããŸãã åæã«ãã¢ããªã±ãŒã·ã§ã³ããžãã¯ãåŠçããã«ã¯ã次ã®ç©ççãªã¹ãããã§ã¯ãªãã次ã®è«ççãªã¹ããããèšè¿°ããå¿
èŠããããŸããããšãã°ãããŒã¿ããŒã¹ã®ããŒã¿ã衚瀺ãããå Žåã®å¯ŸåŠæ¹æ³ã§ãã
ãããã£ãŠããããã®ãã©ã°ã¡ã³ããçµåããããã®ã¡ã«ããºã ãå¿
èŠã§ãã åæã³ãŒããäœæããå Žåããã®è³ªåãå®å
šã«èŠãé ãããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ããããåŠçããã¹ã¬ããã®äžæãšåã¹ã±ãžã¥ãŒã«ãèš±å¯ãããšè¿°ã¹ãŸããã
ã¬ãã«1ã§ã¯ããã®Pandoraã®ããã¯ã¹ãéããã³ãŒãã«å€ãã®åãæ¿ããã±ãŒã¹ãæ¡ä»¶ããã©ã³ããç¶æ
ãè¿œå ããŸããã ã³ãŒããæ¯èŒçèªã¿ãããããã¬ãã«1ã®ãã¹ãŠã®å©ç¹ãä¿æããããã«ãäœããã®åŠ¥åãå¿
èŠã§ãã
幞ããªããšã«ã1988幎ã«åæ£ã·ã¹ãã ã«æºãã人ã
ã§ããBarbara LiskovãšLyub Shirirãåé¡ãèªèããèšèªã®å€æŽãå¿
èŠã«ãªããŸããã ããã°ã©ãã³ã°èšèªã«æ§é ãè¿œå ããŠãã€ãã³ãéã®æéçé¢ä¿ãè¡šçŸããå¿
èŠããããŸã-çŸåšã®ç¬éãšå°æ¥ã®äžç¢ºå®ãªç¬éã
ãããã¯çŽæãšåŒã°ããŸãã ã³ã³ã»ããã¯ã¯ãŒã«ã§ããã20幎ãã®éæ£ã«ã»ãããéããŠããŸããã â , Twitter, Ruby on Rails Scala, , , , future . Your Server as a Function. , .
Scala, , ++ ?
, Future. T c : , - .
template <class T> class Future <T>
, , , . , «», , . Future «», Promise â «». ; , JavaScript, Promise â , Java â Future.
, . , , boost::future ( std::future) â , .
5.1ã Future & Promise
template <class T> class Future { bool IsSet() const; const T& Get() const; T* TryGet() const; void Subscribe(std::function<void(const T&)> cb); template <class R> Future<R> Then( std::function<R(const T&)> f); template <class R> Future<R> Then( std::function<Future<R>(const T&)> f); }; template <class T> Future<T> MakeFuture(const T& value);
, , - , . , , , . , , â , , . Then, .
template <class T> class Promise { bool IsSet() const; void Set(const T& value); bool TrySet(const T& value); Future<T> ToFuture() const; }; template <class T> Promise<T> NewPromise();
. , . «, , , ».
5.2ã
? , . Then â , .
, â future --, - t â . , , , f, - r.
t f. , , r.
: t, , r . :
template <class T> template <class R> Future<R> Future<T>::Then(std::function<R(const T&)> f) { auto promise = NewPromise<R>(); this->Subscribe([promise] (const T& t) { auto r = f(t); promise.Set(r); }); return promise.ToFuture(); }
:
Promise
R
,Future<T>
t
,- ,
r = f(t)
, r
Promise
,Promise
.
f
, R
, Future<R>
, R
. :
template <class T> template <class R> Future<R> Future<T>::Then(std::function<Future<R>(const T&)> f) { auto promise = NewPromise<R>(); this->Subscribe([promise] (const T& t) { auto that = f(t); that.Subscribe([promise] (R r) { promise.Set(r); }); }); return promise.ToFuture(); }
, - t. f, r, . , , .
, Then :
Promise
,Subscribe
-,Promise
, Future
.
, . , , , .
, , , -. , , -, Subscribe. , , , - . , .
5.3ã äŸ
AsyncComputeValue, GPU, . Then, , (2v+1) 2 .
Future<int> value = AsyncComputeValue();
. , : (2v+1) 2 . , .
, , . .
2çªç®ã®äŸã : , ; ; .
Future<int> GetDbKey(); Future<string> LoadDbValue(int key); Future<void> SendToMars(string message); Future<void> ExploreOuterSpace() { return GetDbKey()
â ExploreOuterSpace. Then; â â , . ( ) . .
5.4ã Any-
: Future
, , . , , :
template <class T> Future<T> Any(Future<T> f1, Future<T> f2) { auto promise = NewPromise<T>(); f1.Subscribe([promise] (const T& t) { promise.TrySet(t); }); f2.Subscribe([promise] (const T& t) { promise.TrySet(t); }); return promise.ToFuture(); }
, Any-, Future : , . , , .
, , , , , . « DB1, DB2, â - ».
5.5ã All-
. , , , ( T1 T2), T1 T2 , , .
template <class T1, class T2> Future<std::tuple<T1, T2>> All(Future<T1> f1, Future<T2> f2) { auto promise = NewPromise<std::tuple<T1, T2>>(); auto result = std::make_shared< std::tuple<T1, T2> >(); auto counter = std::make_shared< std::atomic<int> >(2); f1.Subscribe([promise, result, counter] (const T1& t1) { std::get<0>(*result) = t1; if (--(*counter) == 0) { promise.Set(*result)); } }); f2.Subscribe([promise, result, counter] (const T2& t2) { } return promise.ToFuture(); }
nginx. , , . nginx « », « », « » . All- , . .
5.6.
Future Promises â legacy-, . callback- , , : Future, , callback- Future.
: , Future .
6.
, , . .
Future<Request> GetRequest(); Future<Payload> QueryBackend(Request req); Future<Response> HandlePayload(Payload pld); Future<void> Reply(Request req, Response rsp);
. Request, - . , . , , , . , - .
, , . ã©ããã â , request payload, â , .
, Java Netty. , , . , , .
, GetRequest, QueryBackend, HandlePayload Reply , Future.
, , Future T â WaitFor.
Future<Request> GetRequest(); Future<Payload> QueryBackend(Request req); Future<Response> HandlePayload(Payload pld); Future<void> Reply(Request req, Response rsp); template <class T> T WaitFor(Future<T> future);
:
Future<Request> GetRequest(); Future<Payload> QueryBackend(Request req); Future<Response> HandlePayload(Payload pld); Future<void> Reply(Request req, Response rsp); template <class T> T WaitFor(Future<T> future); auto req = WaitFor(GetRequest()); auto pld = WaitFor(QueryBackend(req)); auto rsp = WaitFor(HandlePayload(pld)); WaitFor(Reply(req, rsp));
: Future, . . , . .
. . - 0, , , mutex+cvar future. . , .
6.1ã ã³ã«ãŒãã³
, . , , , , - , . , - .
â «» , , . . . : boost::asio boost::fiber.
, . ã©ããã£ãŠããã®ïŒ
6.2ã WaitFor
, , boost::context, : , ; , . x86/64 , , .
, goto: , , , .
, - . Fiber â . +Future. , , Future, .
class Fiber { MachineContext context_; Future<void> future_; };
class Scheduler { void WaitFor(Future<void> future); void Loop(); MachineContext loop_context_; Fiber* current_fiber_; std::deque<Fiber*> run_queue_; };
Future , , , . : Loop, , , , , .
WaitFor?
thread_local Scheduler* ThisScheduler; template <class T> T WaitFor(Future<T> future) { ThisScheduler->WaitFor(future.As<void>()); return future.Get(); } void Scheduler::WaitFor(Future<void> future) { current_fiber_->future_ = future; SwitchContext(€t_fiber_->context_, &loop_context_); }
: , - , , Future void, . .
Future<void>
, , - .
WaitFor : : « Fiber Future», ( ) .
, :
ThisScheduler->WaitFor
return future.Get()
, .
? , Future, .
6.3ã
- , , , - , . SwitchContext , 2 â .
void Scheduler::Loop() { while (true) {
次ã«äœãèµ·ãããŸããïŒ , , , Future, Future, , , .
void Scheduler::Loop() { while (true) {
, . :
WaitFor â .
Switch- .
Future ( ), , . - Fiber.
WaitFor Future , - , Future . :
Future<Request> GetRequest(); Future<Payload> QueryBackend(Request req); Future<Response> HandlePayload(Payload pld); Future<void> Reply(Request req, Response rsp); template <class T> T WaitFor(Future<T> future); auto req = WaitFor( GetRequest()); auto pld = WaitFor( QueryBackend(req)); auto rsp = WaitFor( HandlePayload(pld)); WaitFor( Reply(req, rsp));
, , , . , , .
6.4. Coroutine TS
? â . Coroutine TS, , WaitFor CoroutineWait, CoroutineTS â - . , - . , Waiter Co, , .
7. ?
. , , , . , , , .
â . , . . , . , , , , .
- , , . , . , , .
, ? , .
. , , , , . . , , , , .
nginx, , , , , . , , , future promises.
, , , , , , , .
futures, promises actors. . , .
: , , , . , , , , . ? , .
åºåã®åã 19-20 C++ Russia 2019. , , Grimm Rainer «Concurrency and parallelism in C++17 and C++20/23» , C++ . , . , , - .