217 lines
6.0 KiB
C++
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
|