Initial commit of source code

This commit is contained in:
Sylvain Schneider
2026-03-12 16:32:03 +01:00
parent b5d0fef4d9
commit f25c5789ea
46 changed files with 27732 additions and 0 deletions

45
src/core/coreManager.cpp Normal file
View File

@@ -0,0 +1,45 @@
#include "coreManager.h"
using namespace std;
using namespace core;
//--------------------------------------------------------------
/* Default constructor */
CoreManager::CoreManager()
{
init();
}
//--------------------------------------------------------------
/* Default destructor */
CoreManager::~CoreManager()
{
release();
}
//--------------------------------------------------------------
/* Get a reference to the application bus */
dBus::Bus &CoreManager::getBus() const
{
return *m_bus;
}
//--------------------------------------------------------------
/* Initialize the core manager (e.g., set up the bus, etc.) */
void CoreManager::init()
{
// Initialize the application bus
m_bus = make_unique<dBus::Bus>();
// Initialize other subsystems (e.g., logger, etc.)
m_logger = make_unique<logger::Logger>(*m_bus);
m_requirementManager = make_unique<requirementManager::RequirementManager>(*m_bus);
}
//--------------------------------------------------------------
/* Release resources used by the core manager (e.g., clean up the bus, etc.) */
void CoreManager::release()
{
// Clean up other subsystems (e.g., logger, etc.)
m_requirementManager.reset();
m_logger.reset();
// Clean up the application bus
m_bus.reset();
}
//--------------------------------------------------------------

35
src/core/coreManager.h Normal file
View File

@@ -0,0 +1,35 @@
#pragma once
#include "logger/logger.h"
#include "requirementManager/requirementManager.h"
#include <dBus/dBus.h>
#include <memory>
namespace core
{
//--------------------------------------------------------------
class CoreManager
{
public:
CoreManager(); // Default constructor
virtual ~CoreManager(); // Default destructor
CoreManager(const CoreManager &obj) = delete; // Copy constructor
CoreManager(CoreManager &&obj) noexcept = delete; // Move constructor
CoreManager &operator=(const CoreManager &obj) = delete; // Copy assignment operator
CoreManager &operator=(CoreManager &&obj) noexcept = delete; // Move assignment operator
[[nodiscard]] dBus::Bus &getBus() const; // Get a reference to the application bus
protected:
std::unique_ptr<dBus::Bus> m_bus; // Application data bus
std::unique_ptr<logger::Logger> m_logger; // Application logger system
std::unique_ptr<requirementManager::RequirementManager> m_requirementManager; // Requirement manager system
private:
void init(); // Initialize the core manager (e.g., set up the bus, etc.)
void release(); // Release resources used by the core manager (e.g., clean up the bus, etc.)
};
//--------------------------------------------------------------
} // namespace core

172
src/core/logger/logger.cpp Normal file
View File

