[ndc2015] c++11 고급 기능 - crow에 사용된 기법 중심으로

117
C++11 features used in Crow Crow 를 를를 를를를를 C++11 를 를 를를 를를를 @ipkn [email protected]

Upload: jaeseung-ha

Post on 06-Aug-2015

1.382 views

Category:

Technology


6 download

TRANSCRIPT

Page 1: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

C++11 featuresused in Crow

Crow 를 통해 살펴보는 C++11 의 새 기능

하재승@ipkn

[email protected]

Page 2: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Crow Framework 을 작성하기 위해 사용한 기법들을 소개 (TMP 중심 )

auto, lambda 등 일반적인 C++ 개발에서 접하기 쉬운 기법들에 대한 설명은 생략

목표

Page 3: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

목표

Page 4: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

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

Page 5: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Web server 개념

브라우저로 접속해서 요청을 보내면해당 요청에 맞는 응답을 보내줌

GET / HTTP/1.1Host: www.example.com

HTTP/1.1 200 OKContent-Length: 12...

Hello World!

Page 6: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

간단한 Crow 예제#include “crow_all.h”

int main() { crow::SimpleApp app; CROW_ROUTE(app, “/”) ([]{ return “Hello world!”; }); app.port(8080).run(); return 0;}

Page 7: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

… as Flask (from Quickstart)

from flask import Flaskapp = Flask(__name__)

@app.route('/')def hello_world(): return 'Hello World!'

if __name__ == '__main__': app.run()

Page 8: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

목차

RoutingCompile timeRun time

Middleware서버 구조

Page 9: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

소개될 C++11 기능

template metaprogrammingconstexprvariadic templateSFINAEdecltype, declvalstd::chrono, operator ””, enum class

Page 10: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

왜 굳이 C++ 로 ?https://github.com/ipkn/crow-benchmark

Page 11: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

C++?

빠른 속도멀티 패러다임 언어

절차형 + OOP + Generic (template)

Page 12: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

template

compile time code generation

vector<T> →vector<int>, vector<string>

T 는 컴파일 타임에 결정되어야 한다 .

Page 13: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Quick Review - auto, lambda, move

auto get_answer = []{ return 42; };auto x = get_answer();

SomeBigData f() { … }v.push_back(f());

Page 14: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Crow 클래스 구조

AppServer

ConnectionRouter

Rule (TaggedRule)Trie

Page 15: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Routing

Page 16: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Routing - CROW_ROUTE

어떤 요청에 어떤 응답을 줄지 지정

CROW_ROUTE(app, “/”)CROW_ROUTE(app, “/post/all”)CROW_ROUTE(app, “/post/<int>”)CROW_ROUTE(app,

“/near/<double>/<double>”)

Page 17: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

CROW_ROUTE 목표

쓰기 편하게실수하기 어렵게

잘못된 핸들러를 주면 에러나게빠르게실제 함수 호출 시 오버헤드를 최소화

Page 18: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

CROW_ROUTE 기능 (1)

여러 타입의 인자 지원

<int><uint><double><str><path>

Page 19: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

CROW_ROUTE 기능 (2)

컴파일 시간에 핸들러 타입 체크

