|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define TROMPELOEIL_PARAMS(num) TROMPELOEIL_CONCAT(TROMPELOEIL_PARAMS, num) |
|
|
#define TROMPELOEIL_PARAMS(num) TROMPELOEIL_CONCAT(TROMPELOEIL_PARAMS, num) |
|
|
|
|
|
|
|
|
|
|
|
#if defined(__cxx_rtti) || defined(__GXX_RTTI) || defined(_CPPRTTI) |
|
|
|
|
|
# define TROMPELOEIL_TYPE_ID_NAME(x) typeid(x).name() |
|
|
|
|
|
#else |
|
|
|
|
|
# define TROMPELOEIL_TYPE_ID_NAME(x) "object" |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
#if (TROMPELOEIL_CPLUSPLUS == 201103L) |
|
|
#if (TROMPELOEIL_CPLUSPLUS == 201103L) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class specialized; |
|
|
class specialized; |
|
|
|
|
|
|
|
|
namespace { |
|
|
|
|
|
inline |
|
|
|
|
|
const std::shared_ptr<std::recursive_mutex>& |
|
|
|
|
|
get_mutex_obj() |
|
|
|
|
|
{ |
|
|
|
|
|
static auto obj = std::make_shared<std::recursive_mutex>(); |
|
|
|
|
|
return obj; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
auto mutex_holder = get_mutex_obj(); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
template <typename T> |
|
|
|
|
|
using aligned_storage_for = |
|
|
|
|
|
typename std::aligned_storage<sizeof(T), alignof(T)>::type; |
|
|
|
|
|
|
|
|
template <typename T = void> |
|
|
template <typename T = void> |
|
|
std::unique_lock<std::recursive_mutex> get_lock() |
|
|
std::unique_lock<std::recursive_mutex> get_lock() |
|
|
{ |
|
|
{ |
|
|
return std::unique_lock<std::recursive_mutex>{ *get_mutex_obj() }; |
|
|
|
|
|
|
|
|
// Ugly hack for lifetime of mutex. The statically allocated |
|
|
|
|
|
// recursive_mutex is intentionally leaked, to ensure that the |
|
|
|
|
|
// mutex is available and valid even if the last use is from |
|
|
|
|
|
// the destructor of a global object in a translation unit |
|
|
|
|
|
// without #include <trompeloeil.hpp> |
|
|
|
|
|
|
|
|
|
|
|
static aligned_storage_for<std::recursive_mutex> buffer; |
|
|
|
|
|
static auto mutex = new (&buffer) std::recursive_mutex; |
|
|
|
|
|
return std::unique_lock<std::recursive_mutex>{*mutex}; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <size_t N, typename T> |
|
|
template <size_t N, typename T> |
|
|
|
|
|
|
|
|
, exp_loc(loc) |
|
|
, exp_loc(loc) |
|
|
, seq(*i.second) |
|
|
, seq(*i.second) |
|
|
{ |
|
|
{ |
|
|
|
|
|
auto lock = get_lock(); |
|
|
seq.add_last(this); |
|
|
seq.add_last(this); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
std::ostringstream os; |
|
|
std::ostringstream os; |
|
|
os << "Unexpected destruction of " |
|
|
os << "Unexpected destruction of " |
|
|
<< typeid(T).name() << "@" << this << '\n'; |
|
|
|
|
|
|
|
|
<< TROMPELOEIL_TYPE_ID_NAME(T) << "@" << this << '\n'; |
|
|
send_report<specialized>(severity::nonfatal, |
|
|
send_report<specialized>(severity::nonfatal, |
|
|
location{}, |
|
|
location{}, |
|
|
os.str()); |
|
|
os.str()); |