@@ -0,0 +1,172 @@
#include "logger.h"
#include <iostream>
#include <syncstream>
using namespace std;
using namespace core::logger;
//--------------------------------------------------------------
/* Constructor */
Logger::Logger(dBus::Bus &bus)
: Node(bus)
{
// Initialize the log printing loop
runPrintingLoop();
// Initialize the bus listener thread
runBusListener();
}
//--------------------------------------------------------------
/* Default destructor */
Logger::~Logger()
{
// Stop the bus listener thread if it's running
stopBusListener();
// Stop the log printing loop if it's running
stopPrintingLoop();
}
//--------------------------------------------------------------
/* Run the loop that periodically prints log entries to the console */
void Logger::runPrintingLoop()
{
/* Start the printing thread to periodically print log entries to the console.
* The thread will continuously wait for messages and process them until a stop is requested */
// clang-format off
m_printingThread = std::jthread([this](const std::stop_token &stopToken)
{
while (!stopToken.stop_requested())
{
// Sleep for a short duration to avoid busy waiting and reduce CPU usage
this_thread::sleep_for(100ms);
// Print the log entries after processing the message
if (m_logEntries.timer.isElapsed(LOG_PRINT_INTERVAL, true))
printLogEntries();
}
});
// clang-format on
}
//--------------------------------------------------------------
/* Stop the log printing loop */
void Logger::stopPrintingLoop()
{
// Stop printing thread loop
m_printingThread.request_stop();
// Despite a jthread will automatically join in its destructor, we
// can explicitly join here to ensure that the thread has finished
// executing before the Logger object is destroyed.
// This is especially important if the thread is still running and
// may access resources that are being cleaned up in the destructor.
// By joining the thread, we can ensure a clean shutdown of the Logger
// and avoid potential issues with dangling threads or accessing invalid resources.
if (m_printingThread.joinable())
m_printingThread.join();
}
//--------------------------------------------------------------
/* Print the log entries to the console */
void Logger::printLogEntries()
{
// Move the log entries to a local variable and clear the
// original vector to minimize the time the mutex is locked
std::vector<std::string> logEntries;
{
scoped_lock lock(m_logEntries.mtx);
logEntries = std::move(m_logEntries.entries);
m_logEntries.entries.clear();
}
for (const auto &entry : logEntries)
{
// Use osyncstream to ensure thread-safe output to the console
std::osyncstream syncOut(std::cout);
syncOut << entry << std::endl;
}
}
//--------------------------------------------------------------
/* Process a log message received from the bus */
void Logger::processUserMessage(const LogMessage_ptr &logMessage)
{
// Sanity check
if (!logMessage)
return;
// Add the log entry to the vector of log entries
std::scoped_lock lock(m_logEntries.mtx);
m_logEntries.entries.push_back(logMessage->toString());
}
//--------------------------------------------------------------
/* Process a system log message received from the bus */
void Logger::processSystemMessage(const std::string &logMessage)
{
// Sanity check
if (logMessage.empty())
return;
// Add the log entry to the vector of log entries
std::scoped_lock lock(m_logEntries.mtx);
m_logEntries.entries.push_back(logMessage);
}
//--------------------------------------------------------------
/* Run the bus listener thread */
void Logger::runBusListener()
{
// Subscribe to the bus in broadcast mode to receive all messages posted to the bus
m_bus.subscribeToBroadcast(this);
/* Start the bus listener thread to process incoming messages related to requirements.
* The thread will continuously wait for messages and process them until a stop is requested */
// clang-format off
m_busListenerThread = std::jthread([this](const std::stop_token &stopToken)
{
while (!stopToken.stop_requested())
{
// Wait for a message to be received
syncWaitForMessage();
// Process all received messages
while (getMessageCount() > 0)
{
auto message = popNextMessage();
if (message)
processMessageBus(message);
}
}
});
// clang-format on
}
//--------------------------------------------------------------
/* Stop the bus listener thread */
void Logger::stopBusListener()
{
// Stop event thread loop
m_busListenerThread.request_stop();
// Wake up event thread if waiting
notifyMessageQueue();
// Join the bus listener thread to ensure it has finished
// executing before the Logger object is destroyed
if (m_busListenerThread.joinable())
m_busListenerThread.join();
}
//--------------------------------------------------------------
/* Process a message received from the bus */
void Logger::processMessageBus(const Message_ptr &message)
{
// Check the message type and process accordingly
const auto messageType = message->getMessageTypeID();
if (messageType == dBus::makeID("log.message"))
{
// Process log message
processUserMessage(message->as<dBus::EventMessage<api::log::LogMessage>>());
}
else
{
// Process system log message (for any other message type, we will log it as a system message)
processSystemMessage(message->toString());
}
}
//--------------------------------------------------------------

53
src/core/logger/logger.h Normal file
View File

@@ -0,0 +1,53 @@
#pragma once
#include <dBus/api/log.h>
#include <dBus/dBus.h>
#include <mutex>
#include <sdi_toolBox/dateTime/timer.h>
#include <thread>
namespace core::logger
{
//--------------------------------------------------------------
class Logger : public dBus::Node
{
static constexpr auto LOG_PRINT_INTERVAL = std::chrono::seconds{ 1 };
public:
Logger() = delete; // Default constructor
virtual ~Logger(); // Default destructor
Logger(const Logger &obj) = delete; // Copy constructor
Logger(Logger &&obj) noexcept = delete; // Move constructor
Logger &operator=(const Logger &obj) = delete; // Copy assignment operator
Logger &operator=(Logger &&obj) noexcept = delete; // Move assignment operator
explicit Logger(dBus::Bus &bus); // Constructor
protected:
struct
{
std::mutex mtx; // Mutex to protect access to the log entries vector
sdi_toolBox::dateTime::Timer timer; // Timer to control the frequency of log printing
std::vector<std::string> entries; // Vector to store log entries received from the bus
} m_logEntries;
private:
void runPrintingLoop(); // Run the loop that periodically prints log entries to the console
void stopPrintingLoop(); // Stop the log printing loop
void printLogEntries(); // Print the log entries to the console
std::jthread m_printingThread; // Thread for printing log entries to the console
// Logger management
using LogMessage_ptr = std::shared_ptr<dBus::EventMessage<api::log::LogMessage>>;
void processUserMessage(const LogMessage_ptr &logMessage); // Process a log message received from the bus
void processSystemMessage(const std::string &logMessage); // Process a system log message received from the bus
// dBus management
using Message_ptr = std::shared_ptr<dBus::Message>;
void runBusListener(); // Run the bus listener thread
void stopBusListener(); // Stop the bus listener thread
void processMessageBus(const Message_ptr &message); // Process a message received from the bus
std::jthread m_busListenerThread; // Thread for listening to bus messages related to requirements
};
//--------------------------------------------------------------
} // namespace core::logger

