1028 lines
48 KiB
C++
Executable File
1028 lines
48 KiB
C++
Executable File
/****************************************************************************
|
|
*
|
|
* Copyright (c) 2020-2023 Vivante Corporation
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*
|
|
*****************************************************************************/
|
|
#ifndef TIM_EXPERIMENTAL_TRACE_TRACER_H_
|
|
#define TIM_EXPERIMENTAL_TRACE_TRACER_H_
|
|
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <iostream>
|
|
#include <list>
|
|
#include <mutex>
|
|
#include <vector>
|
|
#include <array>
|
|
#include <memory>
|
|
#include <sstream>
|
|
#include <algorithm>
|
|
#include <type_traits>
|
|
#include <unordered_map>
|
|
|
|
#include <boost/type_index.hpp>
|
|
#include <boost/preprocessor/seq/size.hpp>
|
|
#include <boost/preprocessor/seq/elem.hpp>
|
|
#include <boost/preprocessor/seq/subseq.hpp>
|
|
#include <boost/preprocessor/seq/for_each.hpp>
|
|
#include <boost/preprocessor/seq/for_each_i.hpp>
|
|
#include <boost/preprocessor/variadic/to_seq.hpp>
|
|
#include <boost/preprocessor/variadic/size.hpp>
|
|
#include <boost/preprocessor/control/if.hpp>
|
|
#include <boost/preprocessor/arithmetic/dec.hpp>
|
|
#include <boost/preprocessor/comparison/equal.hpp>
|
|
#include <boost/hana/tuple.hpp>
|
|
#include <boost/hana/for_each.hpp>
|
|
#include <boost/hana/transform.hpp>
|
|
#include <boost/hana/unpack.hpp>
|
|
|
|
|
|
#define TRACE_LOG_NAME_ "trace_log.cc"
|
|
#define TRACE_BIN_FILE_ "trace_bin.bin"
|
|
#define TRACE_LOG_FILE_REPLAY_ "trace_log.rpl.cc"
|
|
#define TRACE_BIN_FILE_REPLAY_ "trace_bin.rpl.bin"
|
|
#define TRACE_PREFIX_ENV_VAR_ "TRACE_DUMP_PREFIX"
|
|
|
|
#define TCLOGE(fmt, ...) do { \
|
|
printf("[ERROR] [%s:%s:%d]" fmt, __FILE__, __FUNCTION__, __LINE__, \
|
|
##__VA_ARGS__); \
|
|
fflush(stdout); \
|
|
} while (0)
|
|
|
|
|
|
/********************** definitions of extra type traits **********************/
|
|
namespace trace {
|
|
|
|
template<typename...>
|
|
using void_t = void;
|
|
|
|
template <class, class = void>
|
|
struct is_fundamental_vector : std::false_type {};
|
|
|
|
template <class T>
|
|
struct is_fundamental_vector<std::vector<T>> {
|
|
static constexpr bool value = std::is_fundamental<T>::value;
|
|
};
|
|
|
|
template <class, class = void>
|
|
struct is_fundamental_array : std::false_type {};
|
|
|
|
template <class T, std::size_t N>
|
|
struct is_fundamental_array<std::array<T, N>> {
|
|
static constexpr bool value = std::is_fundamental<T>::value;
|
|
};
|
|
|
|
template <class T>
|
|
struct is_fundamental_pointer : std::integral_constant<bool,
|
|
std::is_pointer<T>::value &&
|
|
std::is_fundamental<std::remove_pointer_t<T>>::value> {};
|
|
|
|
template <class, class = void>
|
|
struct is_traced_obj : std::false_type {};
|
|
|
|
template <class T>
|
|
struct is_traced_obj<T,
|
|
void_t<decltype(std::declval<T&>().TraceGetObjName())>>
|
|
: std::true_type {};
|
|
|
|
template <class, class = void>
|
|
struct is_traced_obj_ptr : std::false_type {};
|
|
|
|
template <class T>
|
|
struct is_traced_obj_ptr<T,
|
|
void_t<decltype(std::declval<T&>()->TraceGetObjName())>>
|
|
: std::true_type {};
|
|
|
|
template <class, class = void>
|
|
struct is_traced_obj_ptr_vector : std::false_type {};
|
|
|
|
template <class T>
|
|
struct is_traced_obj_ptr_vector<std::vector<T>> {
|
|
static constexpr bool value = is_traced_obj_ptr<T>::value;
|
|
};
|
|
|
|
template <class T>
|
|
struct is_others_type : std::integral_constant<bool,
|
|
!is_fundamental_vector<std::decay_t<T>>::value &&
|
|
!is_fundamental_array<std::decay_t<T>>::value &&
|
|
!std::is_enum<std::decay_t<T>>::value &&
|
|
!std::is_fundamental<std::decay_t<T>>::value &&
|
|
!is_traced_obj<std::decay_t<T>>::value &&
|
|
!is_traced_obj_ptr<std::decay_t<T>>::value &&
|
|
!is_traced_obj_ptr_vector<std::decay_t<T>>::value> {};
|
|
|
|
template <class T>
|
|
struct is_not_traced_obj_like : std::integral_constant<bool,
|
|
!is_traced_obj<std::decay_t<T>>::value &&
|
|
!is_traced_obj_ptr<std::decay_t<T>>::value &&
|
|
!is_traced_obj_ptr_vector<std::decay_t<T>>::value> {};
|
|
|
|
} /* namespace trace */
|
|
|
|
/*************************** definition of replayer ***************************/
|
|
namespace trace {
|
|
|
|
class Replayer {
|
|
static FILE* file_trace_bin_;
|
|
static FILE* open_file(const char* file_name);
|
|
public:
|
|
template <class T>
|
|
static std::vector<T> get_vector(uint32_t offset, size_t vec_size);
|
|
|
|
template <class T>
|
|
static std::vector<T> get_vector_from(
|
|
const char* file_path, uint32_t offset, size_t vec_size);
|
|
|
|
template <class T, std::size_t N>
|
|
static std::array<T, N> get_array(uint32_t offset, size_t vec_size);
|
|
};
|
|
|
|
// #define API_REPLAYER_IMPLEMENTATION
|
|
#ifdef API_REPLAYER_IMPLEMENTATION
|
|
FILE* Replayer::file_trace_bin_ = Replayer::open_file(TRACE_BIN_FILE_REPLAY_);
|
|
/* static */ FILE* Replayer::open_file(const char* file_name) {
|
|
char* prefix = getenv(TRACE_PREFIX_ENV_VAR_);
|
|
FILE* fp;
|
|
char path[1024] = {0};
|
|
if (prefix != NULL) {
|
|
strcpy(path, prefix);
|
|
strcat(path, file_name);
|
|
} else {
|
|
strcpy(path, file_name);
|
|
}
|
|
fp = fopen(path, "r");
|
|
if (!fp) {
|
|
TCLOGE("Can not open file at: %s\n", path);
|
|
}
|
|
return fp;
|
|
}
|
|
|
|
template <class T>
|
|
/* static */ std::vector<T> Replayer::get_vector(
|
|
uint32_t offset, size_t vec_size) {
|
|
std::vector<T> ret_vec;
|
|
if (!file_trace_bin_) {
|
|
TCLOGE("FILE pointer is NULL!\n");
|
|
} else {
|
|
T* buffer = new T[vec_size];
|
|
fseek(file_trace_bin_, offset, SEEK_SET);
|
|
if (fread(buffer, sizeof(T), vec_size, file_trace_bin_) == vec_size) {
|
|
ret_vec.assign(buffer, buffer + vec_size);
|
|
} else {
|
|
TCLOGE("Read binary data failed!\n");
|
|
}
|
|
delete[] buffer;
|
|
}
|
|
return ret_vec;
|
|
}
|
|
|
|
template <class T, std::size_t N>
|
|
/* static */ std::array<T, N> Replayer::get_array(
|
|
uint32_t offset, size_t vec_size) {
|
|
std::vector<T> ret_vec = get_vector<T>(offset, vec_size);
|
|
std::array<T, N> ret_arr;
|
|
std::copy_n(ret_vec.begin(), ret_vec.size(), ret_arr.begin());
|
|
return ret_arr;
|
|
}
|
|
|
|
template <class T>
|
|
/* static */ std::vector<T> Replayer::get_vector_from(
|
|
const char* file_path,uint32_t offset, size_t vec_size) {
|
|
FILE* external_file = fopen(file_path, "r");
|
|
if (!external_file) {
|
|
TCLOGE("Can not open file at: %s\n", file_path);
|
|
}
|
|
std::vector<T> ret_vec;
|
|
T* buffer = new T[vec_size];
|
|
fseek(external_file, offset, SEEK_SET);
|
|
if (fread(buffer, sizeof(T), vec_size, external_file) == vec_size) {
|
|
ret_vec.assign(buffer, buffer + vec_size);
|
|
} else {
|
|
TCLOGE("Read binary data failed!\n");
|
|
}
|
|
delete[] buffer;
|
|
return ret_vec;
|
|
}
|
|
|
|
#endif /* #ifdef API_TRACER_IMPLEMENTATION */
|
|
|
|
} /* namespace trace */
|
|
|
|
/**************************** definition of tracer ****************************/
|
|
namespace trace {
|
|
|
|
class Tracer {
|
|
static std::unordered_map<const void*, std::string> obj_names_;
|
|
static std::unordered_map<std::string, std::string> objs_prefix_;
|
|
static std::vector<std::string> params_log_cache_;
|
|
static std::list<std::string> msg_cache_;
|
|
static std::unordered_map<const void*, void*> target2trace_map_;
|
|
static FILE* file_trace_log_;
|
|
static FILE* file_trace_bin_;
|
|
static std::mutex log_mtx_;
|
|
static std::mutex bin_mtx_;
|
|
|
|
static FILE* open_file(const char* file_name);
|
|
|
|
public:
|
|
static void logging_msg(const char* format, ...);
|
|
|
|
static uint32_t dump_data(const void* data, size_t byte_size, size_t count);
|
|
|
|
static std::string allocate_obj_name(const std::string& prefix = "obj_");
|
|
|
|
static inline void insert_obj_name(
|
|
const void* obj_ptr, const std::string& obj_name) {
|
|
obj_names_[obj_ptr] = obj_name;
|
|
}
|
|
|
|
static inline void insert_traced_obj(const void* p_target, void* p_traced) {
|
|
target2trace_map_.insert({p_target, p_traced});
|
|
}
|
|
|
|
static inline void* get_traced_obj(const void* p_target) {
|
|
return target2trace_map_[p_target];
|
|
}
|
|
|
|
static inline std::string& get_obj_name(const void* obj) {
|
|
return obj_names_[obj];
|
|
}
|
|
|
|
static inline std::string& get_obj_prefix(const std::string cls_name) {
|
|
return objs_prefix_[cls_name];
|
|
}
|
|
|
|
static inline void push_back_msg_cache(const std::string& msg) {
|
|
msg_cache_.push_back(msg);
|
|
}
|
|
|
|
static inline void amend_last_msg_cache(const std::string& msg) {
|
|
if (msg_cache_.empty()) {
|
|
TCLOGE("Can't amend sub_msg, because msg cache is empty!\n");
|
|
}
|
|
msg_cache_.back() += msg;
|
|
}
|
|
|
|
static inline void insert_before_last_msg_cache(const std::string& msg) {
|
|
msg_cache_.insert(--msg_cache_.end(), msg);
|
|
}
|
|
|
|
static inline void msg_cache_sync_to_file() {
|
|
while (!msg_cache_.empty()) {
|
|
logging_msg(msg_cache_.front().c_str());
|
|
msg_cache_.pop_front();
|
|
}
|
|
}
|
|
|
|
static inline void clear_params_log_cache() {
|
|
params_log_cache_.clear();
|
|
}
|
|
|
|
static inline void init_params_log_cache(uint32_t params_size) {
|
|
params_log_cache_.clear();
|
|
params_log_cache_.resize(params_size);
|
|
}
|
|
|
|
static inline void append_params_log_cache(std::string param_log) {
|
|
params_log_cache_.push_back(param_log);
|
|
}
|
|
|
|
static inline void insert_params_log_cache(
|
|
std::string param_log, uint32_t idx) {
|
|
if (idx != static_cast<uint32_t>(-1)) {
|
|
params_log_cache_[idx] = param_log;
|
|
} else {
|
|
params_log_cache_.push_back(param_log);
|
|
}
|
|
}
|
|
|
|
// pop the log of params into msg cache
|
|
static inline void pop_params_log_cache() {
|
|
if (params_log_cache_.size() == 0) return;
|
|
for (uint32_t i = 0; i < params_log_cache_.size() - 1; i++) {
|
|
amend_last_msg_cache(params_log_cache_[i] + ", ");
|
|
}
|
|
amend_last_msg_cache(params_log_cache_.back());
|
|
}
|
|
|
|
// directly dump the log of params to file
|
|
static inline void dump_params_log_cache() {
|
|
if (params_log_cache_.size() == 0) return;
|
|
for (uint32_t i = 0; i < params_log_cache_.size() - 1; i++) {
|
|
logging_msg("%s, ", params_log_cache_[i].c_str());
|
|
}
|
|
logging_msg(params_log_cache_.back().c_str());
|
|
}
|
|
|
|
/*
|
|
* template functions for logging parameters to log file
|
|
*/
|
|
// default substitution
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
|
template <class T,
|
|
typename std::enable_if_t<is_others_type<T>::value, int> = 0>
|
|
static inline void logging_param(const T& t, uint32_t idx) {
|
|
insert_params_log_cache(std::string(), idx);
|
|
}
|
|
#pragma GCC diagnostic pop
|
|
|
|
// enable if T is fundamental std::vector
|
|
template <class T,
|
|
typename std::enable_if_t<
|
|
is_fundamental_vector<std::decay_t<T>>::value, int> = 0>
|
|
static inline void logging_param(const T& t, uint32_t idx) {
|
|
uint32_t offset = dump_data(t.data(), sizeof(t[0]), t.size());
|
|
std::string element_type =
|
|
boost::typeindex::type_id<decltype(t[0])>().pretty_name();
|
|
char log_msg[1024] = {0};
|
|
snprintf(log_msg, 1024, "trace::Replayer::get_vector<%s>(%u, %u)",
|
|
element_type.c_str(), offset, (uint32_t)t.size());
|
|
insert_params_log_cache(std::string(log_msg), idx);
|
|
}
|
|
|
|
// enable if T is fundamental std::array
|
|
template <class T,
|
|
typename std::enable_if_t<
|
|
is_fundamental_array<std::decay_t<T>>::value, int> = 0>
|
|
static inline void logging_param(const T& t, uint32_t idx) {
|
|
uint32_t offset = dump_data(t.data(), sizeof(t[0]), t.size());
|
|
std::string element_type =
|
|
boost::typeindex::type_id<decltype(t[0])>().pretty_name();
|
|
char log_msg[1024] = {0};
|
|
snprintf(log_msg, 1024, "trace::Replayer::get_array<%s, %d>(%u, %u)",
|
|
element_type.c_str(), (uint32_t)t.size(), offset,
|
|
(uint32_t)t.size());
|
|
insert_params_log_cache(std::string(log_msg), idx);
|
|
}
|
|
|
|
// enable if T is enum
|
|
template <class T,
|
|
typename std::enable_if_t<
|
|
std::is_enum<std::decay_t<T>>::value, int> = 0>
|
|
static inline void logging_param(const T& t, uint32_t idx) {
|
|
std::string enum_type =
|
|
boost::typeindex::type_id<decltype(t)>().pretty_name();
|
|
char log_msg[1024] = {0};
|
|
snprintf(log_msg, 1024, "(%s)%d", enum_type.c_str(), (int)t);
|
|
insert_params_log_cache(std::string(log_msg), idx);
|
|
}
|
|
|
|
// enable if T is fundamental
|
|
template <class T,
|
|
typename std::enable_if_t<
|
|
std::is_fundamental<std::decay_t<T>>::value, int> = 0>
|
|
static inline void logging_param(const T& t, uint32_t idx) {
|
|
insert_params_log_cache(std::to_string(t), idx);
|
|
}
|
|
|
|
// enable if T is derive from TraceClassBase
|
|
template <class T,
|
|
typename std::enable_if_t<
|
|
is_traced_obj<std::decay_t<T>>::value, int> = 0>
|
|
static inline void logging_param(const T& t, uint32_t idx) {
|
|
insert_params_log_cache(t.TraceGetObjName(), idx);
|
|
}
|
|
|
|
// enable if T is pointer to object which
|
|
// derive from TraceClassBase
|
|
template <class T,
|
|
typename std::enable_if_t<
|
|
is_traced_obj_ptr<std::decay_t<T>>::value, int> = 0>
|
|
static inline void logging_param(const T& t, uint32_t idx) {
|
|
insert_params_log_cache(t->TraceGetObjName(), idx);
|
|
}
|
|
|
|
// enable if T is vector of pointer to object which
|
|
// derive from TraceClassBase
|
|
template <class T,
|
|
typename std::enable_if_t<
|
|
is_traced_obj_ptr_vector<std::decay_t<T>>::value, int> = 0>
|
|
static inline void logging_param(const T& t, uint32_t idx) {
|
|
std::stringstream ss;
|
|
ss << "{";
|
|
for (uint32_t i = 0; i < t.size() - 1; i++) {
|
|
ss << t[i]->TraceGetObjName() << ", ";
|
|
}
|
|
ss << t.back()->TraceGetObjName() << "}";
|
|
insert_params_log_cache(ss.str(), idx);
|
|
}
|
|
|
|
/*
|
|
* template functions for pass correct parameters to api implementation
|
|
*/
|
|
// default substitution
|
|
template <class T,
|
|
typename std::enable_if_t<is_not_traced_obj_like<T>::value, int> = 0>
|
|
static inline T&& proc_param(T&& t) {
|
|
return std::forward<T>(t);
|
|
}
|
|
|
|
// enable if T is derive from TraceClassBase
|
|
template <class T,
|
|
typename std::enable_if_t<
|
|
is_traced_obj<std::decay_t<T>>::value, int> = 0>
|
|
static inline decltype(std::declval<T&>().TraceGetImpl())&& proc_param(
|
|
T&& t) {
|
|
return std::forward<T>(t).TraceGetImpl();
|
|
}
|
|
|
|
// enable if T is pointer to object which
|
|
// derive from TraceClassBase
|
|
template <class T,
|
|
typename std::enable_if_t<
|
|
is_traced_obj_ptr<std::decay_t<T>>::value, int> = 0>
|
|
static inline decltype(std::declval<T&>()->TraceGetImplSp()) proc_param(
|
|
T&& t) {
|
|
return std::forward<T>(t)->TraceGetImplSp();
|
|
}
|
|
|
|
// enable if T is std::vector which element is pointer of traced object
|
|
template <class T,
|
|
typename std::enable_if_t<
|
|
is_traced_obj_ptr_vector<std::decay_t<T>>::value, int> = 0>
|
|
static inline std::vector<decltype(std::declval<T&>()[0]->TraceGetImplSp())>
|
|
proc_param(T&& t) {
|
|
std::vector<decltype(t[0]->TraceGetImplSp())> impl_vec;
|
|
for (auto& x : std::forward<T>(t)) {
|
|
impl_vec.emplace_back(x->TraceGetImplSp());
|
|
}
|
|
return impl_vec;
|
|
}
|
|
};
|
|
|
|
#ifdef API_TRACER_IMPLEMENTATION
|
|
std::unordered_map<const void*, std::string> Tracer::obj_names_;
|
|
std::vector<std::string> Tracer::params_log_cache_;
|
|
std::list<std::string> Tracer::msg_cache_;
|
|
std::unordered_map<const void*, void*> Tracer::target2trace_map_;
|
|
FILE* Tracer::file_trace_log_ = Tracer::open_file(TRACE_LOG_NAME_);
|
|
FILE* Tracer::file_trace_bin_ = Tracer::open_file(TRACE_BIN_FILE_);
|
|
std::mutex Tracer::log_mtx_;
|
|
std::mutex Tracer::bin_mtx_;
|
|
std::unordered_map<std::string, std::string> Tracer::objs_prefix_ = {
|
|
{"Quantization", "quant_" },
|
|
{"TensorSpec", "spec_" },
|
|
{"Tensor", "tensor_" },
|
|
{"Graph", "graph_" }
|
|
};
|
|
/* static */ FILE* Tracer::open_file(const char* file_name) {
|
|
char* prefix = getenv(TRACE_PREFIX_ENV_VAR_);
|
|
FILE* fp;
|
|
char path[1024] = {0};
|
|
if (prefix != NULL) {
|
|
strcpy(path, prefix);
|
|
strcat(path, file_name);
|
|
} else {
|
|
strcpy(path, file_name);
|
|
}
|
|
fp = fopen(path, "w");
|
|
if (!fp) {
|
|
TCLOGE("Can not open file at: %s\n", path);
|
|
}
|
|
return fp;
|
|
}
|
|
|
|
/* static */ std::string Tracer::allocate_obj_name(
|
|
const std::string& prefix) {
|
|
static std::unordered_map<std::string, uint32_t> objects_counter;
|
|
if (objects_counter.find(prefix) == objects_counter.end()) {
|
|
objects_counter[prefix] = 0;
|
|
}
|
|
return prefix + std::to_string(objects_counter[prefix]++);
|
|
}
|
|
|
|
/* static */ void Tracer::logging_msg(const char* format, ...) {
|
|
char arg_buffer[1024] = {0};
|
|
va_list args;
|
|
va_start(args, format);
|
|
vsnprintf(arg_buffer, 1024, format, args);
|
|
va_end(args);
|
|
// printf("%s", arg_buffer);
|
|
if (!file_trace_log_) {
|
|
TCLOGE("Log file do not exist\n");
|
|
}
|
|
std::lock_guard<std::mutex> lock(log_mtx_);
|
|
fprintf(file_trace_log_, "%s", arg_buffer);
|
|
fflush(file_trace_log_);
|
|
}
|
|
|
|
/* static */ uint32_t Tracer::dump_data(
|
|
const void* data, size_t byte_size, size_t count) {
|
|
std::lock_guard<std::mutex> lock(bin_mtx_);
|
|
if (fwrite(data, byte_size, count, file_trace_bin_) != count) {
|
|
TCLOGE("Write trace binary data failed!\n");
|
|
}
|
|
fflush(file_trace_bin_);
|
|
static uint32_t offset = 0;
|
|
uint32_t temp = offset;
|
|
offset += byte_size * count;
|
|
return temp;
|
|
}
|
|
#endif /* #ifdef API_TRACER_IMPLEMENTATION */
|
|
|
|
} /* namespace trace */
|
|
|
|
/************************ definition of TraceClassBase ************************/
|
|
namespace trace {
|
|
|
|
template <class TargetClass>
|
|
struct TraceClassBase {
|
|
TargetClass& TraceGetImpl() const { return *impl_; }
|
|
|
|
// temporary return rvalue to prevent compile error
|
|
std::shared_ptr<TargetClass> TraceGetImplSp() { return impl_; }
|
|
|
|
std::string& TraceGetObjName() const {
|
|
return Tracer::get_obj_name(static_cast<const void*>(impl_.get()));
|
|
}
|
|
|
|
std::shared_ptr<TargetClass> impl_;
|
|
// static const char* target_namespace_name_;
|
|
};
|
|
|
|
// #ifdef TARGET_NAMESPACE_NAME
|
|
// template <class TargetClass>
|
|
// const char* TraceClassBase<TargetClass>::target_namespace_name_ =
|
|
// TARGET_NAMESPACE_NAME;
|
|
// #endif // #ifdef TARGET_NAMESPACE_NAME
|
|
|
|
} /* namespace trace */
|
|
|
|
#ifdef TARGET_NAMESPACE_NAME
|
|
static const char* target_namespace_name_ = TARGET_NAMESPACE_NAME;
|
|
#endif // #ifdef TARGET_NAMESPACE_NAME
|
|
|
|
/**************************** definitions of macros ***************************/
|
|
#define LOG_PARAM_IMPL_(r, _, i, param) \
|
|
Tracer::logging_param(param, i);
|
|
|
|
#define LOG_PARAMS(params) \
|
|
Tracer::init_params_log_cache(BOOST_PP_SEQ_SIZE(params)); \
|
|
BOOST_PP_SEQ_FOR_EACH_I(LOG_PARAM_IMPL_, _, params)
|
|
|
|
#define PROC_PARAM_IMPL_COMMA_(r, _, param) \
|
|
Tracer::proc_param(param),
|
|
|
|
#define PROC_PARAM_IMPL_NO_COMMA_(param) \
|
|
Tracer::proc_param(param)
|
|
|
|
#define PROC_SINGLE_PARAM_(params) \
|
|
PROC_PARAM_IMPL_NO_COMMA_(BOOST_PP_SEQ_ELEM(0, params))
|
|
|
|
#define PROC_MULTI_PARAMS_(params) \
|
|
BOOST_PP_SEQ_FOR_EACH( \
|
|
PROC_PARAM_IMPL_COMMA_, _, \
|
|
BOOST_PP_SEQ_SUBSEQ(params, 0, BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(params)))) \
|
|
PROC_PARAM_IMPL_NO_COMMA_( \
|
|
BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(params)), params))
|
|
|
|
#define PROC_PARAMS(params) \
|
|
BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE(params), 1), \
|
|
PROC_SINGLE_PARAM_, PROC_MULTI_PARAMS_)(params)
|
|
|
|
|
|
#define NAME_A_PARAM_(r, data, i, elem) (param_##i)
|
|
|
|
#define ARGS_DESC_TO_PARAMS(descs) \
|
|
BOOST_PP_SEQ_FOR_EACH_I(NAME_A_PARAM_, _, descs)
|
|
|
|
#define IS_WITH_DEFAULT_VAL_(desc) \
|
|
BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE(desc), 2)
|
|
|
|
#define SET_DEFAULT_VAL_(val) = BOOST_PP_SEQ_HEAD(val)
|
|
|
|
#define DO_NOTHING(x)
|
|
|
|
#define DECLARE_AN_ARG_COMMA_(r, names, i, desc) \
|
|
BOOST_PP_SEQ_HEAD(desc) BOOST_PP_SEQ_ELEM(i, names) \
|
|
BOOST_PP_IF(IS_WITH_DEFAULT_VAL_(desc), SET_DEFAULT_VAL_, DO_NOTHING) \
|
|
(BOOST_PP_SEQ_TAIL(desc)),
|
|
|
|
#define DECLARE_AN_ARG_NO_COMMA_(name, desc) \
|
|
BOOST_PP_SEQ_HEAD(desc) name \
|
|
BOOST_PP_IF(IS_WITH_DEFAULT_VAL_(desc), SET_DEFAULT_VAL_, DO_NOTHING) \
|
|
(BOOST_PP_SEQ_TAIL(desc))
|
|
|
|
#define SINGLE_ARG_DESC_TO_DECLARATION_(desc) \
|
|
DECLARE_AN_ARG_NO_COMMA_( \
|
|
BOOST_PP_SEQ_ELEM(0, ARGS_DESC_TO_PARAMS(desc)), \
|
|
BOOST_PP_SEQ_ELEM(0, desc))
|
|
|
|
#define MULTI_ARGS_DESC_TO_DECLARATION_(descs) \
|
|
BOOST_PP_SEQ_FOR_EACH_I(DECLARE_AN_ARG_COMMA_, \
|
|
BOOST_PP_SEQ_SUBSEQ(ARGS_DESC_TO_PARAMS(descs), \
|
|
0, BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(descs))), \
|
|
BOOST_PP_SEQ_SUBSEQ(descs, 0, \
|
|
BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(descs)))) \
|
|
DECLARE_AN_ARG_NO_COMMA_( \
|
|
BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(descs)), \
|
|
ARGS_DESC_TO_PARAMS(descs)), \
|
|
BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(descs)), descs))
|
|
|
|
#define ARGS_DESC_TO_DECLARATION(descs) \
|
|
BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE(descs), 1), \
|
|
SINGLE_ARG_DESC_TO_DECLARATION_, \
|
|
MULTI_ARGS_DESC_TO_DECLARATION_)(descs)
|
|
|
|
#define TO_VARIADIC_IMPL_COMMA_(r, _, elem) elem,
|
|
#define TO_VARIADIC_IMPL_NO_COMMA_(elem) elem
|
|
|
|
#define SEQ_TO_VARIADICS(seqs) \
|
|
BOOST_PP_SEQ_FOR_EACH(TO_VARIADIC_IMPL_COMMA_, _, \
|
|
BOOST_PP_SEQ_SUBSEQ(seqs, 0, BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(seqs)))) \
|
|
TO_VARIADIC_IMPL_NO_COMMA_( \
|
|
BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(seqs)), seqs))
|
|
|
|
#define DEF_MEMFN_SP_2_(ret_class, api_name) \
|
|
std::shared_ptr<ret_class> api_name() { \
|
|
std::string this_obj_name = TraceGetObjName(); \
|
|
std::string obj_name = \
|
|
Tracer::allocate_obj_name(Tracer::get_obj_prefix(#ret_class)); \
|
|
Tracer::logging_msg("auto %s = %s->%s();\n", obj_name.c_str(), \
|
|
this_obj_name.c_str(), __FUNCTION__); \
|
|
auto obj_impl_sp = impl_->api_name(); \
|
|
auto obj_sp = std::make_shared<ret_class>(obj_impl_sp); \
|
|
Tracer::insert_obj_name(static_cast<void*>(obj_impl_sp.get()), obj_name); \
|
|
return obj_sp; \
|
|
}
|
|
|
|
#define DEF_MEMFN_SP_3_(ret_class, api_name, args_desc) \
|
|
std::shared_ptr<ret_class> api_name(ARGS_DESC_TO_DECLARATION(args_desc)) { \
|
|
std::string this_obj_name = TraceGetObjName(); \
|
|
std::string obj_name = \
|
|
Tracer::allocate_obj_name(Tracer::get_obj_prefix(#ret_class)); \
|
|
Tracer::logging_msg("auto %s = %s->%s(", obj_name.c_str(), \
|
|
this_obj_name.c_str(), __FUNCTION__); \
|
|
LOG_PARAMS(ARGS_DESC_TO_PARAMS(args_desc)) \
|
|
Tracer::dump_params_log_cache(); \
|
|
Tracer::logging_msg(");\n"); \
|
|
auto obj_impl_sp = impl_->api_name( \
|
|
PROC_PARAMS(ARGS_DESC_TO_PARAMS(args_desc))); \
|
|
auto obj_sp = std::make_shared<ret_class>(obj_impl_sp); \
|
|
Tracer::insert_obj_name(static_cast<void*>(obj_impl_sp.get()), obj_name); \
|
|
return obj_sp; \
|
|
}
|
|
|
|
#define DEF_MEMFN_SP_4_(ret_class, api_name, args_desc, SPECIAL_MACRO_) \
|
|
std::shared_ptr<ret_class> api_name(ARGS_DESC_TO_DECLARATION(args_desc)) { \
|
|
std::string this_obj_name = TraceGetObjName(); \
|
|
std::string obj_name = \
|
|
Tracer::allocate_obj_name(Tracer::get_obj_prefix(#ret_class)); \
|
|
Tracer::push_back_msg_cache("auto " + obj_name + " = " + this_obj_name \
|
|
+ "->" + __FUNCTION__ + "("); \
|
|
LOG_PARAMS(ARGS_DESC_TO_PARAMS(args_desc)) \
|
|
SPECIAL_MACRO_(ARGS_DESC_TO_PARAMS(args_desc)) \
|
|
Tracer::pop_params_log_cache(); \
|
|
Tracer::amend_last_msg_cache(");\n"); \
|
|
Tracer::msg_cache_sync_to_file(); \
|
|
auto obj_impl_sp = impl_->api_name( \
|
|
PROC_PARAMS(ARGS_DESC_TO_PARAMS(args_desc))); \
|
|
auto obj_sp = std::make_shared<ret_class>(obj_impl_sp); \
|
|
Tracer::insert_obj_name(static_cast<void*>(obj_impl_sp.get()), obj_name); \
|
|
return obj_sp; \
|
|
}
|
|
|
|
#define DEF_SIMPLE_UNTRACED_API(retval, api_name) \
|
|
retval api_name() { \
|
|
return impl_->api_name(); \
|
|
}
|
|
|
|
#define DEF_MEMFN_2_(retval, api_name) \
|
|
retval api_name() { \
|
|
std::string this_obj_name = TraceGetObjName(); \
|
|
Tracer::logging_msg("%s->%s();\n", \
|
|
this_obj_name.c_str(), __FUNCTION__); \
|
|
return impl_->api_name(); \
|
|
}
|
|
|
|
#define DEF_MEMFN_3_(retval, api_name, args_desc) \
|
|
retval api_name(ARGS_DESC_TO_DECLARATION(args_desc)) { \
|
|
std::string this_obj_name = TraceGetObjName(); \
|
|
Tracer::logging_msg("%s->%s(", \
|
|
this_obj_name.c_str(), __FUNCTION__); \
|
|
LOG_PARAMS(ARGS_DESC_TO_PARAMS(args_desc)) \
|
|
Tracer::dump_params_log_cache(); \
|
|
Tracer::logging_msg(");\n"); \
|
|
return impl_->api_name( \
|
|
PROC_PARAMS(ARGS_DESC_TO_PARAMS(args_desc))); \
|
|
}
|
|
|
|
#define DEF_MEMFN_4_(retval, api_name, args_desc, SPECIAL_MACRO_) \
|
|
retval api_name(ARGS_DESC_TO_DECLARATION(args_desc)) { \
|
|
std::string this_obj_name = TraceGetObjName(); \
|
|
Tracer::push_back_msg_cache( \
|
|
this_obj_name + "->" + __FUNCTION__ + "("); \
|
|
LOG_PARAMS(ARGS_DESC_TO_PARAMS(args_desc)) \
|
|
SPECIAL_MACRO_(ARGS_DESC_TO_PARAMS(args_desc)) \
|
|
Tracer::pop_params_log_cache(); \
|
|
Tracer::amend_last_msg_cache(");\n"); \
|
|
Tracer::msg_cache_sync_to_file(); \
|
|
return impl_->api_name( \
|
|
PROC_PARAMS(ARGS_DESC_TO_PARAMS(args_desc))); \
|
|
}
|
|
|
|
#define DEF_INPLACE_MEMFN_2_(retval, api_name) \
|
|
retval api_name() { \
|
|
std::string this_obj_name = TraceGetObjName(); \
|
|
Tracer::logging_msg("%s->%s();\n", \
|
|
this_obj_name.c_str(), __FUNCTION__); \
|
|
impl_->api_name(); \
|
|
return *this; \
|
|
}
|
|
|
|
#define DEF_INPLACE_MEMFN_3_(retval, api_name, args_desc) \
|
|
retval api_name(ARGS_DESC_TO_DECLARATION(args_desc)) { \
|
|
std::string this_obj_name = TraceGetObjName(); \
|
|
Tracer::logging_msg("%s->%s(", \
|
|
this_obj_name.c_str(), __FUNCTION__); \
|
|
LOG_PARAMS(ARGS_DESC_TO_PARAMS(args_desc)) \
|
|
Tracer::dump_params_log_cache(); \
|
|
Tracer::logging_msg(");\n"); \
|
|
impl_->api_name(PROC_PARAMS(ARGS_DESC_TO_PARAMS(args_desc))); \
|
|
return *this; \
|
|
}
|
|
|
|
#define DEF_INPLACE_MEMFN_4_(retval, api_name, args_desc, SPECIAL_MACRO_) \
|
|
retval api_name(ARGS_DESC_TO_DECLARATION(args_desc)) { \
|
|
std::string this_obj_name = TraceGetObjName(); \
|
|
Tracer::push_back_msg_cache( \
|
|
this_obj_name + "->" + __FUNCTION__ + "("); \
|
|
LOG_PARAMS(ARGS_DESC_TO_PARAMS(args_desc)) \
|
|
SPECIAL_MACRO_(ARGS_DESC_TO_PARAMS(args_desc)) \
|
|
Tracer::pop_params_log_cache(); \
|
|
Tracer::amend_last_msg_cache(");\n"); \
|
|
Tracer::msg_cache_sync_to_file(); \
|
|
impl_->api_name(PROC_PARAMS(ARGS_DESC_TO_PARAMS(args_desc))); \
|
|
return *this; \
|
|
}
|
|
|
|
#define DEF_CONSTRUCTOR_1_(class_name) \
|
|
class_name() { \
|
|
std::string obj_name = \
|
|
Tracer::allocate_obj_name(Tracer::get_obj_prefix(#class_name)); \
|
|
Tracer::logging_msg("auto %s = %s::%s();\n", obj_name.c_str(), \
|
|
target_namespace_name_, __FUNCTION__); \
|
|
impl_ = std::make_shared<target::class_name>(); \
|
|
Tracer::insert_traced_obj( \
|
|
static_cast<void*>(impl_.get()), static_cast<void*>(this)); \
|
|
Tracer::insert_obj_name(static_cast<void*>(impl_.get()), obj_name); \
|
|
}
|
|
|
|
#define DEF_CONSTRUCTOR_2_(class_name, args_desc) \
|
|
class_name(ARGS_DESC_TO_DECLARATION(args_desc)) { \
|
|
std::string obj_name = \
|
|
Tracer::allocate_obj_name(Tracer::get_obj_prefix(#class_name)); \
|
|
Tracer::logging_msg("auto %s = %s::%s(", obj_name.c_str(), \
|
|
target_namespace_name_, __FUNCTION__); \
|
|
LOG_PARAMS(ARGS_DESC_TO_PARAMS(args_desc)) \
|
|
Tracer::dump_params_log_cache(); \
|
|
Tracer::logging_msg(");\n"); \
|
|
impl_ = std::make_shared<target::class_name>( \
|
|
PROC_PARAMS(ARGS_DESC_TO_PARAMS(args_desc))); \
|
|
Tracer::insert_traced_obj( \
|
|
static_cast<void*>(impl_.get()), static_cast<void*>(this)); \
|
|
Tracer::insert_obj_name(static_cast<void*>(impl_.get()), obj_name); \
|
|
}
|
|
|
|
#define DEF_CONSTRUCTOR_3_(class_name, args_desc, SPECIAL_MACRO_) \
|
|
class_name(ARGS_DESC_TO_DECLARATION(args_desc)) { \
|
|
std::string obj_name = \
|
|
Tracer::allocate_obj_name(Tracer::get_obj_prefix(#class_name)); \
|
|
Tracer::push_back_msg_cache( \
|
|
"auto " + obj_name + " = " + target_namespace_name_ + "::" + \
|
|
__FUNCTION__ + "("); \
|
|
LOG_PARAMS(ARGS_DESC_TO_PARAMS(args_desc)) \
|
|
SPECIAL_MACRO_(ARGS_DESC_TO_PARAMS(args_desc)) \
|
|
Tracer::pop_params_log_cache(); \
|
|
Tracer::amend_last_msg_cache(");\n"); \
|
|
Tracer::msg_cache_sync_to_file(); \
|
|
impl_ = std::make_shared<target::class_name>( \
|
|
PROC_PARAMS(ARGS_DESC_TO_PARAMS(args_desc))); \
|
|
Tracer::insert_traced_obj( \
|
|
static_cast<void*>(impl_.get()), static_cast<void*>(this)); \
|
|
Tracer::insert_obj_name(static_cast<void*>(impl_.get()), obj_name); \
|
|
}
|
|
|
|
|
|
/*
|
|
* Follows code to detect empty macro variadic is from:
|
|
* https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
|
|
*/
|
|
#define __ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13,_14,\
|
|
_15, ...) _15
|
|
#define __HAS_COMMA(...) __ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
|
1, 1, 1, 0)
|
|
#define __TRIGGER_PARENTHESIS_(...) ,
|
|
#define __PASTE5(_0, _1, _2, _3, _4) _0 ## _1 ## _2 ## _3 ## _4
|
|
#define __IS_EMPTY_CASE_0001 ,
|
|
#define __IS_EMPTY(_0, _1, _2, _3) __HAS_COMMA( \
|
|
__PASTE5(__IS_EMPTY_CASE_, _0, _1, _2, _3))
|
|
|
|
#define TUPLE_IS_EMPTY(...) \
|
|
__IS_EMPTY( \
|
|
/* test if there is just one argument, eventually an empty one */ \
|
|
__HAS_COMMA(__VA_ARGS__), \
|
|
/* test if _TRIGGER_PARENTHESIS_ together with the argument adds a comma */\
|
|
__HAS_COMMA(__TRIGGER_PARENTHESIS_ __VA_ARGS__), \
|
|
/* test if the argument together with a parenthesis adds a comma */ \
|
|
__HAS_COMMA(__VA_ARGS__ (/*empty*/)), \
|
|
/* test if placing it between _TRIGGER_PARENTHESIS_ */ \
|
|
/* and the parenthesis adds a comma */ \
|
|
__HAS_COMMA(__TRIGGER_PARENTHESIS_ __VA_ARGS__ (/*empty*/)) \
|
|
)
|
|
|
|
#define EMPTY_LAMBDA_ placeholder
|
|
// BOOST_PP_VARIADIC_SIZE() variadic is empty, but it's will expand to 1.
|
|
// And there are unknow issue of tensorflow build, ##__VA_ARGS__ can't correctly
|
|
// remove the comma before.
|
|
#define VARIADIC_SIZE_PLUS_ONE(...) \
|
|
BOOST_PP_VARIADIC_SIZE(EMPTY_LAMBDA_, ##__VA_ARGS__)
|
|
#define INVOKE_LAMBDA_(r, _, lambda) lambda();
|
|
#define INVOKE_LAMBDAS_(...) \
|
|
BOOST_PP_IF(BOOST_PP_EQUAL(TUPLE_IS_EMPTY(__VA_ARGS__), 1), \
|
|
BOOST_PP_EMPTY(), BOOST_PP_SEQ_FOR_EACH(INVOKE_LAMBDA_, _, \
|
|
BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)))
|
|
|
|
/*
|
|
* In substitution for traced obj, api_impl got pointer retval because if
|
|
* directly return reference will get build error of using pure virtual class
|
|
* constructor.
|
|
*/
|
|
#define DEF_TRACED_API(Ret, api_name, ...) \
|
|
template <class R = Ret, class... Args> \
|
|
typename std::enable_if_t<is_traced_obj<R>::value, R> api_name( \
|
|
Args... params) { \
|
|
std::string this_obj_name = TraceGetObjName(); \
|
|
Tracer::push_back_msg_cache( \
|
|
this_obj_name + "->" + __FUNCTION__ + "("); \
|
|
Tracer::clear_params_log_cache(); \
|
|
boost::hana::tuple<Args...> params_tuple = {params...}; \
|
|
boost::hana::for_each(params_tuple, [&] (auto x) { \
|
|
Tracer::logging_param(x, -1); \
|
|
}); \
|
|
INVOKE_LAMBDAS_(__VA_ARGS__) \
|
|
Tracer::pop_params_log_cache(); \
|
|
Tracer::amend_last_msg_cache(");\n"); \
|
|
Tracer::msg_cache_sync_to_file(); \
|
|
auto api_impl = [&] (auto&&... ts) { \
|
|
return &(impl_->api_name(ts...)); \
|
|
}; \
|
|
auto proc_param_lambda = [] (auto&& t) { \
|
|
return Tracer::proc_param(t); \
|
|
}; \
|
|
auto params_impl = boost::hana::transform(params_tuple, proc_param_lambda);\
|
|
auto ret_impl_p = boost::hana::unpack(params_impl, api_impl); \
|
|
return *static_cast<std::decay_t<R>*>(Tracer::get_traced_obj(ret_impl_p)); \
|
|
} \
|
|
\
|
|
template <class R = Ret, class... Args> \
|
|
typename std::enable_if_t<is_traced_obj_ptr<R>::value, R> api_name( \
|
|
Args... params) { \
|
|
std::string this_obj_name = TraceGetObjName(); \
|
|
std::string obj_name = \
|
|
Tracer::allocate_obj_name(Tracer::get_obj_prefix( \
|
|
boost::typeindex::type_id<typename R::element_type>() \
|
|
.pretty_name())); \
|
|
Tracer::push_back_msg_cache( \
|
|
this_obj_name + "->" + __FUNCTION__ + "("); \
|
|
Tracer::clear_params_log_cache(); \
|
|
boost::hana::tuple<Args...> params_tuple = {params...}; \
|
|
boost::hana::for_each(params_tuple, [&] (auto x) { \
|
|
Tracer::logging_param(x, -1); \
|
|
}); \
|
|
INVOKE_LAMBDAS_(__VA_ARGS__) \
|
|
Tracer::pop_params_log_cache(); \
|
|
Tracer::amend_last_msg_cache(");\n"); \
|
|
Tracer::msg_cache_sync_to_file(); \
|
|
auto api_impl = [&] (auto&&... ts) { \
|
|
return impl_->api_name(ts...); \
|
|
}; \
|
|
auto proc_param_lambda = [] (auto&& t) { \
|
|
return Tracer::proc_param(t); \
|
|
}; \
|
|
auto params_impl = boost::hana::transform(params_tuple, proc_param_lambda);\
|
|
auto obj_impl_sp = boost::hana::unpack(params_impl, api_impl); \
|
|
R obj_sp(obj_impl_sp); \
|
|
Tracer::insert_obj_name(static_cast<void*>(obj_impl_sp.get()), obj_name); \
|
|
return obj_sp; \
|
|
} \
|
|
\
|
|
template <class R = Ret, class... Args> \
|
|
typename std::enable_if_t<is_traced_obj_ptr_vector<R>::value, R> api_name( \
|
|
Args... params) { \
|
|
std::string this_obj_name = TraceGetObjName(); \
|
|
Tracer::push_back_msg_cache( \
|
|
this_obj_name + "->" + __FUNCTION__ + "("); \
|
|
Tracer::clear_params_log_cache(); \
|
|
boost::hana::tuple<Args...> params_tuple = {params...}; \
|
|
boost::hana::for_each(params_tuple, [&] (auto x) { \
|
|
Tracer::logging_param(x, -1); \
|
|
}); \
|
|
INVOKE_LAMBDAS_(__VA_ARGS__) \
|
|
Tracer::pop_params_log_cache(); \
|
|
Tracer::amend_last_msg_cache(");\n"); \
|
|
Tracer::msg_cache_sync_to_file(); \
|
|
auto api_impl = [&] (auto&&... ts) { \
|
|
return impl_->api_name(ts...); \
|
|
}; \
|
|
auto proc_param_lambda = [] (auto&& t) { \
|
|
return Tracer::proc_param(t); \
|
|
}; \
|
|
auto params_impl = boost::hana::transform(params_tuple, proc_param_lambda);\
|
|
auto ret_impl = boost::hana::unpack(params_impl, api_impl); \
|
|
R ret; \
|
|
for(auto& x : ret_impl) { \
|
|
ret.push_back(std::make_shared<typename R::value_type::element_type>( \
|
|
*static_cast<typename R::value_type::element_type*>( \
|
|
Tracer::get_traced_obj(x.get())))); \
|
|
} \
|
|
return ret; \
|
|
} \
|
|
\
|
|
template <class R = Ret, class... Args> \
|
|
typename std::enable_if_t<is_not_traced_obj_like<R>::value, R> api_name( \
|
|
Args... params) { \
|
|
std::string this_obj_name = TraceGetObjName(); \
|
|
Tracer::push_back_msg_cache( \
|
|
this_obj_name + "->" + __FUNCTION__ + "("); \
|
|
Tracer::clear_params_log_cache(); \
|
|
boost::hana::tuple<Args...> params_tuple = {params...}; \
|
|
boost::hana::for_each(params_tuple, [&] (auto x) { \
|
|
Tracer::logging_param(x, -1); \
|
|
}); \
|
|
INVOKE_LAMBDAS_(__VA_ARGS__) \
|
|
Tracer::pop_params_log_cache(); \
|
|
Tracer::amend_last_msg_cache(");\n"); \
|
|
Tracer::msg_cache_sync_to_file(); \
|
|
auto api_impl = [&] (auto&&... ts) { \
|
|
return impl_->api_name(ts...); \
|
|
}; \
|
|
auto proc_param_lambda = [] (auto&& t) { \
|
|
return Tracer::proc_param(t); \
|
|
}; \
|
|
auto params_impl = boost::hana::transform(params_tuple, proc_param_lambda);\
|
|
return boost::hana::unpack(params_impl, api_impl); \
|
|
}
|
|
|
|
#define GET_MACRO_OVERLOAD_4_(_1, _2, _3, _4, MACRO, ...) MACRO
|
|
#define GET_MACRO_OVERLOAD_3_(_1, _2, _3, MACRO, ...) MACRO
|
|
|
|
#define DEF_MEMFN_SP(...) \
|
|
GET_MACRO_OVERLOAD_4_(__VA_ARGS__, \
|
|
DEF_MEMFN_SP_4_, \
|
|
DEF_MEMFN_SP_3_, \
|
|
DEF_MEMFN_SP_2_)(__VA_ARGS__)
|
|
|
|
#define DEF_MEMFN(...) \
|
|
GET_MACRO_OVERLOAD_4_(__VA_ARGS__, \
|
|
DEF_MEMFN_4_, \
|
|
DEF_MEMFN_3_, \
|
|
DEF_MEMFN_2_)(__VA_ARGS__)
|
|
|
|
#define DEF_INPLACE_MEMFN(...) \
|
|
GET_MACRO_OVERLOAD_4_(__VA_ARGS__, \
|
|
DEF_INPLACE_MEMFN_4_, \
|
|
DEF_INPLACE_MEMFN_3_, \
|
|
DEF_INPLACE_MEMFN_2_)(__VA_ARGS__)
|
|
|
|
#define DEF_CONSTRUCTOR(...) \
|
|
GET_MACRO_OVERLOAD_3_(__VA_ARGS__, \
|
|
DEF_CONSTRUCTOR_3_, \
|
|
DEF_CONSTRUCTOR_2_, \
|
|
DEF_CONSTRUCTOR_1_)(__VA_ARGS__)
|
|
|
|
#define LOGGING_POINTER_MSG(offset, length, idx) \
|
|
char log_msg[1024] = {0}; \
|
|
snprintf(log_msg, 1024, \
|
|
"trace::Replayer::get_vector<char>(%u, %u).data()", \
|
|
offset, length); \
|
|
Tracer::insert_params_log_cache(std::string(log_msg), idx);
|
|
|
|
#define DEF_INTERFACE_CONSTRUCTOR(interface) \
|
|
interface(const std::shared_ptr<target::interface>& impl) { \
|
|
Tracer::insert_traced_obj(static_cast<void*>(impl.get()), \
|
|
static_cast<void*>(this)); \
|
|
impl_ = impl; \
|
|
}
|
|
|
|
#endif // TIM_EXPERIMENTAL_TRACE_TRACER_H_
|