src: Rewrite defer function template

This commit is contained in:
Tatsuhiro Tsujikawa 2015-02-06 23:27:15 +09:00
parent 6ff67ae869
commit b4b2ddad3b
10 changed files with 35 additions and 33 deletions

View File

@ -525,7 +525,7 @@ int http2_handler::start() {
return -1; return -1;
} }
auto cb_del = util::defer(callbacks, nghttp2_session_callbacks_del); auto cb_del = defer(nghttp2_session_callbacks_del, callbacks);
nghttp2_session_callbacks_set_on_begin_headers_callback( nghttp2_session_callbacks_set_on_begin_headers_callback(
callbacks, on_begin_headers_callback); callbacks, on_begin_headers_callback);
@ -548,7 +548,7 @@ int http2_handler::start() {
return -1; return -1;
} }
auto opt_del = util::defer(option, nghttp2_option_del); auto opt_del = defer(nghttp2_option_del, option);
nghttp2_option_set_recv_client_preface(option, 1); nghttp2_option_set_recv_client_preface(option, 1);

View File

@ -135,10 +135,10 @@ void http2_impl::backlog(int backlog) { backlog_ = backlog; }
} // namespace server } // namespace server
template <typename T, typename F> template <typename F, typename... T>
std::shared_ptr<util::Defer<T, F>> defer_shared(T &&t, F f) { std::shared_ptr<Defer<F, T...>> defer_shared(F &&f, T &&... t) {
return std::make_shared<util::Defer<T, F>>(std::forward<T>(t), return std::make_shared<Defer<F, T...>>(std::forward<F>(f),
std::forward<F>(f)); std::forward<T>(t)...);
} }
read_cb file_reader(const std::string &path) { read_cb file_reader(const std::string &path) {
@ -151,7 +151,7 @@ read_cb file_reader(const std::string &path) {
} }
read_cb file_reader_from_fd(int fd) { read_cb file_reader_from_fd(int fd) {
auto d = defer_shared(static_cast<int>(fd), close); auto d = defer_shared(close, fd);
return [fd, d](uint8_t *buf, size_t len) -> read_cb::result_type { return [fd, d](uint8_t *buf, size_t len) -> read_cb::result_type {
int rv; int rv;

View File

@ -280,7 +280,7 @@ void print_server_tmp_key(SSL *ssl) {
return; return;
} }
auto key_del = util::defer(key, EVP_PKEY_free); auto key_del = defer(EVP_PKEY_free, key);
std::cout << "Server Temp Key: "; std::cout << "Server Temp Key: ";
@ -293,7 +293,7 @@ void print_server_tmp_key(SSL *ssl) {
break; break;
case EVP_PKEY_EC: { case EVP_PKEY_EC: {
auto ec = EVP_PKEY_get1_EC_KEY(key); auto ec = EVP_PKEY_get1_EC_KEY(key);
auto ec_del = util::defer(ec, EC_KEY_free); auto ec_del = defer(EC_KEY_free, ec);
auto nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); auto nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
auto cname = EC_curve_nid2nist(nid); auto cname = EC_curve_nid2nist(nid);
if (!cname) { if (!cname) {

View File

@ -28,6 +28,7 @@
#include "h2load.h" #include "h2load.h"
#include "util.h" #include "util.h"
#include "template.h"
using namespace nghttp2; using namespace nghttp2;
@ -126,8 +127,7 @@ void Http2Session::on_connect() {
nghttp2_session_callbacks_new(&callbacks); nghttp2_session_callbacks_new(&callbacks);
auto callbacks_deleter = auto callbacks_deleter = defer(nghttp2_session_callbacks_del, callbacks);
util::defer(callbacks, nghttp2_session_callbacks_del);
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks, nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
on_frame_recv_callback); on_frame_recv_callback);

View File

@ -2136,7 +2136,7 @@ int run(char **uris, int n) {
nghttp2_session_callbacks *callbacks; nghttp2_session_callbacks *callbacks;
nghttp2_session_callbacks_new(&callbacks); nghttp2_session_callbacks_new(&callbacks);
auto cbsdel = util::defer(callbacks, nghttp2_session_callbacks_del); auto cbsdel = defer(nghttp2_session_callbacks_del, callbacks);
nghttp2_session_callbacks_set_on_stream_close_callback( nghttp2_session_callbacks_set_on_stream_close_callback(
callbacks, on_stream_close_callback); callbacks, on_stream_close_callback);

View File

@ -1174,8 +1174,7 @@ int Http2Session::on_connect() {
return -1; return -1;
} }
auto callbacks_deleter = auto callbacks_deleter = defer(nghttp2_session_callbacks_del, callbacks);
util::defer(callbacks, nghttp2_session_callbacks_del);
nghttp2_session_callbacks_set_on_stream_close_callback( nghttp2_session_callbacks_set_on_stream_close_callback(
callbacks, on_stream_close_callback); callbacks, on_stream_close_callback);

View File

@ -666,8 +666,7 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
assert(rv == 0); assert(rv == 0);
auto callbacks_deleter = auto callbacks_deleter = defer(nghttp2_session_callbacks_del, callbacks);
util::defer(callbacks, nghttp2_session_callbacks_del);
nghttp2_session_callbacks_set_on_stream_close_callback( nghttp2_session_callbacks_set_on_stream_close_callback(
callbacks, on_stream_close_callback); callbacks, on_stream_close_callback);

View File

@ -639,7 +639,7 @@ void get_altnames(X509 *cert, std::vector<std::string> &dns_names,
GENERAL_NAMES *altnames = static_cast<GENERAL_NAMES *>( GENERAL_NAMES *altnames = static_cast<GENERAL_NAMES *>(
X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr)); X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr));
if (altnames) { if (altnames) {
auto altnames_deleter = util::defer(altnames, GENERAL_NAMES_free); auto altnames_deleter = defer(GENERAL_NAMES_free, altnames);
size_t n = sk_GENERAL_NAME_num(altnames); size_t n = sk_GENERAL_NAME_num(altnames);
for (size_t i = 0; i < n; ++i) { for (size_t i = 0; i < n; ++i) {
const GENERAL_NAME *altname = sk_GENERAL_NAME_value(altnames, i); const GENERAL_NAME *altname = sk_GENERAL_NAME_value(altnames, i);
@ -699,7 +699,7 @@ int check_cert(SSL *ssl) {
LOG(ERROR) << "No certificate found"; LOG(ERROR) << "No certificate found";
return -1; return -1;
} }
auto cert_deleter = util::defer(cert, X509_free); auto cert_deleter = defer(X509_free, cert);
long verify_res = SSL_get_verify_result(ssl); long verify_res = SSL_get_verify_result(ssl);
if (verify_res != X509_V_OK) { if (verify_res != X509_V_OK) {
LOG(ERROR) << "Certificate verification failed: " LOG(ERROR) << "Certificate verification failed: "
@ -877,7 +877,7 @@ int cert_lookup_tree_add_cert_from_file(CertLookupTree *lt, SSL_CTX *ssl_ctx,
LOG(ERROR) << "BIO_new failed"; LOG(ERROR) << "BIO_new failed";
return -1; return -1;
} }
auto bio_deleter = util::defer(bio, BIO_vfree); auto bio_deleter = defer(BIO_vfree, bio);
if (!BIO_read_filename(bio, certfile)) { if (!BIO_read_filename(bio, certfile)) {
LOG(ERROR) << "Could not read certificate file '" << certfile << "'"; LOG(ERROR) << "Could not read certificate file '" << certfile << "'";
return -1; return -1;
@ -888,7 +888,7 @@ int cert_lookup_tree_add_cert_from_file(CertLookupTree *lt, SSL_CTX *ssl_ctx,
<< "'"; << "'";
return -1; return -1;
} }
auto cert_deleter = util::defer(cert, X509_free); auto cert_deleter = defer(X509_free, cert);
std::string common_name; std::string common_name;
std::vector<std::string> dns_names; std::vector<std::string> dns_names;
std::vector<std::string> ip_addrs; std::vector<std::string> ip_addrs;

View File

@ -54,6 +54,23 @@ template <typename T, size_t N> constexpr size_t array_size(T (&)[N]) {
return N; return N;
} }
// inspired by <http://blog.korfuri.fr/post/go-defer-in-cpp/>, but our
// template can take functions returning other than void.
template <typename F, typename... T> struct Defer {
Defer(F &&f, T &&... t)
: f(std::bind(std::forward<F>(f), std::forward<T>(t)...)) {}
Defer(Defer &&o) : f(std::move(o.f)) {}
~Defer() { f(); }
using ResultType = typename std::result_of<
typename std::decay<F>::type(typename std::decay<T>::type...)>::type;
std::function<ResultType()> f;
};
template <typename F, typename... T> Defer<F, T...> defer(F &&f, T &&... t) {
return Defer<F, T...>(std::forward<F>(f), std::forward<T>(t)...);
}
} // namespace nghttp2 } // namespace nghttp2
#endif // TEMPLATE_H #endif // TEMPLATE_H

View File

@ -54,19 +54,6 @@ namespace nghttp2 {
namespace util { namespace util {
template <typename T, typename F> struct Defer {
Defer(T t, F f) : t(t), f(std::move(f)) {}
~Defer() { f(t); }
T t;
F f;
};
template <typename T, typename F> Defer<T, F> defer(T &&t, F f) {
return Defer<T, F>(std::forward<T>(t), std::forward<F>(f));
}
extern const char DEFAULT_STRIP_CHARSET[]; extern const char DEFAULT_STRIP_CHARSET[];
template <typename InputIterator> template <typename InputIterator>