View File

@@ -0,0 +1,89 @@
#include "requirementManager.h"
using namespace std;
using namespace core::requirementManager;
//--------------------------------------------------------------
/* Constructor */
RequirementManager::RequirementManager(dBus::Bus &bus)
: Node(bus)
{
// Initialize the bus listener thread
runBusListener();
}
//--------------------------------------------------------------
/* Default destructor */
RequirementManager::~RequirementManager()
{
// Stop the bus listener thread if it's running
stopBusListener();
}
//--------------------------------------------------------------
/* Get the root requirement */
api::requirement::Requirement &RequirementManager::getRootRequirement()
{
return m_rootRequirement;
}
//--------------------------------------------------------------
/* Run the bus listener thread */
void RequirementManager::runBusListener()
{
// Subscribe to the bus for messages related to log entries
subscribe(dBus::makeID("requirement.file.operation"));
/* Start the bus listener thread to process incoming messages related to requirements.
* The thread will continuously wait for messages and process them until a stop is requested. */
// clang-format off
m_busListenerThread = std::jthread([this](const std::stop_token &stopToken)
{
while (!stopToken.stop_requested())
{
// Wait for a message to be received
syncWaitForMessage();
// Process all received messages
while (getMessageCount() > 0)
{
auto message = popNextMessage();
if (message)
processMessageBus(message);
}
}
});
// clang-format on
}
//--------------------------------------------------------------
/* Stop the bus listener thread */
void RequirementManager::stopBusListener()
{
// Stop event thread loop
m_busListenerThread.request_stop();
// Wake up event thread if waiting
notifyMessageQueue();
/* No need to join the thread explicitly as std::jthread will
* automatically join in its destructor.
* Subscribe to the bus will be automatically cleaned up in the
* Node destructor. */
}
//--------------------------------------------------------------
/* Process a message received from the bus */
void RequirementManager::processMessageBus(const Message_ptr &message)
{
const auto messageType = message->getMessageTypeID();
switch (messageType)
{
case dBus::makeID("requirement.file.operation"):
{
// Process file operation request
const auto requestMessage = message->as<dBus::RequestMessage<api::requirement::FileOperationEvent, void>>();
if (!requestMessage)
break;
requestMessage->responsePromise.set_exception(std::make_exception_ptr(std::runtime_error("Failed to process file operation request")));
break;
}
}
}
//--------------------------------------------------------------

View File

@@ -0,0 +1,38 @@
#pragma once
#include <api/requirement.h>
#include <dBus/dBus.h>
#include <thread>
namespace core::requirementManager
{
//--------------------------------------------------------------
class RequirementManager : public dBus::Node
{
public:
RequirementManager() = delete; // Default constructor
virtual ~RequirementManager(); // Default destructor
RequirementManager(const RequirementManager &obj) = delete; // Copy constructor
RequirementManager(RequirementManager &&obj) noexcept = delete; // Move constructor
RequirementManager &operator=(const RequirementManager &obj) = delete; // Copy assignment operator
RequirementManager &operator=(RequirementManager &&obj) noexcept = delete; // Move assignment operator
explicit RequirementManager(dBus::Bus &bus); // Constructor
protected:
// dBus::Bus &m_bus; // Reference to the application bus
api::requirement::Requirement m_rootRequirement;
private:
api::requirement::Requirement &getRootRequirement(); // Get the root requirement
// dBus management
using Message_ptr = std::shared_ptr<dBus::Message>;
void runBusListener(); // Run the bus listener thread
void stopBusListener(); // Stop the bus listener thread
void processMessageBus(const Message_ptr &message); // Process a message received from the bus
std::jthread m_busListenerThread; // Thread for listening to bus messages related to requirements
};
//--------------------------------------------------------------
} // namespace core::requirementManager