/*////////////////////////////////////////////////////////////////////////////// // 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 #include "Macros.h" #include "Types.h" #include "Mpl.h" #include "SmartPointer.h" #include /** * @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 &ad, boost::any &val) {} }; template < typename T > struct AnyCastAdapter : AnyCastAdapterBase { void operator()(SmartPointer &ad, boost::any &val) { ad->operator()(boost::any_cast(val)); } }; struct DItem { DItem(){} template DItem(std::string str, T &t) : m_adapter(new AnyCastAdapter()), m_name(str), m_value(t) { } SmartPointer 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 Adapter; typedef detail::DebugAdapter::DItem DItem; public: template 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 m_v; std::vector m_a; }; } // uLib #endif // DEBUG_H