Program Listing for File DeviceAgentVector_impl.h

Return to documentation for file (include/flamegpu/runtime/agent/DeviceAgentVector_impl.h)

#ifndef INCLUDE_FLAMEGPU_RUNTIME_AGENT_DEVICEAGENTVECTOR_IMPL_H_
#define INCLUDE_FLAMEGPU_RUNTIME_AGENT_DEVICEAGENTVECTOR_IMPL_H_

#include <string>
#include <utility>
#include <memory>
#include <list>
#include <map>
#include <set>
#include <vector>

#include "flamegpu/simulation/AgentVector.h"
#include "flamegpu/simulation/detail/CUDAFatAgentStateList.h"  // VariableBuffer

namespace flamegpu {
namespace detail {
class CUDAScatter;
class CUDAAgent;
}  // detail
struct VarOffsetStruct;
struct NewAgentStorage;

class DeviceAgentVector_impl : protected AgentVector {
 public:
    using AgentVector::Agent;
    using AgentVector::CAgent;
    DeviceAgentVector_impl(detail::CUDAAgent& _cuda_agent, const std::string& cuda_agent_state,
        const VarOffsetStruct& _agentOffsets, std::vector<NewAgentStorage>& _newAgentData,
        detail::CUDAScatter& scatter, unsigned int streamId, cudaStream_t stream);
     // DeviceAgentVector_t(const DeviceAgentVector_t& other) = delete;
     // DeviceAgentVector_t& operator=(const DeviceAgentVector_t& other) = delete;
    void syncChanges();
    void purgeCache();

    using AgentVector::at;
    using AgentVector::operator[];
    using AgentVector::front;
    using AgentVector::back;
    // using AgentVector::data; // Would need to assume whole vector changed
    using AgentVector::begin;
    using AgentVector::end;
    using AgentVector::cbegin;
    using AgentVector::cend;
    using AgentVector::rbegin;
    using AgentVector::rend;
    using AgentVector::crbegin;
    using AgentVector::crend;
    using AgentVector::empty;
    using AgentVector::size;
    using AgentVector::max_size;
    using AgentVector::reserve;
    using AgentVector::capacity;
    using AgentVector::shrink_to_fit;
    using AgentVector::clear;
    using AgentVector::insert;
#ifdef SWIG
    using AgentVector::py_insert;
#endif
    using AgentVector::erase;
#ifdef SWIG
    using AgentVector::py_erase;
#endif
    using AgentVector::push_back;
    using AgentVector::pop_back;
    using AgentVector::resize;
    // using AgentVector::swap; // This would essentially require replacing the entire on-device agent vector

 protected:
    void _insert(size_type pos, size_type count) override;
    void _erase(size_type pos, size_type count) override;
    void _changed(const std::string& variable_name, size_type pos) override;
    void _changedAfter(const std::string& variable_name, size_type pos) override;
    void _require(const std::string& variable_name) const override;
    void _requireAll() const override;
    void _requireLength() const override;
    std::map<std::string, std::pair<size_type, size_type>> change_detail;
    mutable std::set<std::string> invalid_variables;
    bool unbound_buffers_has_changed;

 private:
     struct VariableBufferPair {
         explicit VariableBufferPair(const std::shared_ptr<detail::VariableBuffer>& _device)
             : device(_device) { }
         VariableBufferPair(VariableBufferPair&& other) {
             *this = std::move(other);
         }
         VariableBufferPair& operator=(VariableBufferPair&& other) {
             std::swap(this->host, other.host);
             std::swap(this->device, other.device);
             return *this;
         }
         // @todo Solve this
         // VariableBufferPair(const VariableBufferPair& other) = delete;
         // VariableBufferPair& operator=(const VariableBufferPair& other) = delete;

         ~VariableBufferPair() {
             if (host) free(host);
         }
         char* host = nullptr;

         std::shared_ptr<detail::VariableBuffer> device;
     };
    std::list<VariableBufferPair> unbound_buffers;
    unsigned int known_device_buffer_size = 0;
    unsigned int unbound_host_buffer_size = 0;
    unsigned int unbound_host_buffer_capacity = 0;
    bool unbound_host_buffer_invalid = false;
    void initUnboundBuffers();
    void reinitUnboundBuffers();
    void resizeUnboundBuffers(unsigned int new_capacity, bool init);
    detail::CUDAAgent& cuda_agent;
    std::string cuda_agent_state;


    const VarOffsetStruct& agentOffsets;
    std::vector<NewAgentStorage>& newAgentData;

    detail::CUDAScatter& scatter;
    const unsigned int streamId;
    const cudaStream_t stream;
};

}  // namespace flamegpu

#endif  // INCLUDE_FLAMEGPU_RUNTIME_AGENT_DEVICEAGENTVECTOR_IMPL_H_