Program Listing for File SimLogger.cu

Return to documentation for file (src/flamegpu/simulation/detail/SimLogger.cu)

#include "flamegpu/simulation/detail/SimLogger.h"

#include <filesystem>
#include <string>
#include <map>
#include <queue>
#include <memory>

#include "flamegpu/io/LoggerFactory.h"
#include "flamegpu/simulation/RunPlanVector.h"

#ifdef _MSC_VER
#include <windows.h>
#else
#include <pthread.h>
#endif

namespace flamegpu {
namespace detail {

SimLogger::SimLogger(const std::map<unsigned int, RunLog> &_run_logs,
        const RunPlanVector &_run_plans,
        const std::string &_out_directory,
        const std::string &_out_format,
        std::queue<unsigned int> &_log_export_queue,
        std::mutex &_log_export_queue_mutex,
        std::condition_variable &_log_export_queue_cdn,
        bool _export_step,
        bool _export_exit,
        bool _export_step_time,
        bool _export_exit_time)
    : run_logs(_run_logs)
    , run_plans(_run_plans)
    , out_directory(_out_directory)
    , out_format(_out_format)
    , log_export_queue(_log_export_queue)
    , log_export_queue_mutex(_log_export_queue_mutex)
    , log_export_queue_cdn(_log_export_queue_cdn)
    , export_step(_export_step)
    , export_exit(_export_exit)
    , export_step_time(_export_step_time)
    , export_exit_time(_export_exit_time) {
    this->thread = std::thread(&SimLogger::start, this);
    // Attempt to name the thread
#ifdef _MSC_VER
    std::wstringstream thread_name;
    thread_name << L"SimLogger";
    // HRESULT hr =
    SetThreadDescription(this->thread.native_handle(), thread_name.str().c_str());
    // if (FAILED(hr)) {
    //     fprintf(stderr, "Failed to name thread 'SimLogger'\n");
    // }
#else
    std::stringstream thread_name;
    thread_name << "SimLogger";
    // int hr =
    pthread_setname_np(this->thread.native_handle(), thread_name.str().c_str());
    // if (hr) {
    //     fprintf(stderr, "Failed to name thread 'SimLogger'\n");
    // }
#endif
}
void SimLogger::start() {
    const std::filesystem::path p_out_directory = out_directory;
    unsigned int logs_processed = 0;
    while (logs_processed < run_plans.size()) {
        std::unique_lock<std::mutex> lock(log_export_queue_mutex);
        log_export_queue_cdn.wait(lock, [this]{ return !log_export_queue.empty(); });
        do {
            // Pop item to be logged from queue
            const unsigned int target_log = log_export_queue.front();
            log_export_queue.pop();
            lock.unlock();

            // Check item isn't telling us to exit early
            if (target_log == UINT_MAX) {
                logs_processed = UINT_MAX;
                break;
            }
            // Log items
            if (export_exit) {
                const std::filesystem::path exit_path = p_out_directory / std::filesystem::path(run_plans[target_log].getOutputSubdirectory()) / std::filesystem::path("exit." + out_format);
                const auto exit_logger = io::LoggerFactory::createLogger(exit_path.generic_string(), false, false);
                exit_logger->log(run_logs.at(target_log), run_plans[target_log], false, true, false, export_exit_time);
            }
            if (export_step) {
                const std::filesystem::path step_path = p_out_directory/std::filesystem::path(run_plans[target_log].getOutputSubdirectory())/std::filesystem::path(std::to_string(target_log)+"."+out_format);
                const auto step_logger = io::LoggerFactory::createLogger(step_path.generic_string(), false, true);
                step_logger->log(run_logs.at(target_log), run_plans[target_log], true, false, export_step_time, false);
            }
            // Continue
            ++logs_processed;
            lock.lock();
        } while (!log_export_queue.empty());
    }
}

}  // namespace detail
}  // namespace flamegpu