73#include <unordered_map>
107 throw std::runtime_error(
"cstats.destroyed() called with unknown "
108 "instance; potential double-destruction "
109 "or a missing cstats.created()");
115#if defined(PYPY_VERSION)
116 PyObject *
globals = PyEval_GetGlobals();
117 PyObject *result = PyRun_String(
"import gc\n"
123 if (result ==
nullptr)
124 throw py::error_already_set();
127 py::module_::import(
"gc").attr(
"collect")();
144 template <
typename T,
typename... Tmore>
146 std::ostringstream oss;
155 for (
const auto &v :
_values) {
156 l.append(py::cast(v));
164 static std::unordered_map<std::type_index, ConstructorStats> all_cstats;
165 return all_cstats[
type];
169 template <
typename T>
171#if defined(PYPY_VERSION)
174 return get(
typeid(T));
179 auto &
internals = py::detail::get_internals();
180 const std::type_index *t1 =
nullptr, *t2 =
nullptr;
193 }
catch (
const std::out_of_range &) {
196 throw std::runtime_error(
"Unknown class passed to ConstructorStats::get()");
198 auto &cs1 =
get(*t1);
202 auto &cs2 =
get(*t2);
203 int cs1_total = cs1.default_constructions + cs1.copy_constructions
204 + cs1.move_constructions + (int) cs1._values.size();
205 int cs2_total = cs2.default_constructions + cs2.copy_constructions
206 + cs2.move_constructions + (int) cs2._values.size();
207 if (cs2_total > cs1_total) {
220 ConstructorStats::get<T>().copy_created(inst);
224 ConstructorStats::get<T>().move_created(inst);
226template <
class T,
typename... Values>
228 auto &cst = ConstructorStats::get<T>();
229 cst.copy_assignments++;
230 cst.value(std::forward<Values>(values)...);
232template <
class T,
typename... Values>
234 auto &cst = ConstructorStats::get<T>();
235 cst.move_assignments++;
236 cst.value(std::forward<Values>(values)...);
238template <
class T,
typename... Values>
240 auto &cst = ConstructorStats::get<T>();
241 cst.default_created(inst);
242 cst.value(std::forward<Values>(values)...);
244template <
class T,
typename... Values>
246 auto &cst = ConstructorStats::get<T>();
248 cst.value(std::forward<Values>(values)...);
250template <
class T,
typename... Values>
252 ConstructorStats::get<T>().destroyed(inst);
254template <
class T,
typename... Values>
256 ConstructorStats::get<T>().value(std::forward<Values>(values)...);
263 return "{:#x}"_s.format(
reinterpret_cast<std::uintptr_t
>(p));
267 return std::forward<T>(x);
270template <
class T,
typename... Output>
281template <
class T,
typename... Values>
283 Values &&...values) {
287template <
class T,
typename... Values>
289 Values &&...values) {
293template <
class T,
typename... Values>
298template <
class T,
typename... Values>
303template <
class T,
typename... Values>
308template <
class T,
typename... Values>
313template <
class T,
typename... Values>
318template <
class T,
typename... Values>
void value(const T &v, Tmore &&...args)
std::list< std::string > _values
void copy_created(void *inst)
int default_constructions
void move_created(void *inst)
static ConstructorStats & get()
void destroyed(void *inst)
std::unordered_map< void *, int > _instances
void default_created(void *inst)
static ConstructorStats & get(std::type_index type)
static ConstructorStats & get(py::object class_)
dict globals()
Return a dictionary representing the global variables in the current execution frame,...
void print_default_created(T *inst, Values &&...values)
void track_destroyed(T *inst)
void track_values(T *, Values &&...values)
void track_move_assigned(T *, Values &&...values)
void print_constr_details(T *inst, const std::string &action, Output &&...output)
void print_copy_created(T *inst, Values &&...values)
void print_copy_assigned(T *inst, Values &&...values)
void track_created(T *inst, Values &&...values)
void print_created(T *inst, Values &&...values)
void track_move_created(T *inst)
void print_values(T *inst, Values &&...values)
const char * format_ptrs(const char *p)
Don't cast pointers to Python, print them as strings.
void track_copy_created(T *inst)
void track_copy_assigned(T *, Values &&...values)
void print_destroyed(T *inst, Values &&...values)
void print_move_assigned(T *inst, Values &&...values)
void track_default_created(T *inst, Values &&...values)
void print_move_created(T *inst, Values &&...values)
Internal data structure used to track registered instances and types.
type_map< type_info * > registered_types_cpp
std::unordered_map< PyTypeObject *, std::vector< type_info * > > registered_types_py
Additional type information which does not fit into the PyTypeObject.