mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-01 12:46:12 +00:00
aux/util: Add variable tracking code
This commit is contained in:
parent
58008d2ff1
commit
a9e88f3f20
|
@ -47,6 +47,8 @@ set(UTIL_SOURCE_FILES
|
||||||
util/u_sink_queue.c
|
util/u_sink_queue.c
|
||||||
util/u_time.cpp
|
util/u_time.cpp
|
||||||
util/u_time.h
|
util/u_time.h
|
||||||
|
util/u_var.cpp
|
||||||
|
util/u_var.h
|
||||||
)
|
)
|
||||||
|
|
||||||
# Common includes
|
# Common includes
|
||||||
|
|
243
src/xrt/auxiliary/util/u_var.cpp
Normal file
243
src/xrt/auxiliary/util/u_var.cpp
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
// Copyright 2019, Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief Variable tracking code.
|
||||||
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||||
|
* @ingroup aux_util
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "util/u_var.h"
|
||||||
|
#include "util/u_time.h"
|
||||||
|
#include "util/u_misc.h"
|
||||||
|
#include "util/u_debug.h"
|
||||||
|
#include "util/u_device.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Enums, Classes and Defines.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
class Var
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string name;
|
||||||
|
u_var_kind kind;
|
||||||
|
union {
|
||||||
|
void *ptr;
|
||||||
|
struct xrt_colour_rgb_u8 *rgb_u8;
|
||||||
|
struct xrt_colour_rgb_f32 *rgb_f32;
|
||||||
|
bool *boolean;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class Obj
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string name = {};
|
||||||
|
std::vector<Var> vars = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
class Tracker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::unordered_map<std::string, size_t> counters = {};
|
||||||
|
std::unordered_map<ptrdiff_t, Obj> map = {};
|
||||||
|
bool on;
|
||||||
|
bool tested;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int
|
||||||
|
getNumber(std::string name)
|
||||||
|
{
|
||||||
|
auto s = counters.find(name);
|
||||||
|
int count = (s != counters.end() ? s->second : 0) + 1;
|
||||||
|
counters[name] = count;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static class Tracker tracker;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Helper functions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool
|
||||||
|
get_on()
|
||||||
|
{
|
||||||
|
if (tracker.tested) {
|
||||||
|
return tracker.on;
|
||||||
|
}
|
||||||
|
tracker.on = debug_get_bool_option("XRT_TRACK_VARIABLES", false);
|
||||||
|
tracker.tested = true;
|
||||||
|
|
||||||
|
return tracker.on;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_var(void *root, void *ptr, u_var_kind kind, const char *c_name)
|
||||||
|
{
|
||||||
|
auto s = tracker.map.find((ptrdiff_t)root);
|
||||||
|
if (s == tracker.map.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Var var;
|
||||||
|
var.name = std::string(c_name);
|
||||||
|
var.kind = kind;
|
||||||
|
var.ptr = ptr;
|
||||||
|
|
||||||
|
s->second.vars.push_back(var);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Exported functions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
u_var_force_on(void)
|
||||||
|
{
|
||||||
|
tracker.on = true;
|
||||||
|
tracker.tested = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
u_var_add_root(void *root, const char *c_name, bool number)
|
||||||
|
{
|
||||||
|
if (!get_on()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto name = std::string(c_name);
|
||||||
|
|
||||||
|
if (number) {
|
||||||
|
int count = tracker.getNumber(name);
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << name << " #" << count;
|
||||||
|
name = ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &obj = tracker.map[(ptrdiff_t)root] = Obj();
|
||||||
|
obj.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
u_var_remove_root(void *root)
|
||||||
|
{
|
||||||
|
if (!get_on()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto s = tracker.map.find((ptrdiff_t)root);
|
||||||
|
if (s == tracker.map.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracker.map.erase(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
u_var_add_bool(void *obj, bool *ptr, const char *c_name)
|
||||||
|
{
|
||||||
|
if (!get_on()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_var(obj, ptr, U_VAR_KIND_BOOL, c_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
u_var_add_u8(void *obj, uint8_t *ptr, const char *c_name)
|
||||||
|
{
|
||||||
|
if (!get_on()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_var(obj, ptr, U_VAR_KIND_U8, c_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
u_var_add_u32(void *obj, uint32_t *ptr, const char *c_name)
|
||||||
|
{
|
||||||
|
if (!get_on()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_var(obj, ptr, U_VAR_KIND_U32, c_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
u_var_add_rgb_u8(void *obj, struct xrt_colour_rgb_u8 *ptr, const char *c_name)
|
||||||
|
{
|
||||||
|
if (!get_on()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_var(obj, ptr, U_VAR_KIND_RGB_U8, c_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
u_var_add_rgb_f32(void *obj, struct xrt_colour_rgb_f32 *ptr, const char *c_name)
|
||||||
|
{
|
||||||
|
if (!get_on()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_var(obj, ptr, U_VAR_KIND_RGB_F32, c_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
u_var_add_text(void *obj, const char *ptr, const char *c_name)
|
||||||
|
{
|
||||||
|
if (!get_on()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_var(obj, (void *)ptr, U_VAR_KIND_TEXT, c_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
u_var_visit(u_var_root_cb enter,
|
||||||
|
u_var_root_cb exit,
|
||||||
|
u_var_elm_cb elem,
|
||||||
|
void *priv)
|
||||||
|
{
|
||||||
|
if (!get_on()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Obj *> tmp;
|
||||||
|
tmp.reserve(tracker.map.size());
|
||||||
|
|
||||||
|
for (auto &n : tracker.map) {
|
||||||
|
tmp.push_back(&n.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Obj *obj : tmp) {
|
||||||
|
enter(obj->name.c_str(), priv);
|
||||||
|
|
||||||
|
for (auto &var : obj->vars) {
|
||||||
|
elem(var.name.c_str(), (u_var_kind)var.kind, var.ptr,
|
||||||
|
priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(obj->name.c_str(), priv);
|
||||||
|
}
|
||||||
|
}
|
127
src/xrt/auxiliary/util/u_var.h
Normal file
127
src/xrt/auxiliary/util/u_var.h
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
// Copyright 2019, Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief Variable tracking code.
|
||||||
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||||
|
* @ingroup aux_util
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "xrt/xrt_defines.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @ingroup aux_util
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* What kind of variable is this tracking.
|
||||||
|
*/
|
||||||
|
enum u_var_kind
|
||||||
|
{
|
||||||
|
U_VAR_KIND_BOOL,
|
||||||
|
U_VAR_KIND_U8,
|
||||||
|
U_VAR_KIND_U32,
|
||||||
|
U_VAR_KIND_RGB_U8,
|
||||||
|
U_VAR_KIND_RGB_F32,
|
||||||
|
U_VAR_KIND_TEXT,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Callback for entering and leaving root nodes.
|
||||||
|
*/
|
||||||
|
typedef void (*u_var_root_cb)(const char *, void *);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Callback on each variable a root node has.
|
||||||
|
*/
|
||||||
|
typedef void (*u_var_elm_cb)(const char *, enum u_var_kind, void *, void *);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Add a named root object, the u_var subsystem is completely none-invasive
|
||||||
|
* to the object it's tracking. The root pointer is used as a entry into a
|
||||||
|
* hashmap of hidden objecrs. When not active all calls are stubs and have no
|
||||||
|
* side-effects.
|
||||||
|
*
|
||||||
|
* This is intended only for debugging and is turned off by default, as this all
|
||||||
|
* very very unsafe. It is just pointers straight into objects, completely
|
||||||
|
* ignores ownership or any safe practices.
|
||||||
|
*
|
||||||
|
* If it's stupid, but it works, it ain't stupid.
|
||||||
|
*
|
||||||
|
* ```c
|
||||||
|
* // On create
|
||||||
|
* u_var_add_root((void*)psmv, "PS Move Controller", psmv_var_updated_callback);
|
||||||
|
* u_var_add_rgb_u8((void*)psmv, &psmv->led_color, "LED");
|
||||||
|
* u_var_add_bool((void*)psmv, &psmv->print_spew, "Spew");
|
||||||
|
* u_var_add_bool((void*)psmv, &psmv->print_debug, "Debug");
|
||||||
|
*
|
||||||
|
* // On destroy, only need to destroy the root object.
|
||||||
|
* u_var_remove_root((void*)psmv);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @ingroup aux_util
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
u_var_add_root(void *, const char *, bool);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Remove the root node.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
u_var_remove_root(void *);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Visit all root nodes and their variables.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
u_var_visit(u_var_root_cb enter,
|
||||||
|
u_var_root_cb exit,
|
||||||
|
u_var_elm_cb e_cb,
|
||||||
|
void *priv);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* This forces the variable tracking code to on, it is disabled by default.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
u_var_force_on(void);
|
||||||
|
|
||||||
|
//! Add a variable to track on a root node, does not claim ownership.
|
||||||
|
void
|
||||||
|
u_var_add_rgb_u8(void *, struct xrt_colour_rgb_u8 *, const char *);
|
||||||
|
|
||||||
|
//! Add a variable to track on a root node, does not claim ownership.
|
||||||
|
void
|
||||||
|
u_var_add_rgb_f32(void *, struct xrt_colour_rgb_f32 *, const char *);
|
||||||
|
|
||||||
|
//! Add a variable to track on a root node, does not claim ownership.
|
||||||
|
void
|
||||||
|
u_var_add_u8(void *, uint8_t *, const char *);
|
||||||
|
|
||||||
|
//! Add a variable to track on a root node, does not claim ownership.
|
||||||
|
void
|
||||||
|
u_var_add_u32(void *, uint32_t *, const char *);
|
||||||
|
|
||||||
|
//! Add a variable to track on a root node, does not claim ownership.
|
||||||
|
void
|
||||||
|
u_var_add_bool(void *, bool *, const char *);
|
||||||
|
|
||||||
|
//! Add a variable to track on a root node, does not claim ownership.
|
||||||
|
void
|
||||||
|
u_var_add_text(void *, const char *, const char *);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Reference in a new issue