Files
uLib/src/Core/Debug.h

217 lines
6.0 KiB
C++

/*//////////////////////////////////////////////////////////////////////////////
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
All rights reserved
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
------------------------------------------------------------------
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
//////////////////////////////////////////////////////////////////////////////*/
#ifndef U_CORE_DEBUG_H
#define U_CORE_DEBUG_H
#include <vector>
#include "Macros.h"
#include "Types.h"
#include "Mpl.h"
#include "SmartPointer.h"
#include <boost/any.hpp>
/**
* @file Debug.h
* @brief Unified Debugging and Monitoring System for uLib.
*
* # Debug System Documentation
*
* The `Debug` system provides a flexible, adapter-based mechanism for monitoring
* and outputting internal variables and states without hardcoding output logic
* into core classes.
*
* ## Architecture
*
* The system follows an adapter pattern:
*
* - **`DebugAdapterInterface`**: The base interface for all output targets.
* Subclasses define how primitive types and strings are handled (e.g., printing
* to `std::cout`, writing to a log file, or updating a real-time UI widget).
*
* - **`Debug` Class**: The central registry. It stores:
* 1. A list of "Adapters" (`DebugAdapterInterface`).
* 2. A list of "Items" to monitor. Each item is a reference to a variable
* associated with a name.
*
* - **Type Safety**: Although variables are stored using `boost::any` (type erasure),
* the system automatically preserves the original type information via
* internal template adapters (`AnyCastAdapter`), ensuring that the correct
* overload of the adapter interface is called.
*
* ## Core Components
*
* | Component | Description |
* | :--- | :--- |
* | `Debug` | The main controller used to add adapters and register variables. |
* | `DebugAdapterInterface` | Virtual base for creating new output methods. |
* | `DebugAdapterText` | A simple built-in adapter for `std::ostream` output. |
*
* ## How to Use
*
* ### 1. Initialize the Debug Object
* ```cpp
* uLib::Debug dbg;
* ```
*
* ### 2. Add an Adapter
* ```cpp
* uLib::DebugAdapterText console(std::cout);
* dbg.AddAdapter(console);
* ```
*
* ### 3. Register Variables to Monitor
* Use the `operator()` to bind a variable by reference.
* ```cpp
* int frameCount = 0;
* std::string state = "Initializing";
* dbg("Frames", frameCount);
* dbg("Status", state);
* ```
*
* ### 4. Update
* Call `Update()` periodically (e.g., once per frame) to push the current
* values of all registered variables to all connected adapters.
* ```cpp
* while(running) {
* frameCount++;
* dbg.Update(); // This triggers the output
* }
* ```
*/
namespace uLib {
namespace detail {
struct DebugAdapterInterface {
virtual ~DebugAdapterInterface() {}
virtual void operator()(char val) {}
virtual void operator()(unsigned char val) {}
virtual void operator()(short val) {}
virtual void operator()(unsigned short val) {}
virtual void operator()(int val) {}
virtual void operator()(unsigned int val) {}
virtual void operator()(long val) {}
virtual void operator()(unsigned long val) {}
virtual void operator()(float val) {}
virtual void operator()(double val) {}
virtual void operator()(std::string val) {}
};
struct DebugAdapter {
struct AnyCastAdapterBase {
virtual ~AnyCastAdapterBase(){}
virtual void operator()(SmartPointer<DebugAdapterInterface> &ad, boost::any &val) {}
};
template < typename T >
struct AnyCastAdapter : AnyCastAdapterBase {
void operator()(SmartPointer<DebugAdapterInterface> &ad, boost::any &val) { ad->operator()(boost::any_cast<T>(val)); }
};
struct DItem {
DItem(){}
template <typename T> DItem(std::string str, T &t) :
m_adapter(new AnyCastAdapter<T>()),
m_name(str),
m_value(t) { }
SmartPointer<AnyCastAdapterBase> m_adapter;
std::string m_name;
boost::any m_value;
};
};
} // detail
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// text ADAPTER
class DebugAdapterText : public detail::DebugAdapterInterface {
std::ostream &m_out;
public:
DebugAdapterText(std::ostream &o) : m_out(o) {}
void operator()(int val) { m_out << "debug: " << val << "\n"; }
void operator()(std::string val) { m_out << "debug: " << val << "\n"; }
};
class Debug {
typedef detail::DebugAdapterInterface AdapterInterface;
typedef SmartPointer<detail::DebugAdapterInterface> Adapter;
typedef detail::DebugAdapter::DItem DItem;
public:
template <typename T> void operator() (std::string str, T &t) { m_v.push_back(DItem(str,t)); }
void AddAdapter(AdapterInterface &ad) { m_a.push_back(Adapter(ad)); }
void Update() {
for(Adapter &ad : m_a) {
for(DItem &item : m_v) {
item.m_adapter->operator()(ad, item.m_value);
}
}
}
private:
std::vector<DItem> m_v;
std::vector<Adapter> m_a;
};
} // uLib
#endif // DEBUG_H