4. Crow
C++ Framework for writing Web server
http://github.com/ipkn/crow
GitHub Star 1251개
Hacker News vote 194
https://news.ycombinator.com/item?id=8002604
5. Web server 개념
브라우저로 접속해서 요청을 보내면
해당 요청에 맞는 응답을 보내줌
GET / HTTP/1.1
Host: www.example.com
HTTP/1.1 200 OK
Content-Length: 12
...
Hello World!
16. Routing - CROW_ROUTE
어떤 요청에 어떤 응답을 줄지 지정
CROW_ROUTE(app, “/”)
CROW_ROUTE(app, “/post/all”)
CROW_ROUTE(app, “/post/<int>”)
CROW_ROUTE(app,
“/near/<double>/<double>”)
28. constexpr
컴파일 타임에 계산할 수도 있는 함수 또는 값
cin >> n; cout << fact(n); // 런타임
fact(5) == 120, 컴파일 타임에 계산 가능
→ 배열의 크기, 템플릿 인자 등으로 사용 가능
string literal의 컴파일 타임 해쉬 계산
29. get_parameter_tag
URL 을 받아 인자 정보를 가지는 숫자로 변환
인자가 없는 경우 0
URL 인자는 5종류: <int>=1 <uint>=2 …
6진법으로 표현
(자세한 구현은 생략)
54. 호출부 구현
template <typename CP,
int NInt, int NUint, int NDouble, int NString,
typename S1, typename S2>
struct call;
S1 - URL로 부터 정의된 핸들러 인자 타입의 리스트
S2 - 호출을 위한 타입+인덱스 정보의 리스트
N?? - 인자 처리를 위한 인덱스 값들, CP - 호출 파라미터
76. Middleware of express.js (Node.js)
app.use(function (req, res, next) {
req.cookies = parse_cookies(req);
next();
});
// req에 임의로 변수추가 가능
77. Middleware 구현의 제약들
근데 우린 C++이잖아… 변수는 다 선언되어야
unordered_map<string, any> ???
+ express의 문제점: Dependency
세션은 사용하는데 쿠키파서가 없는 경우
78. 이 문제를 어떻게 해결하면 좋을까?
각 MW별로 저장해야할 값들이 존재
어떤 MW는 다른 MW의 값을 참조해야 한다
(C++이니까)
필요한 MW가 빠진 경우 컴파일 에러가 발생해
야함
79. struct MW::context
MW가 필요한 값을 저장하는 struct
내용에 특별한 제한이 없음
App<A, B, C> app;
A, B, C 세 MW를 사용하는 app
SimpleApp == App<>
Crow에서의 해결 방식
80. ctx_A : public A::context
ctx_AB : public ctx_A, public B::context
ctx_ABC : public ctx_AB, public C::context
context : public ctx_ABC
실제로 ctx_AB === partial_context<A, B>
context 체인 상속 - App<A, B, C>
81. Crow에서의 해결 방식
template <typename AllContext>
before_handle(req, res, context& ctx,
AllContext& all_ctx)
from MW - all_ctx.get<A>()
from handler - app.get_context<A>(req)
82. Crow에서의 해결 방식 - 전체 호출 과정
A::before_handle(req, res, ctx_A)
B::before_handle(req, res, ctx_AB)
C::before_handle(req, res, ctx_ABC)
app.handle(req, res)
C::after_handle(req, res, ctx_ABC)
B::after_handle(req, res, ctx_AB)
A::after_handle(req, res, ctx_A)
87. 다른 MW과 연관이 없는 MW라면?
template <typename AllContext>
before_handle(req, res,
context& ctx, AllContext& all_ctx)
대부분의 경우
before_handle(req, res, context& ctx)
88. SFINAE
Substitution failure is not an error.
템플릿 인자를 대입하는 과정에서 발생하는 에
러는 에러로 간주하지 않는다. (모두 실패하는
경우에는 에러)
또는 이를 이용한 프로그래밍 기법을 지칭함
93. std::enable_if
SFINAE를 이용하기 편하게 만들어둔 도구
조건부로 구현을 선택
template <typename T>
enable_if<is_integral<T>::value> func(T x) …
handler 형태를 고를 때 사용 (생략)
http://en.cppreference.com/w/cpp/types/enable_if
94. CookieParser - Example Middleware
CookieParser::context
uo_map<string, string> jar,
cookies_to_add;
get_cookie(key)
set_cookie(key, value)
before - 파싱 + jar에 저장
after - Set-Cookie 헤더 추가
97. 고려해야 할 점
멀티 쓰레드 작업 배분
Connection 객체의 생성, 소멸 관리
HTTP 타임 아웃 (Keep-Alive)
98. 초기 버전
boost::asio + joyent/http-parser
asio::io_service 하나
concurrency 개수 만큼 io_service.run()
shared_ptr<Connection> 으로 수명 관리
asio::deadline_timer로 타임아웃 처리
99. 초당 처리 횟수가 100,000 이상..
shared_ptr의 atomic 연산이 성능 부하
deadline_timer 내부 자료구조 업데이트 부하
100. 여러 개의 싱글 쓰레드 서버의 결합
N 개의 작업용 쓰레드 (asio::io_service ✕ N)
요청이 들어올 때마다
어느 쓰레드가 처리할지 RR로 분배
해당 요청에 대한 모든 처리는
담당한 쓰레드 안에서만 이루어짐
101. deadline_timer 성능 저하 문제
각 쓰레드 별로 thread_local한 타이머를 구현
관련 코드: dumb_timer_queue.h
102. shared_ptr 제거
Connection 객체를 하나의 쓰레드가 담당
atomic 연산 불필요
변경 후 성능 4배 향상
쓰레드간 통신 전혀 없음
* shared_ptr을 쓰지말란 얘기는 아닙니다.
112. template <typename A, typename B>
auto add(A a, B b) -> decltype(a+b)
{ return a+b; }
template <typename A, typename B>
decltype(declval<A>() + declval<B>())
add(A a, B b)
C++14: return type deduction
114. C++14 - minor patch to 11
Function return type deduction
Relaxed constexpr
Variable template
Lambda capture expression
Generic lambda
auto lambda = [a = 3](auto x, auto y)
{return a + x + y;};
115. C++14 - minor patch to 11
그외 …
01010b, 1’234’5678’9 == 123456789
make_unique
...
116. C++14 - minor patch는 훼이크
auto p = [](auto& s, auto...x){
[](...){}((s<<x,1)...);
};
p(cout, 42, "hello?");
위 코드의 실행 결과를 설명하시오. (3점)
117. VS2015 RC C++11 지원
http://blogs.msdn.com/b/vcblog/archive/2015/04/29/c-
11-14-17-features-in-vs-2015-rc.aspx
ref-qualifiers(멤버함수 뒤 &&)
Inheriting constructors
u8"한글", char16_t , char32_t
struct B1 {
B1( int );
};
struct D1 : B1 {
using B1::B1;
};