CROW_ROUTE(app, “/post/<int>”)([](string a) … ([](int a, int b) … ([](int a) ...

Page 20: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

CROW_ROUTE 기능 (3)

여러 종류의 핸들러 지원

[](…)[](const request& req, …)[](const request& req, response& res, …)

* 어떻게 여러 종류를 지원하는지에 관해선 나중에 설명 예정

Page 21: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

실제 CROW_ROUTE 구현

#define CROW_ROUTE(app, url) app.route< crow::black_magic::get_parameter_tag(url) >(url)

Page 22: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

black_magic ???!!!

이름을 말할 수 없는 그분 (...)

다음 슬라이드부터 지옥의 내용이 펼쳐진다는 소문이 있습니다

(?)

Page 23: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

app.route<get_parameter_tag(url)>(url)

핸들러 형태 체크 → 컴파일 타임 → 템플릿 인자실행 중에 URL 체크 → 런타임 → 함수 인자

실제 CROW_ROUTE 구현 (2)

Page 24: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

app.route<get_parameter_tag(url)>(url)

핸들러 형태 체크 → 컴파일 타임 → 템플릿 인자실행 중에 URL 체크 → 런타임 → 함수 인자

실제 CROW_ROUTE 구현 (2)

Page 25: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

app.route<get_parameter_tag(url)>(url)

핸들러 형태 체크 → 컴파일 타임 → 템플릿 인자실행 중에 URL 체크 → 런타임 → 함수 인자

실제 CROW_ROUTE 구현 (2)

Page 26: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

app.route<get_parameter_tag(url)>(url)

스트링 값 (“abc” 등 ) 은 템플릿 인자로 사용할 수 없음

url 로 부터 인자에 대한 정보를 얻어템플릿 인자로 넣을 수 있는 값으로 변환

템플릿 인자부터 ..

Page 27: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

constexpr function

constexpr int fact(int n) { return (n <= 1)

? 1 : fact(n-1)*n;}

char arr[fact(5)];

Page 28: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

constexpr

컴파일 타임에 계산할 수도 있는 함수 또는 값

cin >> n; cout << fact(n); // 런타임

fact(5) == 120, 컴파일 타임에 계산 가능 → 배열의 크기 , 템플릿 인자 등으로 사용 가능

string literal 의 컴파일 타임 해쉬 계산

Page 29: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

get_parameter_tag

URL 을 받아 인자 정보를 가지는 숫자로 변환

인자가 없는 경우 0URL 인자는 5 종류 : <int>=1 <uint>=2 …6 진법으로 표현

( 자세한 구현은 생략 )

Page 30: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

get_parameter_tag

“/”“/post”“/post/<int>”“/near/<int>/<int>”“/put_score/<double>”“/wiki/<path>”

0011135

Page 31: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

숫자에서 다시 타입 리스트 복원

0 → <>1 → <int>11 → <int, int>13 → <double, int>4 → <string>5 → <string> * path 도 타입은 string

Page 32: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

black_magic::S

variadic template 으로 타입 리스트를 구현S<int, double, string> 이 가능 S<a,b>::push<c> === S<c, a, b>S<a>::push_back<b> === S<a, b>S<a,b,c>::rebind<Rule> === Rule<a,b,c>

Page 33: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

black_magic::S<T…> 구현 (1)

template <typename ... T> struct S {

template <typename U> using push = S<U, T...>;

S<a,b>::push<c> === S<c, a, b>

* using A = B; === typedef B A;

Page 34: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

black_magic::S<T…> 구현 (2)

template <typename ... T> struct S {

template <template <typename ...> class U>using rebind = U<T...>;

S<a,b,c>::rebind<Rule> == Rule<a,b,c>

Page 35: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

black_magic::arguments<uint64_t>

get_parameter_tag 값을 타입 리스트로

arguments<0>::type == S<>arguments<3>::type == S<double>arguments<11>::type == S<int, int>

Page 36: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

arguments 구현

template <uint64_t Tag> struct arguments { using subarg = typename arguments<Tag/6>::type;

using type = typename subargs::template push< typename single_tag_to_type<Tag%6>::type >;};

Page 37: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

실제로 일어나는 일

argument<31>subarg = arg<3>type = subarg::push<int>

Page 38: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

실제로 일어나는 일

argument<31>subarg = S<double>type = S<int, double>

arg<3>subarg = arg<0> = S<>type = S<>:push<double> =

S<double>

Page 39: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

partial template specialization

template <int N>struct single_tag_to_type {};

template <>struct single_tag_to_type<1> {

using type = int64_t;};// C++11 은 아니지만 ..

Page 40: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

arguments 구현

template <> struct arguments<0> { using type = S<>;};

Page 41: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

URL 이 라우팅 규칙이 되기까지

get_parameter_tag(“/<int>/<int>”)→ arguments<11>→ S<int, int>→ TaggedRule<int, int>

Router vector<unique_ptr<BaseRule>> rules_;

Page 42: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Q&A for Routing 1

get_parameter_tag(“/<int>/<int>”)→ arguments<11>→ S<int, int>→ TaggedRule<int, int>

Page 43: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

실제 핸들러 호출하기

Routing 2

Page 44: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

남은 문제

/v<uint>/<string>/<path>“/v2/wiki/example/document”

TaggedRule<uint, string, string>

handler[](uint32_t ver, string func, string path)

Page 45: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Rule, TaggedRule

최종적으로 호출될 핸들러를 가지고 있음app.route 의 리턴 값

void handle( const request& req, response& res, const routing_params& params)

Page 46: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Trie based routing

여러 rule 들의 URL 을 모아서요청이 들어왔을 때 어느 Rule 에서 처리할 지 판단

트리 구조로 성능 향상

Page 47: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Trie example

GET statuses/home_timelineGET statuses/retweets/:idGET statuses/retweets_of_mePOST statuses/retweet/:id

(from Twitter REST API)

Page 48: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

statuses/

retweethome_timelin

e

s/

_of_meuint

uint

/

GET statuses/home_timelineGET statuses/retweets/:idGET statuses/retweets_of_mePOST statuses/retweet/:id

Page 49: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Trie

add( string url, rule )find( string url )

-> rule, routing_params

http://en.wikipedia.org/wiki/Trierouting.h

Page 50: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

routing_params

vector<int> int_params;vector<uint> uint_params;vector<double> double_params;vector<string> string_params;

Page 51: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Trie example (1)

/near/<double>/<double>“/near/37.1/10.1”

routing_params.double_params == {37.1, 10.1}

Page 52: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Trie example (2)

/v<uint>/<string>/<path>“/v2/wiki/example/document”

routing_params.uint_params == {2}.string_params ==

{“wiki”, “example/document”}

Page 53: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

핸들러 호출하기

/v<uint>/<string>/<path>[](unsigned int, string, string)

handler(rp.uint_params[0], rp.string_params[0], rp.string_params[1])

compile time

Page 54: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

호출부 구현template <typename CP,

int NInt, int NUint, int NDouble, int NString, typename S1, typename S2>struct call;

S1 - URL 로 부터 정의된 핸들러 인자 타입의 리스트S2 - 호출을 위한 타입 + 인덱스 정보의 리스트 N?? - 인자 처리를 위한 인덱스 값들 , CP - 호출

파라미터

Page 55: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

TaggedRule<Args…>::handle

void handle(req, res, routing_params) {call<CallParams, 0, 0, 0, 0, S<Args…>, S<>>(

call_params);}

call_paramsreq + res + routing_params + handler

Page 56: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

call 호출 과정 - /v<uint>/<string>/<path>

0 0 [uint, str, str] []1 0 [str, str] [(uint, 0)]1 1 [str] [(uint, 0) (str, 0)]1 2 [] [(uint, 0) (str, 0) (str, 1)]

call 을 재귀호출

NUint NStr S1 S2

Page 57: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

call 호출 과정 - /v<uint>/<string>/<path>

0 0 [uint, str, str] []NUint NStr S1 S2

Page 58: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

call 호출 과정 - /v<uint>/<string>/<path>

0 0 [uint, str, str] []

→ 1 0 [str, str] [<uint, 0>]

NUint NStr S1 S2

Page 59: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

struct call<CP, NInt, NUint, NDouble, NString, S< int64_t, Args1...>, S<Args2...>> { void operator()(CP cp) { using pushed = typename S<Args2...>:: template push_back<call_pair<int64_t, NInt>>; call<CP, NInt+1, NUint, NDouble, NString, S<Args1...>, pushed>()(cp); }};

Page 60: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

call 호출 과정 - /v<uint>/<string>/<path>

0 0 [uint, str, str] []1 0 [str, str] [<uint, 0>]

→ 1 1 [str] [<uint, 0> <str, 0>]

NUint NStr S1 S2

Page 61: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

call 호출 과정 - /v<uint>/<string>/<path>

0 0 [uint, str, str] []1 0 [str, str] [<uint, 0>]1 1 [str] [<uint, 0> <str, 0>]

→ 1 2 [] [<uint, 0>, <str, 0>, <str, 1>]

NUint NStr S1 S2

Page 62: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

struct call<CP, NInt, NUint, NDouble, NString,S<>, S<Args2...>> { void operator()(CP cp) { // 일부 생략 cp.res = cp.handler( cp.routing_params.template get <typename Args2::type>(Args2::pos) ... ); cparams.res.end(); return;

Page 63: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

T routing_params::get<T>(index)

template<> string routing_params::get<string>(index) const {

return string_params[index]; }

Page 64: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

핸들러 호출하기handler(rp.uint_params[0], rp.string_params[0], rp.string_params[1]);

handler(rp.get<uint>(0), rp.get<string>(0), rp.get<string>(1));

handler( rp.get<Args2::type>(Args2::pos)... )

Page 65: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

핸들러 호출하기Args… = <uint, 0>, <str, 0>, <str, 1>

handler( rp.get<Args::type>(Args::pos)... )

<uint,0> 을 대입한 경우를 보면 = rp.get<uint>(0)

... 을 통해서 반복되므로rp.get<uint>(0), rp.get<str>(1), rp.get<str>(2)

Page 66: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

struct call<CP, NInt, NUint, NDouble, NString,S<>, S<Args2...>> { void operator()(CP cp) { // 일부 생략 cp.res = cp.handler( cp.routing_params.template get <typename Args2::type>(Args2::pos) ... ); cparams.res.end(); return;

Page 67: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Variadic template from example

void print(A a, B b, C c, …) 모든 인자를 출력해주는 함수

print() print(1) - 1print(2, “hello”, 40) - 2hello40

Page 68: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

print 구현void print() {}template <typename A, typename ... Args>void print(A a, Args... args){ cout << a; print(args...);}

Page 69: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

print(2, “hello”, 40) 실행

A = intArgs… = const char*, intargs… = “hello”, 40

cout << 2;print(“hello”, 40);

Page 70: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

print 실행

print<int, const char*, int>(2, “hello”, 40) - 2print<const char*, int>(“hello”, 40) - helloprint<int>(40) - 40print()

2hello40

Page 71: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Variadic template 대입의 예

args… = 1, 5, 10

(args+1)… = 1+1, 5+1, 10+1func(args)… = func(1), func(5), func(10)func(args…) = func(1, 5, 10)

Page 72: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Q&A for Routing 2

TrieRouting parameterVariadic template

Page 73: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Middleware

Page 74: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Middleware?

C 요청 -> S 응답 -> C 받음

요청 --[MW]--> 응답 --[MW]--> 받음

before_handle(req, res)after_handle(req, res)

Page 75: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Example Middleware

Static page serving (cache control)Cookie parsing, Session supportJSON parsingProfiling, Logging

Page 76: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Middleware of express.js (Node.js)

app.use(function (req, res, next) { req.cookies = parse_cookies(req); next();});

// req에 임의로 변수추가 가능

Page 77: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Middleware 구현의 제약들

근데 우린 C++ 이잖아… 변수는 다 선언되어야 unordered_map<string, any> ???

+ express 의 문제점 : Dependency 세션은 사용하는데 쿠키파서가 없는 경우

Page 78: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

이 문제를 어떻게 해결하면 좋을까 ?

각 MW 별로 저장해야할 값들이 존재어떤 MW 는 다른 MW 의 값을 참조해야 한다

(C++ 이니까 )필요한 MW 가 빠진 경우 컴파일 에러가 발생해야함

Page 79: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

struct MW::contextMW 가 필요한 값을 저장하는 struct내용에 특별한 제한이 없음

App<A, B, C> app;A, B, C 세 MW 를 사용하는 app

SimpleApp == App<>

Crow 에서의 해결 방식

Page 80: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

ctx_A : public A::contextctx_AB : public ctx_A, public B::contextctx_ABC : public ctx_AB, public C::contextcontext : public ctx_ABC

실제로 ctx_AB === partial_context<A, B>

context 체인 상속 - App<A, B, C>

Page 81: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

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)

Page 82: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

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)

Page 83: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Dependency 해결 (1)

Session MW 는 Cookie MW 에 의존한다면

app<Cookie, Session> - OKapp<Session> - errorapp<Session, Cookie> - error

의존 : all_ctx.get<Cookie> 를 사용한다 .

Page 84: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Dependency 해결 (2)

App<A, B, C> app;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)

Page 85: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Dependency 해결 (3)

ctx_A :: get<A> - OKctx_A :: get<B> - error

ctx_AB :: get<A> - OKctx_AB :: get<B> - OK

Page 86: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

ctx_AB::get

template <typename T>typename T::context& get() { return static_cast<typename T::context&>(*this);}

상속한 MW 의 context 타입으로만 캐스팅 가능

Page 87: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

다른 MW 과 연관이 없는 MW 라면 ?

template <typename AllContext>before_handle(req, res,

context& ctx, AllContext& all_ctx)

대부분의 경우before_handle(req, res, context&

ctx)

Page 88: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

SFINAE

Substitution failure is not an error.

템플릿 인자를 대입하는 과정에서 발생하는 에러는 에러로 간주하지 않는다 . ( 모두 실패하는 경우에는 에러 )

또는 이를 이용한 프로그래밍 기법을 지칭함

Page 89: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

SFINAE 예제template <typename T>true_type has_iterator_checker(typename T::iterator *); template <typename T>false_type has_iterator_checker(...);

decltype(has_iterator_checker<int>()) === false_typedecltype(has_iterator_checker<string>()) === true_type

Page 90: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
Page 91: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

template <typename MW>struct check_before_handle_arity_3{ template <typename T, void(T::*)(request&,response&,MW::context&)

= &T::before_handle

> struct get {};};

Page 92: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

template <typename T>struct is_before_handle_arity_3_impl{ template <typename C> static std::true_type f(check_before_handle_arity_3<T>::get<C>*);

template <typename C> static std::false_type f(...);

public: static const bool value = decltype(f<T>(nullptr))::value;};

Page 93: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

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

Page 94: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

CookieParser - Example Middleware

CookieParser::contextuo_map<string, string> jar,

cookies_to_add;get_cookie(key)set_cookie(key, value)

before - 파싱 + jar 에 저장after - Set-Cookie 헤더 추가

Page 95: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Q&A for Middleware

App<A, B, C> app;

context inheritance chainMiddleware call chain

CookieParser

SFINAE

Page 96: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

Crow 서버 구조

Page 97: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

고려해야 할 점

멀티 쓰레드 작업 배분Connection 객체의 생성 , 소멸 관리HTTP 타임 아웃 (Keep-Alive)

Page 98: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

초기 버전

boost::asio + joyent/http-parser

asio::io_service 하나concurrency 개수 만큼 io_service.run()shared_ptr<Connection> 으로 수명 관리asio::deadline_timer 로 타임아웃 처리

Page 99: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

초당 처리 횟수가 100,000 이상 ..

shared_ptr 의 atomic 연산이 성능 부하deadline_timer 내부 자료구조 업데이트 부하

Page 100: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

여러 개의 싱글 쓰레드 서버의 결합

N 개의 작업용 쓰레드 (asio::io_service ✕ N)

요청이 들어올 때마다 어느 쓰레드가 처리할지 RR 로 분배

해당 요청에 대한 모든 처리는담당한 쓰레드 안에서만 이루어짐

Page 101: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

deadline_timer 성능 저하 문제

각 쓰레드 별로 thread_local 한 타이머를 구현관련 코드 : dumb_timer_queue.h

Page 102: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

shared_ptr 제거

Connection 객체를 하나의 쓰레드가 담당atomic 연산 불필요

변경 후 성능 4 배 향상쓰레드간 통신 전혀 없음

* shared_ptr 을 쓰지말란 얘기는 아닙니다 .

Page 103: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

그 외 사용된

C++11 기능들 소개

Page 104: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

std::chrono

std::chrono::system_clocksteady_clockhigh_resolution_clock

( 거의 ) 같은 인터페이스 제공

Page 105: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

std::chrono 사용법

auto t1 = clock::now();do_something();auto t2 = clock::now();

if (t2 - t1 > seconds(10)) …duration_cast<seconds>(t2 - t1).count()

Page 106: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

system_clockto_time_t, from_time_t 제공

steady_clock무조건 증가함이 보장됨

high_resolution_clock제일 높은 해상도를 제공

( 가능한 짧은 시간 간격 )

Page 107: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

operator “”

C++11std::chrono::seconds(10)std::chrono::minutes(20)std::string(“hello”)C++1410s20min“hello”s

Page 108: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

POST request

CROW_ROUTE(app, “/update_score”)

.methods(“POST”_method)

([](const crow::request& req){ auto json = crow::json::load(req.body); ...});

Page 109: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

operator “” _method

constexpr crow::HTTPMethod operator "" _method(const char* str, size_t len)

{return

crow::black_magic::is_equ_p(str, "GET", 3) ? crow::HTTPMethod::GET :

…};

Page 110: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

enum class

enum class HTTPMethod{

GET,POST,

...};

int m = HTTPMethod::GET; // error!

Page 111: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

decltype, declval<T>

decltype(X)X 의 선언형

declval<T>()컴파일 타임에만 사용할 수 있는 T 의 객체형

Page 112: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

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

Page 113: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

< 끝 >( 내용 발표는 )

Page 114: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

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;};

Page 115: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

C++14 - minor patch to 11

그외 …01010b, 1’234’5678’9 == 123456789make_unique...

Page 116: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

C++14 - minor patch 는 훼이크

auto p = [](auto& s, auto...x){[](...){}((s<<x,1)...);};p(cout, 42, "hello?");

위 코드의 실행 결과를 설명하시오 . (3 점 )

Page 117: [NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로

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; };