actsim-cluster-agent/include/actsim_agent/task_interface.hpp

146 lines
4.8 KiB
C++

/*************************************************************************
*
* This file is part of the ACT library
*
* Copyright (c) 2024 Fabian Posch
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
**************************************************************************
*/
#ifndef __TASK_INTERFACE__
#define __TASK_INTERFACE__
#include <cstddef>
#include <queue>
#include <unordered_map>
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <vector>
#include "agent_artifact.hpp"
#include <chrono>
/**
* If you want to use this interface for different types, you only need to change it here.
* This can be any type, as long as it publicly derives form pl::Artifact.
*/
using InputType = DBSimConfigArtifact;
using OutputType = DBSimOutputArtifact;
#define NOTHING_AVAILABLE_SLEEP_TIME 500ms
class TaskInterface {
public:
TaskInterface(size_t buffer_size);
~TaskInterface();
void wait_for_fresh();
void wait_for_finished(size_t min_size);
void wait_for_buffer_consume();
void wait_for_cleanup_ready();
void wait_for_download_halt();
void wait_for_available();
void notify_cleanup_ready();
void notify_workers_program_halt();
void notify_download_halt();
void push_fresh(std::unique_ptr<InputType> task);
void push_fresh(std::vector<std::unique_ptr<InputType>>& tasks);
std::unique_ptr<InputType> pop_fresh(bool& empty);
void push_finished(std::unique_ptr<OutputType> task);
std::vector<std::unique_ptr<OutputType>> pop_finished(bool& empty);
size_t get_buffer_space();
/*
* Store a design entry locally
*/
bool increment_design(const db::uuid_t& id);
void decrement_design(const db::uuid_t& id);
std::string get_design(const db::uuid_t& id);
void store_design(const db::uuid_t&, std::string& design);
/*
* Store a reference run locally
*/
bool increment_reference(const db::uuid_t& id);
void decrement_reference(const db::uuid_t& id);
std::shared_ptr<pl::SimOutputArtifact> get_reference(const db::uuid_t& id);
void store_reference(const db::uuid_t&, std::shared_ptr<pl::SimOutputArtifact> reference_run);
bool running() { return this->running_.load(std::memory_order_relaxed); };
bool is_stop_immediate() { return this->immediate_stop.load(std::memory_order_relaxed); };
void stop();
void stop_immediately() { this->immediate_stop.store(true, std::memory_order_relaxed); };
bool fresh_queue_empty();
bool finished_queue_empty(size_t min_size);
private:
size_t buffer_size;
std::queue<std::unique_ptr<InputType>> fresh_queue;
std::queue<std::unique_ptr<OutputType>> finished_queue;
volatile std::atomic_bool running_ = std::atomic_bool(true);
volatile std::atomic_bool immediate_stop;
std::unordered_map<db::uuid_t, std::pair<size_t, std::string>> designs;
std::unordered_map<db::uuid_t, std::pair<size_t, std::shared_ptr<pl::SimOutputArtifact>>> references;
bool worker_waiting = false;
bool downloader_waiting = false;
////// Mutexes //////
// access to task queues
std::mutex fresh_queue_mutex, finished_queue_mutex;
// design map access
std::mutex designs_mutex;
// reference map access
std::mutex references_mutex;
// notify upload thread that the finished queue is ready for cleanup
std::atomic_bool cleanup_ready;
std::mutex cleanup_ready_mutex;
std::condition_variable cleanup_ready_condition;
// inform the worker threads that there is data in the fresh task queue
std::mutex fresh_queue_empty_mutex;
std::condition_variable fresh_queue_empty_condition;
// inform the upload thread that there is data in the fresh task queue
std::mutex finished_queue_empty_mutex;
std::condition_variable finished_queue_empty_condition;
// inform the download thread that data was consumed
std::mutex fresh_queue_full_mutex;
std::condition_variable fresh_queue_full_condition;
// inform the main thread that the program is ending
std::mutex download_halt_mutex;
std::condition_variable download_halt_condition;
};
#endif