Program Listing for File AbstractSimRunner.h

Return to documentation for file (include/flamegpu/simulation/detail/AbstractSimRunner.h)

#ifndef INCLUDE_FLAMEGPU_SIMULATION_DETAIL_ABSTRACTSIMRUNNER_H_
#define INCLUDE_FLAMEGPU_SIMULATION_DETAIL_ABSTRACTSIMRUNNER_H_

#include <thread>
#include <mutex>
#include <queue>
#include <condition_variable>
#include <vector>
#include <map>
#include <memory>

#ifdef FLAMEGPU_ENABLE_MPI
#include <mpi.h>
#endif

#include "flamegpu/defines.h"
#include "flamegpu/simulation/LogFrame.h"

namespace flamegpu {
struct ModelData;
class LoggingConfig;
class StepLoggingConfig;
class RunPlanVector;
class CUDAEnsemble;
namespace detail {
class AbstractSimRunner {
    friend class flamegpu::CUDAEnsemble;
    void start();

 public:
    struct ErrorDetail {
        unsigned int run_id;
        unsigned int device_id;
        unsigned int runner_id;
        char exception_string[1024];
    };
#ifdef FLAMEGPU_ENABLE_MPI
    static MPI_Datatype createErrorDetailMPIDatatype() {
        static MPI_Datatype rtn = MPI_DATATYPE_NULL;
        if (rtn == MPI_DATATYPE_NULL) {
            ErrorDetail t;
            constexpr int count = 4;
            constexpr int array_of_blocklengths[count] = {1, 1, 1, sizeof(ErrorDetail::exception_string)};
            const char* t_ptr = reinterpret_cast<char*>(&t);
            const MPI_Aint array_of_displacements[count] = { reinterpret_cast<char*>(&t.run_id) - t_ptr,
                                                             reinterpret_cast<char*>(&t.device_id) - t_ptr,
                                                             reinterpret_cast<char*>(&t.runner_id) - t_ptr,
                                                             reinterpret_cast<char*>(&t.exception_string) - t_ptr };
            const MPI_Datatype array_of_types[count] = {MPI_UNSIGNED, MPI_UNSIGNED, MPI_UNSIGNED, MPI_CHAR};
            MPI_Type_create_struct(count, array_of_blocklengths, array_of_displacements, array_of_types, &rtn);
            MPI_Type_commit(&rtn);
        }
        return rtn;
    }
#endif

    AbstractSimRunner(const std::shared_ptr<const ModelData> _model,
        std::atomic<unsigned int> &_err_ct,
        std::atomic<unsigned int> &_next_run,
        const RunPlanVector &_plans,
        std::shared_ptr<const StepLoggingConfig> _step_log_config,
        std::shared_ptr<const LoggingConfig> _exit_log_config,
        int _device_id,
        unsigned int _runner_id,
        flamegpu::Verbosity _verbosity,
        std::map<unsigned int, RunLog> &run_logs,
        std::queue<unsigned int> &log_export_queue,
        std::mutex &log_export_queue_mutex,
        std::condition_variable &log_export_queue_cdn,
        std::vector<ErrorDetail> &err_detail,
        unsigned int _total_runners,
        bool _isSWIG);
    virtual ~AbstractSimRunner() {}
    virtual void main() = 0;
    void join();

 protected:
    void runSimulation(int plan_id);
    std::thread thread;
    const std::shared_ptr<const ModelData> model;
    const int device_id;
    const unsigned int runner_id;
    const unsigned int total_runners;
    const flamegpu::Verbosity verbosity;
    // External references
    std::atomic<unsigned int> &err_ct;
    std::atomic<unsigned int> &next_run;
    const RunPlanVector &plans;
    const std::shared_ptr<const StepLoggingConfig> step_log_config;
    const std::shared_ptr<const LoggingConfig> exit_log_config;
    std::map<unsigned int, RunLog> &run_logs;
    std::queue<unsigned int> &log_export_queue;
    std::mutex &log_export_queue_mutex;
    std::condition_variable &log_export_queue_cdn;
    std::vector<ErrorDetail>& err_detail;
    const bool isSWIG;
};

}  // namespace detail
}  // namespace flamegpu

#endif  // INCLUDE_FLAMEGPU_SIMULATION_DETAIL_ABSTRACTSIMRUNNER_H_