jeudi 17 septembre 2020

c++ add statements to an expression

There are somecases I have to add statement, like logs or trace to an expression, for example (I wanna log exactly the time for prep_stmt.executeQuery() and still I need its return value):

zdb::PreparedStatement prep_stmt = conn.prepareStatement(sql.data());
prep_stmt.setLLong(1, key);
zdb::ResultSet result = prep_stmt.executeQuery();

// do some stuff with the result

if (result.next()) {
    SCOPE_LOG(HANDLE_RESULTS);
    auto [data, size] = result.getBlob("v");
    // value is a protobuff message
    value->ParseFromArray(image, size);
}

Say I wanna log the time ellasped in prep_stmt.executeQuery(). So I add some macros like these:

// only for debug
#define EXPR_LOG_BEGIN(Name) \
    [&]() { \
        SCOPE_LOG(Name); \
        return
#define EXPR_LOG_END }();

here SCOPE_LOG is a macro for logging using raii (folly's SCOPE_EXIT macro and spdlog):

#define SCOPE_LOG(Expr) \
    auto start =  chrono::system_clock::now(); \
    SCOPE_EXIT {        \
        auto end = std::chrono::system_clock::now(); \
        std::chrono::duration<double, std::milli> elapsed_milliseconds = end - start; \
        SPDLOG_LOGGER_INFO(::Logger::getLogger(),  \
            "[[title={},elapsed_ms={}]]",                  \
            #Expr, elapsed_milliseconds.count()); \
    }

And change the above code to:

zdb::PreparedStatement prep_stmt = conn.prepareStatement(sql.data());
prep_stmt.setLLong(1, key);
zdb::ResultSet result =
        EXPR_LOG_BEGIN(DB_Execute)
        prep_stmt.executeQuery();
        EXPR_LOG_END

So the code is expanded to:

zdb::PreparedStatement prep_stmt = conn.prepareStatement(sql.data());
prep_stmt.setLLong(1, key);
zdb::ResultSet result = [&]() {
    SCOPE_LOG(Name);
    return prep_stmt.executeQuery();
}();

Is it safe to du this stuff? will it be any hidden bug for using an immediate lambda for adding statement for an expression? Is there any better way to do this? I found a similar question: How to immediately invoke a C++ lambda? but it does not state its usecases explicitly

Aucun commentaire:

Enregistrer un commentaire