<commit_before>/** @addtogroup Synchronization
 *  @{
 *  \copyright TU Dresden ZIH. All rights reserved.
 *  \authors Martin Flehmig, Marc Hartung, Marcus Walther
 *  \date Oct 2015
 */

#ifndef INCLUDE_SYNCHRONIZATION_DATAMANAGER_HPP_
#define INCLUDE_SYNCHRONIZATION_DATAMANAGER_HPP_

#include "fmi/AbstractFmu.hpp"
#include "Stdafx.hpp"
#include "BasicTypedefs.hpp"
#include "solver/SolverStepInfo.hpp"
#include "fmi/InputMapping.hpp"
#include "synchronization/IDataManager.hpp"
#include "synchronization/AbstractDataHistory.hpp"
#include "synchronization/Communicator.hpp"
#include "util/Vector.hpp"
#include "initialization/Plans.hpp"

namespace Synchronization
{
    /**
     * Receives data from communicator and interpolates if necessary. One DataManager serves all FMUs on a (compute) node.
     */
    template<class HistoryClass, class WriterClass>
    class DataManager : public IDataManager
    {
        static_assert(std::is_base_of<AbstractDataHistory,HistoryClass>::value, "DataManager: Template argument 1 need to inherit AbstractDataHistory");
        static_assert(std::is_base_of<Writer::IWriter,WriterClass>::value, "DataManager: Template argument 2 need to inherit IWalther");
     public:
        /**
         * Create DataManager for the given FMUs, their connections and the communicator.
         * @param names Names of the FMUs to be handled by this DataManager.
         * @param connections ConnectionMappings of the FMUs.
         * @param comm Communicator.
         * @param writer Writer object to write simulation results.
         */
        //DataManager(const vector<FMI::InputMappingSPtr> & connections, value_type _simStart = 0.0, value_type _stepSize = 0.001);
        DataManager(const Initialization::DataManagerPlan & in, const HistoryClass & history, const WriterClass & writer, shared_ptr<Synchronization::Communicator> & communicator)
                : IDataManager(in),
                  _history(history),
                  _commPtr(communicator),
                  _communicator(*communicator),
                  _writer(writer),
                  _simStart(in.writer.startTime),
                  _stepSize((in.writer.endTime - in.writer.startTime) / in.writer.numSteps),
                  _numManagedFmus(0)
        {
        }

        ~DataManager()
        {
            while (_history.hasWriteOutput())
            {
                _writer.write(_history.getWriteOutput());
            }
        }

        /**
         * \brief Saves all necessary values of the FMU and sets the input values of [fmu] to the given time step
         * If every FMU reached the write-out time step, saveSolverStep calls writeFmuResults.
         * The inputs of [fmu] are interpolated to the given time step. The function frees part of history if possible.
         * @return Returns false, if the results couldn't be saved or when the necessary inputs are not yet present.
         */
        bool saveSolverStep(FMI::AbstractFmu* fmu, const Solver::SolverStepInfo & stepInfo, const size_type & solveOrder) override
        {
            //return true;
            /////////////////////////////////////////////////////////
            ////////////////////// GET INPUTS ///////////////////////
            /////////////////////////////////////////////////////////

            this->setFmuInputValuesAtT(fmu->getTime(), fmu);

            FMI::ValueCollection newValues = fmu->getValues(FMI::ReferenceContainerType::ALL);  // Collection in where inputs are set
            /////////////////////////////////////////////////////////
            ///////////////////// SEND OUTPUTS //////////////////////
            /////////////////////////////////////////////////////////
            if (!sendOutputs(fmu->getTime(), solveOrder, fmu, stepInfo))
                return false;

            //////////////////////////////////////////////////////////
            ////////////////// SAVE DATA IN HISTORY///////////////////
            //////////////////////////////////////////////////////////
            if (stepInfo.hasEventWrite())  // check if event happend
            {
                _history.insert(HistoryEntry(stepInfo.getEventTime<0>(), solveOrder, stepInfo.getEventValues<0>()), fmu->getLocalId(), WriteInfo::EVENTWRITE);  // event save slightly before event
                _history.insert(HistoryEntry(stepInfo.getEventTime<1>(), solveOrder, stepInfo.getEventValues<1>()), fmu->getLocalId(), WriteInfo::EVENTWRITE);  // event save slightly after event
            }
            _history.insert(HistoryEntry(fmu->getTime(), solveOrder, newValues), fmu->getLocalId(),
                            (stepInfo.hasWriteStep()) ? WriteInfo::WRITE : WriteInfo::NOWRITE);  //normal save

            while (_history.hasWriteOutput())
            {
                LOGGER_WRITE("t:" + to_string(fmu->getTime()) + " Write results: " + fmu->getFmuName() + " fmu", Util::LC_SOLVER, Util::LL_DEBUG);
                _writer.write(_history.getWriteOutput());
            }

            return true;
        }
        /**
         * Sets values in fmu, which were send via connections. Only use if its sure that all values are present
         */
        void setFmuInputValuesAtT(const real_type & t, FMI::AbstractFmu* fmu) override
        {
            FMI::ValueCollection fmuValues = fmu->getValues(FMI::ReferenceContainerType::ALL);
            for (const size_type conId : _communicator.getInConnectionIds(fmu))
            {
                FMI::ValueCollection tmpColl = _history.getInputValues(conId, t);  // Implicit interpolation for time [curTime]
                _valuePacking[conId].unpack(fmuValues, tmpColl);
            }
            fmu->setValues(fmuValues);
        }

        /**
         * Calculates the next output time.
         * @param value_type The current FMU time.
         * @return value_type Returns next output time regarding the given argument
         */
        real_type getNextOutputTime(const real_type & currentFmuTime) const override
        {
            double a = (currentFmuTime / _stepSize), b = _simStart / _stepSize;

            int numSteps = ceil(a - b);
            real_type res = numSteps * _stepSize + _simStart;

            if (std::abs(res - currentFmuTime) < _history.getHistory(0).getInterpolation().getTolerance())
                res = (numSteps + 1) * _stepSize + _simStart;
            ;
            if (res < currentFmuTime)
                throw std::runtime_error("getNextOutputTime is buggy\n");
            return res;
        }

        Solver::DependencySolverInfo getDependencyInfo(FMI::AbstractFmu* fmu) override
        {
            if (_communicator.getInConnectionIds(fmu).size() > 0)
            {
                Solver::DependencySolverInfo dsi = collectInputs(fmu->getTime(), fmu);
                if (dsi.depStatus == Solver::DependencyStatus::BLOCKED)
                    return dsi;
                else if (dsi.depStatus == Solver::DependencyStatus::EVENT)
                    _upcomingEvents.push_back(dsi);
                if (!_upcomingEvents.empty())
                    if (_upcomingEvents.front().eventTimeEnd <= fmu->getTime())
                    {
                        dsi = _upcomingEvents.front();
                        _upcomingEvents.pop_front();
                        return dsi;
                    }
            }
            return
            {   Solver::DependencyStatus::FREE, 0,0};
        }

        /**
         * Initialize the result file by defining the result file header for the given FMU.
         * @param fmuName The name of the FMU that should be added to the result file.
         * @param variables A collection of all FMU-variables that should be added to the result file.
         */
        void addFmu(FMI::AbstractFmu * fmu) override
        {
            fmu->setLocalId(_numManagedFmus++);
            size_type numNewCons = _communicator.addFmu(fmu,_valuePacking);

            _lastCommTime.resize(_lastCommTime.size() + numNewCons, -1.0 * std::numeric_limits<real_type>::infinity());
            _lastEventWritten.resize(_lastEventWritten.size() + numNewCons, -1.0 * std::numeric_limits<real_type>::infinity());
            _lastEventRead.resize(_lastEventRead.size() + numNewCons, -1.0 * std::numeric_limits<real_type>::infinity());
            _lastEventReadState.resize(_lastEventReadState.size() + numNewCons, true);
            _lastEventWriteState.resize(_lastEventReadState.size() + numNewCons, true);
            _history.addFmu(fmu, fmu->getConnections());

            if (!_writer.isInitialized())
            {
                _writer.initialize();
                _writer.appendTimeHeader();
            }
            _writer.appendHeader(fmu->getFmuName(), fmu->getValueInfo());
        }

        const AbstractDataHistory* getHistory() const
        {
            return &_history;
        }

        // dirty, passes interface
        bool sendSingleOutput(real_type curTime, size_type solveOrder, const FMI::AbstractFmu* fmu, const size_type & conId)
        {
            if(_communicator.send(
                HistoryEntry(curTime, solveOrder, _valuePacking[conId].pack(fmu->getValues(FMI::ReferenceContainerType::ALL)), true), conId))
                _lastCommTime[conId] = curTime;
            else
                return false;
            return true;
        }

     protected:
        /**
         * Saves all state values at a specific time of the FMUs handled by this DataManager,
         * unless there aren't needed anymore.
         * Access via localId of the FMUs.
         */
        HistoryClass _history;

        /**
         * Communicator that handles data exchange (output values, input values) between several data managers.
         */
        shared_ptr<Synchronization::Communicator> _commPtr;
        Communicator & _communicator;

        /**
         * ConnectionMappings are for packing and unpacking of output and input values, accessible via connectionId.
         */
        vector<FMI::InputMapping> _valuePacking;

        /**
         * The last valid FMU values which has been send over a specific connection
         * (example: _lastCommTime[condId] = _currentTime, setting the connection described by conId to the current time)
         * see sendOuputs
         */
        vector<real_type> _lastCommTime;
        vector<real_type> _lastEventWritten;
        vector<real_type> _lastEventRead;
        /**
         * if _lastEventReadState is false, the next incomming input has to be an event
         */
        vector<bool> _lastEventReadState;
        vector<bool> _lastEventWriteState;

     private:
        WriterClass _writer;

        real_type _simStart;
        real_type _stepSize;

        size_type _numManagedFmus;

        std::list<Solver::DependencySolverInfo> _upcomingEvents;

        Solver::DependencySolverInfo collectInputs(real_type curTime, FMI::AbstractFmu* fmu)
        {
            Solver::DependencySolverInfo res = { Solver::DependencyStatus::FREE, std::numeric_limits<real_type>::max(), std::numeric_limits<real_type>::max() };
            for (const size_type conId : _communicator.getInConnectionIds(fmu))  // Checking all connections
            {
                while (_history.getInputHistory(conId).size() == 0 || _history.getInputHistory(conId).getNewestTime() < curTime)  // while till outputs were send by predecessor FMU
                {
                    HistoryEntry dhe = _communicator.recv(conId);
                    if (dhe.isValid())
                    {

                        if (dhe.hasEvent())
                        {
                            if (!_lastEventReadState[conId])
                            {
                                res.eventTimeStart = _lastEventRead[conId];
                                res.eventTimeEnd = dhe.getTime();
                                _history.insertInputs(dhe, conId);
                                _lastEventReadState[conId] = true;
                                if (std::abs(res.eventTimeStart - res.eventTimeEnd) > 1.0e-3)
                                {
                                    HistoryEntry dhe2 = _communicator.recv(conId);
                                    throw std::runtime_error("Somthings wrong");
                                }
                            }
                            else
                            {
                                HistoryEntry dhe2 = _communicator.recv(conId);
                                if (!dhe2.isValid())
                                {
                                    _lastEventReadState[conId] = false;
                                    _lastEventRead[conId] = dhe.getTime();
                                    _history.insertInputs(dhe, conId);
                                    res.depStatus = Solver::DependencyStatus::BLOCKED;
                                    break;
                                }
                                else
                                {
                                    res.eventTimeStart = dhe.getTime();
                                    res.eventTimeEnd = dhe2.getTime();
                                    _history.insertInputs(dhe, conId);
                                    _history.insertInputs(dhe2, conId);
                                    if (std::abs(res.eventTimeStart - res.eventTimeEnd) > 1.0e-3)
                                    {
                                        HistoryEntry dhe2 = _communicator.recv(conId);
                                        throw std::runtime_error("Somthings wrong");
                                    }
                                }
                            }
                            if (std::abs(res.eventTimeStart - res.eventTimeEnd) > 1.0e-3)
                                throw std::runtime_error("Somthings wrong");
                            res.depStatus = Solver::DependencyStatus::EVENT;
                            _lastEventReadState[conId] = true;
                            _lastEventRead[conId] = -std::numeric_limits<real_type>::infinity();
                            return res;
                        }
                        else
                            _history.insertInputs(dhe, conId);
                    }
                    else
                    {
                        res.depStatus = Solver::DependencyStatus::BLOCKED;
                        break;
                    }
                }
                if (res.depStatus == Solver::DependencyStatus::BLOCKED)
                    break;
            }
            return res;
        }

        bool sendOutputs(real_type curTime, size_type solveOrder, FMI::AbstractFmu* fmu,
                              const Solver::SolverStepInfo & stepInfo)
        {
            const FMI::ValueCollection fmuValues = fmu->getValues(FMI::ReferenceContainerType::ALL);
            for (size_type conId : _communicator.getOutConnectionIds(fmu))
            {
                if (_lastCommTime[conId] < curTime)  // check if the time wasn't already written
                {
                    if (stepInfo.hasEventWrite() && _lastEventWritten[conId] < stepInfo.getEventTime<0>())  // check for events and if there weren't already written
                    {
                        // send event in two communications
                        if (!_communicator.send(
                                HistoryEntry(stepInfo.getEventTime<0>(), solveOrder, _valuePacking[conId].pack(stepInfo.getEventValues<0>()), true), conId))
                            return false;
                        _lastEventWriteState[conId] = false;
                        _lastCommTime[conId] = curTime;

                        if (!_communicator.send(
                                HistoryEntry(stepInfo.getEventTime<1>(), solveOrder, _valuePacking[conId].pack(stepInfo.getEventValues<1>()), true), conId))
                            return false;
                        _lastEventWritten[conId] = stepInfo.getEventTime<1>();
                        _lastEventWriteState[conId] = true;
                    }
                    else
                    {
                        if (!_communicator.send(HistoryEntry(curTime, solveOrder, _valuePacking[conId].pack(fmuValues), false), conId))
                            return false;
                        _lastCommTime[conId] = curTime;
                    }
                }
                else
                {
                    if (!_lastEventWriteState[conId])
                    {
                        if (!_communicator.send(
                                HistoryEntry(stepInfo.getEventTime<1>(), solveOrder, _valuePacking[conId].pack(stepInfo.getEventValues<1>()), true), conId))
                            return false;
                        _lastEventWritten[conId] = stepInfo.getEventTime<1>();
                        _lastEventWriteState[conId] = true;
                    }
                    else
                        throw std::runtime_error("DataManager: Already send inputs.\n");

                }
            }
            return true;
        }
    }
    ;

} /* namespace Synchronization */

#endif /* INCLUDE_SYNCHRONIZATION_DATAMANAGER_HPP_ */
/**
 * @}
 */
<commit_msg>Cosmetic changes and add override keyword to functions<commit_after>/** @addtogroup Synchronization
 *  @{
 *  \copyright TU Dresden ZIH. All rights reserved.
 *  \authors Martin Flehmig, Marc Hartung, Marcus Walther
 *  \date Oct 2015
 */

#ifndef INCLUDE_SYNCHRONIZATION_DATAMANAGER_HPP_
#define INCLUDE_SYNCHRONIZATION_DATAMANAGER_HPP_

#include "fmi/AbstractFmu.hpp"
#include "Stdafx.hpp"
#include "BasicTypedefs.hpp"
#include "solver/SolverStepInfo.hpp"
#include "fmi/InputMapping.hpp"
#include "synchronization/IDataManager.hpp"
#include "synchronization/AbstractDataHistory.hpp"
#include "synchronization/Communicator.hpp"
#include "util/Vector.hpp"
#include "initialization/Plans.hpp"

namespace Synchronization
{
    /**
     * Receives data from communicator and interpolates if necessary. One DataManager serves all FMUs on a (compute) node.
     */
    template<class HistoryClass, class WriterClass>
    class DataManager : public IDataManager
    {
        static_assert(std::is_base_of<AbstractDataHistory,HistoryClass>::value, "DataManager: Template argument 1 need to inherit AbstractDataHistory");
        static_assert(std::is_base_of<Writer::IWriter,WriterClass>::value, "DataManager: Template argument 2 need to inherit IWalther");

     public:
        /**
         * Create DataManager for the given FMUs, their connections and the communicator.
         * @param names Names of the FMUs to be handled by this DataManager.
         * @param connections ConnectionMappings of the FMUs.
         * @param comm Communicator.
         * @param writer Writer object to write simulation results.
         */
        //DataManager(const vector<FMI::InputMappingSPtr> & connections, value_type _simStart = 0.0, value_type _stepSize = 0.001);
        DataManager(const Initialization::DataManagerPlan & in, const HistoryClass & history, const WriterClass & writer, shared_ptr<Synchronization::Communicator> & communicator)
                : IDataManager(in),
                  _history(history),
                  _commPtr(communicator),
                  _communicator(*communicator),
                  _writer(writer),
                  _simStart(in.writer.startTime),
                  _stepSize((in.writer.endTime - in.writer.startTime) / in.writer.numSteps),
                  _numManagedFmus(0)
        {
        }

        ~DataManager()
        {
            while (_history.hasWriteOutput())
            {
                _writer.write(_history.getWriteOutput());
            }
        }

        /**
         * \brief Saves all necessary values of the FMU and sets the input values of [fmu] to the given time step
         * If every FMU reached the write-out time step, saveSolverStep calls writeFmuResults.
         * The inputs of [fmu] are interpolated to the given time step. The function frees part of history if possible.
         * @return Returns false, if the results couldn't be saved or when the necessary inputs are not yet present.
         */
        bool saveSolverStep(FMI::AbstractFmu* fmu, const Solver::SolverStepInfo & stepInfo, const size_type & solveOrder) override
        {
            //return true;
            /////////////////////////////////////////////////////////
            ////////////////////// GET INPUTS ///////////////////////
            /////////////////////////////////////////////////////////

            this->setFmuInputValuesAtT(fmu->getTime(), fmu);

            FMI::ValueCollection newValues = fmu->getValues(FMI::ReferenceContainerType::ALL);  // Collection in where inputs are set
            /////////////////////////////////////////////////////////
            ///////////////////// SEND OUTPUTS //////////////////////
            /////////////////////////////////////////////////////////
            if (!sendOutputs(fmu->getTime(), solveOrder, fmu, stepInfo))
                return false;

            //////////////////////////////////////////////////////////
            ////////////////// SAVE DATA IN HISTORY///////////////////
            //////////////////////////////////////////////////////////
            if (stepInfo.hasEventWrite())  // check if event happend
            {
                _history.insert(HistoryEntry(stepInfo.getEventTime<0>(), solveOrder, stepInfo.getEventValues<0>()), fmu->getLocalId(), WriteInfo::EVENTWRITE);  // event save slightly before event
                _history.insert(HistoryEntry(stepInfo.getEventTime<1>(), solveOrder, stepInfo.getEventValues<1>()), fmu->getLocalId(), WriteInfo::EVENTWRITE);  // event save slightly after event
            }
            _history.insert(HistoryEntry(fmu->getTime(), solveOrder, newValues), fmu->getLocalId(), (stepInfo.hasWriteStep()) ? WriteInfo::WRITE : WriteInfo::NOWRITE);  //normal save

            while (_history.hasWriteOutput())
            {
                LOGGER_WRITE("t:" + to_string(fmu->getTime()) + " Write results: " + fmu->getFmuName() + " fmu", Util::LC_SOLVER, Util::LL_DEBUG);
                _writer.write(_history.getWriteOutput());
            }

            return true;
        }

        /**
         * Sets values in fmu, which were send via connections. Only use if its sure that all values are present
         */
        void setFmuInputValuesAtT(const real_type & t, FMI::AbstractFmu* fmu) override
        {
            FMI::ValueCollection fmuValues = fmu->getValues(FMI::ReferenceContainerType::ALL);
            for (const size_type conId : _communicator.getInConnectionIds(fmu))
            {
                FMI::ValueCollection tmpColl = _history.getInputValues(conId, t);  // Implicit interpolation for time [curTime]
                _valuePacking[conId].unpack(fmuValues, tmpColl);
            }
            fmu->setValues(fmuValues);
        }

        /**
         * Calculates the next output time.
         * @param value_type The current FMU time.
         * @return value_type Returns next output time regarding the given argument
         */
        real_type getNextOutputTime(const real_type & currentFmuTime) const override
        {
            double a = (currentFmuTime / _stepSize), b = _simStart / _stepSize;

            int numSteps = ceil(a - b);
            real_type res = numSteps * _stepSize + _simStart;

            if (std::abs(res - currentFmuTime) < _history.getHistory(0).getInterpolation().getTolerance())
                res = (numSteps + 1) * _stepSize + _simStart;
            ;
            if (res < currentFmuTime)
                throw std::runtime_error("getNextOutputTime is buggy\n");
            return res;
        }

        Solver::DependencySolverInfo getDependencyInfo(FMI::AbstractFmu* fmu) override
        {
            if (_communicator.getInConnectionIds(fmu).size() > 0)
            {
                Solver::DependencySolverInfo dsi = collectInputs(fmu->getTime(), fmu);
                if (dsi.depStatus == Solver::DependencyStatus::BLOCKED)
                    return dsi;
                else if (dsi.depStatus == Solver::DependencyStatus::EVENT)
                    _upcomingEvents.push_back(dsi);
                if (!_upcomingEvents.empty())
                    if (_upcomingEvents.front().eventTimeEnd <= fmu->getTime())
                    {
                        dsi = _upcomingEvents.front();
                        _upcomingEvents.pop_front();
                        return dsi;
                    }
            }
            return
            {   Solver::DependencyStatus::FREE, 0,0};
        }

        /**
         * Initialize the result file by defining the result file header for the given FMU.
         * @param fmuName The name of the FMU that should be added to the result file.
         * @param variables A collection of all FMU-variables that should be added to the result file.
         */
        void addFmu(FMI::AbstractFmu * fmu) override
        {
            fmu->setLocalId(_numManagedFmus++);
            size_type numNewCons = _communicator.addFmu(fmu, _valuePacking);

            _lastCommTime.resize(_lastCommTime.size() + numNewCons, -1.0 * std::numeric_limits<real_type>::infinity());
            _lastEventWritten.resize(_lastEventWritten.size() + numNewCons, -1.0 * std::numeric_limits<real_type>::infinity());
            _lastEventRead.resize(_lastEventRead.size() + numNewCons, -1.0 * std::numeric_limits<real_type>::infinity());
            _lastEventReadState.resize(_lastEventReadState.size() + numNewCons, true);
            _lastEventWriteState.resize(_lastEventReadState.size() + numNewCons, true);
            _history.addFmu(fmu, fmu->getConnections());

            if (!_writer.isInitialized())
            {
                _writer.initialize();
                _writer.appendTimeHeader();
            }
            _writer.appendHeader(fmu->getFmuName(), fmu->getValueInfo());
        }

        const AbstractDataHistory* getHistory() const override
        {
            return &_history;
        }

        // dirty, passes interface
        bool sendSingleOutput(real_type curTime, size_type solveOrder, const FMI::AbstractFmu* fmu, const size_type & conId)
        {
            if (_communicator.send(HistoryEntry(curTime, solveOrder, _valuePacking[conId].pack(fmu->getValues(FMI::ReferenceContainerType::ALL)), true), conId))
                _lastCommTime[conId] = curTime;
            else
                return false;
            return true;
        }

     protected:
        /**
         * Saves all state values at a specific time of the FMUs handled by this DataManager,
         * unless there aren't needed anymore.
         * Access via localId of the FMUs.
         */
        HistoryClass _history;

        /**
         * Communicator that handles data exchange (output values, input values) between several data managers.
         */
        shared_ptr<Synchronization::Communicator> _commPtr;
        Communicator & _communicator;

        /**
         * ConnectionMappings are for packing and unpacking of output and input values, accessible via connectionId.
         */
        vector<FMI::InputMapping> _valuePacking;

        /**
         * The last valid FMU values which has been send over a specific connection
         * (example: _lastCommTime[condId] = _currentTime, setting the connection described by conId to the current time)
         * see sendOuputs
         */
        vector<real_type> _lastCommTime;
        vector<real_type> _lastEventWritten;
        vector<real_type> _lastEventRead;
        /**
         * if _lastEventReadState is false, the next incomming input has to be an event
         */
        vector<bool> _lastEventReadState;
        vector<bool> _lastEventWriteState;

     private:
        WriterClass _writer;

        real_type _simStart;
        real_type _stepSize;

        size_type _numManagedFmus;

        std::list<Solver::DependencySolverInfo> _upcomingEvents;

        Solver::DependencySolverInfo collectInputs(real_type curTime, FMI::AbstractFmu* fmu)
        {
            Solver::DependencySolverInfo res = { Solver::DependencyStatus::FREE, std::numeric_limits<real_type>::max(), std::numeric_limits<real_type>::max() };
            for (const size_type conId : _communicator.getInConnectionIds(fmu))  // Checking all connections
            {
                while (_history.getInputHistory(conId).size() == 0 || _history.getInputHistory(conId).getNewestTime() < curTime)  // while till outputs were send by predecessor FMU
                {
                    HistoryEntry dhe = _communicator.recv(conId);
                    if (dhe.isValid())
                    {

                        if (dhe.hasEvent())
                        {
                            if (!_lastEventReadState[conId])
                            {
                                res.eventTimeStart = _lastEventRead[conId];
                                res.eventTimeEnd = dhe.getTime();
                                _history.insertInputs(dhe, conId);
                                _lastEventReadState[conId] = true;
                                if (std::abs(res.eventTimeStart - res.eventTimeEnd) > 1.0e-3)
                                {
                                    HistoryEntry dhe2 = _communicator.recv(conId);
                                    throw std::runtime_error("Somthings wrong");
                                }
                            }
                            else
                            {
                                HistoryEntry dhe2 = _communicator.recv(conId);
                                if (!dhe2.isValid())
                                {
                                    _lastEventReadState[conId] = false;
                                    _lastEventRead[conId] = dhe.getTime();
                                    _history.insertInputs(dhe, conId);
                                    res.depStatus = Solver::DependencyStatus::BLOCKED;
                                    break;
                                }
                                else
                                {
                                    res.eventTimeStart = dhe.getTime();
                                    res.eventTimeEnd = dhe2.getTime();
                                    _history.insertInputs(dhe, conId);
                                    _history.insertInputs(dhe2, conId);
                                    if (std::abs(res.eventTimeStart - res.eventTimeEnd) > 1.0e-3)
                                    {
                                        HistoryEntry dhe2 = _communicator.recv(conId);
                                        throw std::runtime_error("Somthings wrong");
                                    }
                                }
                            }
                            if (std::abs(res.eventTimeStart - res.eventTimeEnd) > 1.0e-3)
                                throw std::runtime_error("Somthings wrong");
                            res.depStatus = Solver::DependencyStatus::EVENT;
                            _lastEventReadState[conId] = true;
                            _lastEventRead[conId] = -std::numeric_limits<real_type>::infinity();
                            return res;
                        }
                        else
                            _history.insertInputs(dhe, conId);
                    }
                    else
                    {
                        res.depStatus = Solver::DependencyStatus::BLOCKED;
                        break;
                    }
                }
                if (res.depStatus == Solver::DependencyStatus::BLOCKED)
                    break;
            }
            return res;
        }

        bool sendOutputs(real_type curTime, size_type solveOrder, FMI::AbstractFmu* fmu, const Solver::SolverStepInfo & stepInfo)
        {
            const FMI::ValueCollection fmuValues = fmu->getValues(FMI::ReferenceContainerType::ALL);
            for (size_type conId : _communicator.getOutConnectionIds(fmu))
            {
                if (_lastCommTime[conId] < curTime)  // check if the time wasn't already written
                {
                    if (stepInfo.hasEventWrite() && _lastEventWritten[conId] < stepInfo.getEventTime<0>())  // check for events and if there weren't already written
                    {
                        // send event in two communications
                        if (!_communicator.send(HistoryEntry(stepInfo.getEventTime<0>(), solveOrder, _valuePacking[conId].pack(stepInfo.getEventValues<0>()), true), conId))
                            return false;
                        _lastEventWriteState[conId] = false;
                        _lastCommTime[conId] = curTime;

                        if (!_communicator.send(HistoryEntry(stepInfo.getEventTime<1>(), solveOrder, _valuePacking[conId].pack(stepInfo.getEventValues<1>()), true), conId))
                            return false;
                        _lastEventWritten[conId] = stepInfo.getEventTime<1>();
                        _lastEventWriteState[conId] = true;
                    }
                    else
                    {
                        if (!_communicator.send(HistoryEntry(curTime, solveOrder, _valuePacking[conId].pack(fmuValues), false), conId))
                            return false;
                        _lastCommTime[conId] = curTime;
                    }
                }
                else
                {
                    if (!_lastEventWriteState[conId])
                    {
                        if (!_communicator.send(HistoryEntry(stepInfo.getEventTime<1>(), solveOrder, _valuePacking[conId].pack(stepInfo.getEventValues<1>()), true), conId))
                            return false;
                        _lastEventWritten[conId] = stepInfo.getEventTime<1>();
                        _lastEventWriteState[conId] = true;
                    }
                    else
                        throw std::runtime_error("DataManager: Already send inputs.\n");

                }
            }
            return true;
        }
    };

} /* namespace Synchronization */

#endif /* INCLUDE_SYNCHRONIZATION_DATAMANAGER_HPP_ */
/**
 * @}
 */
<|endoftext|>


<commit_before>// Copyright (c) 2011-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include "config/navcoin-config.h"
#endif

#include "intro.h"
#include "ui_intro.h"
#include "skinize.h"

#include "guiutil.h"
#include "navtechinit.h"

#include "util.h"

#include <boost/filesystem.hpp>

#include <QFileDialog>
#include <QSettings>
#include <QMessageBox>
#include <cmath>

static const uint64_t GB_BYTES = 1000000000LL;
/* Minimum free space (in GB) needed for data directory */
static const uint64_t BLOCK_CHAIN_SIZE = 1;
/* Minimum free space (in GB) needed for data directory when pruned; Does not include prune target */
static const uint64_t CHAIN_STATE_SIZE = 1;
/* Total required space (in GB) depending on user choice (prune, not prune) */
static uint64_t requiredSpace;

/* Check free space asynchronously to prevent hanging the UI thread.

   Up to one request to check a path is in flight to this thread; when the check()
   function runs, the current path is requested from the associated Intro object.
   The reply is sent back through a signal.

   This ensures that no queue of checking requests is built up while the user is
   still entering the path, and that always the most recently entered path is checked as
   soon as the thread becomes available.
*/
class FreespaceChecker : public QObject
{
    Q_OBJECT

public:
    FreespaceChecker(Intro *intro);

    enum Status {
        ST_OK,
        ST_ERROR
    };

public Q_SLOTS:
    void check();

Q_SIGNALS:
    void reply(int status, const QString &message, quint64 available);

private:
    Intro *intro;
};

#include "intro.moc"

FreespaceChecker::FreespaceChecker(Intro *intro)
{
    this->intro = intro;
}

void FreespaceChecker::check()
{
    namespace fs = boost::filesystem;
    QString dataDirStr = intro->getPathToCheck();
    fs::path dataDir = GUIUtil::qstringToBoostPath(dataDirStr);
    uint64_t freeBytesAvailable = 0;
    int replyStatus = ST_OK;
    QString replyMessage;

    /* Find first parent that exists, so that fs::space does not fail */
    fs::path parentDir = dataDir;
    fs::path parentDirOld = fs::path();
    while(parentDir.has_parent_path() && !fs::exists(parentDir))
    {
        parentDir = parentDir.parent_path();

        /* Check if we make any progress, break if not to prevent an infinite loop here */
        if (parentDirOld == parentDir)
            break;

        parentDirOld = parentDir;
    }

    try {
        freeBytesAvailable = fs::space(parentDir).available;
        if(fs::exists(dataDir))
        {
            if(!fs::is_directory(dataDir))
            {
                replyStatus = ST_OK;
                QString replyMessage = tr("NavCoin will try to import an old wallet.dat file.");
            } else {
                replyStatus = ST_ERROR;
                replyMessage = tr("You must choose a wallet.dat file.");
            }
        }
    } catch (const fs::filesystem_error&)
    {
        /* Parent directory does not exist or is not accessible */
        replyStatus = ST_ERROR;
        replyMessage = tr("Cannot read wallet.dat file.");
    }
    Q_EMIT reply(replyStatus, replyMessage, freeBytesAvailable);
}

Intro::Intro(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Intro),
    thread(0),
    signalled(false)
{
    ui->setupUi(this);
    ui->welcomeLabel->setText(ui->welcomeLabel->text().arg(tr(PACKAGE_NAME)));
    ui->storageLabel->setText(ui->storageLabel->text().arg(tr(PACKAGE_NAME)));
    uint64_t pruneTarget = std::max<int64_t>(0, GetArg("-prune", 0));
    requiredSpace = BLOCK_CHAIN_SIZE;
    if (pruneTarget)
        requiredSpace = CHAIN_STATE_SIZE + std::ceil(pruneTarget * 1024 * 1024.0 / GB_BYTES);
    ui->sizeWarningLabel->setText(ui->sizeWarningLabel->text().arg(tr(PACKAGE_NAME)).arg(requiredSpace));
    startThread();
}

Intro::~Intro()
{
    delete ui;
    /* Ensure thread is finished before it is deleted */
    Q_EMIT stopThread();
    thread->wait();
}

QString Intro::getDataDirectory()
{
    return ui->dataDirectory->text();
}

void Intro::setDataDirectory(const QString &dataDir)
{
    ui->dataDirectory->setText(dataDir);
    if(dataDir == getDefaultDataDirectory() + QDir::separator() + "wallet.dat")
    {
        ui->dataDirDefault->setChecked(true);
        ui->dataDirectory->setEnabled(false);
        ui->ellipsisButton->setEnabled(false);
    } else {
        ui->dataDirCustom->setChecked(true);
        ui->dataDirectory->setEnabled(true);
        ui->ellipsisButton->setEnabled(true);
    }
}

QString Intro::getDefaultDataDirectory()
{
    return GUIUtil::boostPathToQString(GetDefaultDataDir());
}

void Intro::pickDataDirectory()
{
    namespace fs = boost::filesystem;
    QSettings settings;
    /* If data directory provided on command line, no need to look at settings
       or show a picking dialog */
    if(!GetArg("-datadir", "").empty())
        return;
    /* 1) Default data directory for operating system */
    QString dataDir = getDefaultDataDirectory();
    /* 2) Allow QSettings to override default dir */
    dataDir = settings.value("strDataDir", dataDir).toString();

    if(!fs::exists(GUIUtil::qstringToBoostPath(dataDir)) || GetBoolArg("-choosedatadir", DEFAULT_CHOOSE_DATADIR))
    {
        /* If current default data directory does not exist, let the user choose one */
        Intro intro;
        intro.setDataDirectory(dataDir + QDir::separator() + "wallet.dat");
        intro.setWindowIcon(QIcon(":icons/navcoin"));
        intro.setStyleSheet(Skinize());

        while(true)
        {
            if(!intro.exec())
            {
                /* Cancel clicked */
                exit(0);
            }
            QString oldWallet = intro.getDataDirectory();
            try {
                TryCreateDirectory(GUIUtil::qstringToBoostPath(dataDir));
                if(oldWallet != dataDir + QDir::separator() + "wallet.dat")
                {
                    //Try to copy old wallet
                    boost::filesystem::detail::copy_file(GUIUtil::qstringToBoostPath(oldWallet),GUIUtil::qstringToBoostPath(dataDir + "/wallet.dat"),boost::filesystem::detail::none);
                    SoftSetArg("-zapwallettxes","2");
                }
                WriteConfigFile("addanonserver", "95.183.52.55:3000");
                WriteConfigFile("addanonserver", "95.183.52.28:3000");
                WriteConfigFile("addanonserver", "95.183.52.29:3000");
                WriteConfigFile("addanonserver", "95.183.53.184:3000");
                SoftSetArg("-firstrun","1");

                break;
            } catch (const fs::filesystem_error&) {
                QMessageBox::critical(0, tr(PACKAGE_NAME),
                    tr("Error creating data folder.").arg(dataDir));
                /* fall through, back to choosing screen */
            }
        }

        settings.setValue("strDataDir", dataDir);
    }
    /* Only override -datadir if different from the default, to make it possible to
     * override -datadir in the navcoin.conf file in the default data directory
     * (to be consistent with navcoind behavior)
     */
    if(dataDir != getDefaultDataDirectory())
        SoftSetArg("-datadir", GUIUtil::qstringToBoostPath(dataDir).string()); // use OS locale for path setting
}

void Intro::setStatus(int status, const QString &message, quint64 bytesAvailable)
{
    switch(status)
    {
    case FreespaceChecker::ST_OK:
        ui->errorMessage->setText(message);
        ui->errorMessage->setStyleSheet("");
        break;
    case FreespaceChecker::ST_ERROR:
        ui->errorMessage->setText(tr("Error") + ": " + message);
        ui->errorMessage->setStyleSheet("QLabel { color: #800000 }");
        break;
    }
    /* Don't allow confirm in ERROR state */
    ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(status != FreespaceChecker::ST_ERROR);
}

void Intro::on_dataDirectory_textChanged(const QString &dataDirStr)
{
    /* Disable OK button until check result comes in */
    ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
    checkPath(dataDirStr);
}

void Intro::on_ellipsisButton_clicked()
{
    QString wallet = QDir::toNativeSeparators(QFileDialog::getOpenFileName(0, "Choose wallet file", ui->dataDirectory->text(), "Wallet (wallet.dat)"));
    ui->dataDirectory->setText(wallet);
}

void Intro::on_dataDirDefault_clicked()
{
    setDataDirectory(getDefaultDataDirectory() + QDir::separator() + "wallet.dat");
}

void Intro::on_dataDirCustom_clicked()
{
    ui->dataDirectory->setEnabled(true);
    ui->ellipsisButton->setEnabled(true);
}

void Intro::startThread()
{
    thread = new QThread(this);
    FreespaceChecker *executor = new FreespaceChecker(this);
    executor->moveToThread(thread);

    connect(executor, SIGNAL(reply(int,QString,quint64)), this, SLOT(setStatus(int,QString,quint64)));
    connect(this, SIGNAL(requestCheck()), executor, SLOT(check()));
    /*  make sure executor object is deleted in its own thread */
    connect(this, SIGNAL(stopThread()), executor, SLOT(deleteLater()));
    connect(this, SIGNAL(stopThread()), thread, SLOT(quit()));

    thread->start();
}

void Intro::checkPath(const QString &dataDir)
{
    mutex.lock();
    pathToCheck = dataDir;
    if(!signalled)
    {
        signalled = true;
        Q_EMIT requestCheck();
    }
    mutex.unlock();
}

QString Intro::getPathToCheck()
{
    QString retval;
    mutex.lock();
    retval = pathToCheck;
    signalled = false; /* new request can be queued now */
    mutex.unlock();
    return retval;
}
<commit_msg>gui: fixed folder separator<commit_after>// Copyright (c) 2011-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include "config/navcoin-config.h"
#endif

#include "intro.h"
#include "ui_intro.h"
#include "skinize.h"

#include "guiutil.h"
#include "navtechinit.h"

#include "util.h"

#include <boost/filesystem.hpp>

#include <QFileDialog>
#include <QSettings>
#include <QMessageBox>
#include <cmath>

static const uint64_t GB_BYTES = 1000000000LL;
/* Minimum free space (in GB) needed for data directory */
static const uint64_t BLOCK_CHAIN_SIZE = 1;
/* Minimum free space (in GB) needed for data directory when pruned; Does not include prune target */
static const uint64_t CHAIN_STATE_SIZE = 1;
/* Total required space (in GB) depending on user choice (prune, not prune) */
static uint64_t requiredSpace;

/* Check free space asynchronously to prevent hanging the UI thread.

   Up to one request to check a path is in flight to this thread; when the check()
   function runs, the current path is requested from the associated Intro object.
   The reply is sent back through a signal.

   This ensures that no queue of checking requests is built up while the user is
   still entering the path, and that always the most recently entered path is checked as
   soon as the thread becomes available.
*/
class FreespaceChecker : public QObject
{
    Q_OBJECT

public:
    FreespaceChecker(Intro *intro);

    enum Status {
        ST_OK,
        ST_ERROR
    };

public Q_SLOTS:
    void check();

Q_SIGNALS:
    void reply(int status, const QString &message, quint64 available);

private:
    Intro *intro;
};

#include "intro.moc"

FreespaceChecker::FreespaceChecker(Intro *intro)
{
    this->intro = intro;
}

void FreespaceChecker::check()
{
    namespace fs = boost::filesystem;
    QString dataDirStr = intro->getPathToCheck();
    fs::path dataDir = GUIUtil::qstringToBoostPath(dataDirStr);
    uint64_t freeBytesAvailable = 0;
    int replyStatus = ST_OK;
    QString replyMessage;

    /* Find first parent that exists, so that fs::space does not fail */
    fs::path parentDir = dataDir;
    fs::path parentDirOld = fs::path();
    while(parentDir.has_parent_path() && !fs::exists(parentDir))
    {
        parentDir = parentDir.parent_path();

        /* Check if we make any progress, break if not to prevent an infinite loop here */
        if (parentDirOld == parentDir)
            break;

        parentDirOld = parentDir;
    }

    try {
        freeBytesAvailable = fs::space(parentDir).available;
        if(fs::exists(dataDir))
        {
            if(!fs::is_directory(dataDir))
            {
                replyStatus = ST_OK;
                QString replyMessage = tr("NavCoin will try to import an old wallet.dat file.");
            } else {
                replyStatus = ST_ERROR;
                replyMessage = tr("You must choose a wallet.dat file.");
            }
        }
    } catch (const fs::filesystem_error&)
    {
        /* Parent directory does not exist or is not accessible */
        replyStatus = ST_ERROR;
        replyMessage = tr("Cannot read wallet.dat file.");
    }
    Q_EMIT reply(replyStatus, replyMessage, freeBytesAvailable);
}

Intro::Intro(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Intro),
    thread(0),
    signalled(false)
{
    ui->setupUi(this);
    ui->welcomeLabel->setText(ui->welcomeLabel->text().arg(tr(PACKAGE_NAME)));
    ui->storageLabel->setText(ui->storageLabel->text().arg(tr(PACKAGE_NAME)));
    uint64_t pruneTarget = std::max<int64_t>(0, GetArg("-prune", 0));
    requiredSpace = BLOCK_CHAIN_SIZE;
    if (pruneTarget)
        requiredSpace = CHAIN_STATE_SIZE + std::ceil(pruneTarget * 1024 * 1024.0 / GB_BYTES);
    ui->sizeWarningLabel->setText(ui->sizeWarningLabel->text().arg(tr(PACKAGE_NAME)).arg(requiredSpace));
    startThread();
}

Intro::~Intro()
{
    delete ui;
    /* Ensure thread is finished before it is deleted */
    Q_EMIT stopThread();
    thread->wait();
}

QString Intro::getDataDirectory()
{
    return ui->dataDirectory->text();
}

void Intro::setDataDirectory(const QString &dataDir)
{
    ui->dataDirectory->setText(dataDir);
    if(dataDir == getDefaultDataDirectory() + QDir::separator() + "wallet.dat")
    {
        ui->dataDirDefault->setChecked(true);
        ui->dataDirectory->setEnabled(false);
        ui->ellipsisButton->setEnabled(false);
    } else {
        ui->dataDirCustom->setChecked(true);
        ui->dataDirectory->setEnabled(true);
        ui->ellipsisButton->setEnabled(true);
    }
}

QString Intro::getDefaultDataDirectory()
{
    return GUIUtil::boostPathToQString(GetDefaultDataDir());
}

void Intro::pickDataDirectory()
{
    namespace fs = boost::filesystem;
    QSettings settings;
    /* If data directory provided on command line, no need to look at settings
       or show a picking dialog */
    if(!GetArg("-datadir", "").empty())
        return;
    /* 1) Default data directory for operating system */
    QString dataDir = getDefaultDataDirectory();
    /* 2) Allow QSettings to override default dir */
    dataDir = settings.value("strDataDir", dataDir).toString();

    if(!fs::exists(GUIUtil::qstringToBoostPath(dataDir)) || GetBoolArg("-choosedatadir", DEFAULT_CHOOSE_DATADIR))
    {
        /* If current default data directory does not exist, let the user choose one */
        Intro intro;
        intro.setDataDirectory(dataDir + QDir::separator() + "wallet.dat");
        intro.setWindowIcon(QIcon(":icons/navcoin"));
        intro.setStyleSheet(Skinize());

        while(true)
        {
            if(!intro.exec())
            {
                /* Cancel clicked */
                exit(0);
            }
            QString oldWallet = intro.getDataDirectory();
            try {
                TryCreateDirectory(GUIUtil::qstringToBoostPath(dataDir));
                if(oldWallet != dataDir + QDir::separator() + "wallet.dat")
                {
                    //Try to copy old wallet
                    boost::filesystem::detail::copy_file(GUIUtil::qstringToBoostPath(oldWallet),GUIUtil::qstringToBoostPath(dataDir + QDir::separator() + "wallet.dat"),boost::filesystem::detail::none);
                    SoftSetArg("-zapwallettxes","2");
                }
                WriteConfigFile("addanonserver", "95.183.52.55:3000");
                WriteConfigFile("addanonserver", "95.183.52.28:3000");
                WriteConfigFile("addanonserver", "95.183.52.29:3000");
                WriteConfigFile("addanonserver", "95.183.53.184:3000");
                SoftSetArg("-firstrun","1");

                break;
            } catch (const fs::filesystem_error&) {
                QMessageBox::critical(0, tr(PACKAGE_NAME),
                    tr("Error creating data folder.").arg(dataDir));
                /* fall through, back to choosing screen */
            }
        }

        settings.setValue("strDataDir", dataDir);
    }
    /* Only override -datadir if different from the default, to make it possible to
     * override -datadir in the navcoin.conf file in the default data directory
     * (to be consistent with navcoind behavior)
     */
    if(dataDir != getDefaultDataDirectory())
        SoftSetArg("-datadir", GUIUtil::qstringToBoostPath(dataDir).string()); // use OS locale for path setting
}

void Intro::setStatus(int status, const QString &message, quint64 bytesAvailable)
{
    switch(status)
    {
    case FreespaceChecker::ST_OK:
        ui->errorMessage->setText(message);
        ui->errorMessage->setStyleSheet("");
        break;
    case FreespaceChecker::ST_ERROR:
        ui->errorMessage->setText(tr("Error") + ": " + message);
        ui->errorMessage->setStyleSheet("QLabel { color: #800000 }");
        break;
    }
    /* Don't allow confirm in ERROR state */
    ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(status != FreespaceChecker::ST_ERROR);
}

void Intro::on_dataDirectory_textChanged(const QString &dataDirStr)
{
    /* Disable OK button until check result comes in */
    ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
    checkPath(dataDirStr);
}

void Intro::on_ellipsisButton_clicked()
{
    QString wallet = QDir::toNativeSeparators(QFileDialog::getOpenFileName(0, "Choose wallet file", ui->dataDirectory->text(), "Wallet (wallet.dat)"));
    ui->dataDirectory->setText(wallet);
}

void Intro::on_dataDirDefault_clicked()
{
    setDataDirectory(getDefaultDataDirectory() + QDir::separator() + "wallet.dat");
}

void Intro::on_dataDirCustom_clicked()
{
    ui->dataDirectory->setEnabled(true);
    ui->ellipsisButton->setEnabled(true);
}

void Intro::startThread()
{
    thread = new QThread(this);
    FreespaceChecker *executor = new FreespaceChecker(this);
    executor->moveToThread(thread);

    connect(executor, SIGNAL(reply(int,QString,quint64)), this, SLOT(setStatus(int,QString,quint64)));
    connect(this, SIGNAL(requestCheck()), executor, SLOT(check()));
    /*  make sure executor object is deleted in its own thread */
    connect(this, SIGNAL(stopThread()), executor, SLOT(deleteLater()));
    connect(this, SIGNAL(stopThread()), thread, SLOT(quit()));

    thread->start();
}

void Intro::checkPath(const QString &dataDir)
{
    mutex.lock();
    pathToCheck = dataDir;
    if(!signalled)
    {
        signalled = true;
        Q_EMIT requestCheck();
    }
    mutex.unlock();
}

QString Intro::getPathToCheck()
{
    QString retval;
    mutex.lock();
    retval = pathToCheck;
    signalled = false; /* new request can be queued now */
    mutex.unlock();
    return retval;
}
<|endoftext|>


<commit_before>#ifndef VMATH_CORE_SWIZZLE_SWIZZLE4_INL
#define VMATH_CORE_SWIZZLE_SWIZZLE4_INL

#include <Vmath/core/swizzle/swizzle4.hpp>

#include <Vmath/core/vector.hpp>

namespace vmath {
namespace core {

/**
 * Convert from a swizzle to a vector.
 * @return Converted vector.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
vector<T, 4> swizzle4<T, N, E1, E2, E3, E4>::to_vector4(void) const {
	return vector<T, 4>(this->data[E1], this->data[E2], this->data[E3], this->data[E4]);
}

/**
 * Implicitly convert from a swizzle to a vector.
 * @return Converted vector.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
swizzle4<T, N, E1, E2, E3, E4>::operator vector<T, 4>(void) {
	return this->to_vector4();
}

/**
 * Set this swizzle (and the underlying vector) equal to a vector.
 * @param V vector to set equal to.
 * @return The modified vector.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
template<typename U, typename>
vector<T, 4>& swizzle4<T, N, E1, E2, E3, E4>::operator=(const vector<T, 4>& V) {
	this->data[E1] = V.x;
	this->data[E2] = V.y;
	this->data[E3] = V.z;
	this->data[E4] = V.w;
	return *(vector<T, 4>*)this;
}

/**
 * Negate this swizzle.
 * @return The negated swizzle.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
vector<T, 4> swizzle4<T, N, E1, E2, E3, E4>::operator-(void) const {
	return -this->to_vector4();
}

/**
 * Add a vector to this swizzle.
 * @param V vector to add.
 * @return The vector sum.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
vector<T, 4> swizzle4<T, N, E1, E2, E3, E4>::operator+(const vector<T, 4>& V) const {
	return this->to_vector4() + V;
}

/**
 * Add a vector to this swizzle. Set this swizzle (and the underlying vector) to
 * the result.
 * @param V vector to add.
 * @return The modified vector.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
template<typename U, typename>
vector<T, 4>& swizzle4<T, N, E1, E2, E3, E4>::operator+=(const vector<T, 4>& V) {
	return *this = *this + V;
}

/**
 * Subtract a vector from this swizzle.
 * @param V vector to subtract.
 * @return The vector difference.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
vector<T, 4> swizzle4<T, N, E1, E2, E3, E4>::operator-(const vector<T, 4>& V) const {
	return this->to_vector4() - V;
}

/**
 * Subtract a vector from this swizzle. Set this swizzle (and the underlying
 * vector) to the result.
 * @param V vector to add.
 * @return The modified vector.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
template<typename U, typename>
vector<T, 4>& swizzle4<T, N, E1, E2, E3, E4>::operator-=(const vector<T, 4>& V) {
	return *this= *this - V;
}

/**
 * Multiply this swizzle by a vector.
 * @param V vector to multiply.
 * @return The vector product.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
vector<T, 4> swizzle4<T, N, E1, E2, E3, E4>::operator*(const vector<T, 4>& V) const {
	return this->to_vector4() * V;
}

/**
 * Multiply this swizzle by a vector. Set this swizzle (and the underlying
 * vector) to the result.
 * @param V vector to multiply by.
 * @return The modified vector.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
template<typename U, typename>
vector<T, 4>& swizzle4<T, N, E1, E2, E3, E4>::operator*=(const vector<T, 4>& V) {
	return *this = *this * V;
}

/**
 * Divide this swizzle by a vector.
 * @param V vector to divide by.
 * @return The vector quotient.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
vector<T, 4> swizzle4<T, N, E1, E2, E3, E4>::operator/(const vector<T, 4>& V) const {
	return this->to_vector4() / V;
}

/**
 * Divide this swizzle by a vector. Set this swizzle (and the underlying vector)
 * to the result.
 * @param V vector to multiply by.
 * @return The modified vector.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
template<typename U, typename>
vector<T, 4>& swizzle4<T, N, E1, E2, E3, E4>::operator/=(const vector<T, 4>& V) {
	return *this = *this / V;
}

/**
 * vector-scalar multiplication.
 * @param s Scalar to multiply by.
 * @return The vector-scalar product.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
vector<T, 4> swizzle4<T, N, E1, E2, E3, E4>::operator*(const T& s) const {
	return this->to_vector4() * s;
}

/**
 * vector-scalar multiplication. Set this swizzle (and the underlying vector) to
 * the result.
 * @param s Scalar to multiply by.
 * @return The vector-scalar product.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
template<typename U, typename>
vector<T, 4>& swizzle4<T, N, E1, E2, E3, E4>::operator*=(const T& s) {
	return *this = *this * s;
}

/**
 * vector-scalar division.
 * @param s Scalar to divide by.
 * @return The vector-scalar quotient.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
vector<T, 4> swizzle4<T, N, E1, E2, E3, E4>::operator/(const T& s) const {
	return this->to_vector4() / s;
}

/**
 * vector-scalar division. Set this swizzle (and the underlying vector) to the
 * result.
 * @param s Scalar to divide by.
 * @return The vector-scalar quotient.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
template<typename U, typename>
vector<T, 4>& swizzle4<T, N, E1, E2, E3, E4>::operator/=(const T& s) {
	return *this = *this / s;
}

/**
 * Check swizzle-vector equality.
 * @param V vector to check equality with.
 * @return True if they are equal, otherwise false.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
bool swizzle4<T, N, E1, E2, E3, E4>::operator==(const vector<T, 4>& V) const {
	return this->to_vector4() == V;
}

/**
 * Check swizzle-vector inequality.
 * @param V vector to check inequality with.
 * @return False if they are equal, otherwise true.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
bool swizzle4<T, N, E1, E2, E3, E4>::operator!=(const vector<T, 4>& V) const {
	return this->to_vector4() != V;
}

}
}

#endif
<commit_msg>Fixed typo in include.<commit_after>#ifndef VMATH_CORE_SWIZZLE_SWIZZLE4_INL
#define VMATH_CORE_SWIZZLE_SWIZZLE4_INL

#include <vmath/core/swizzle/swizzle4.hpp>

#include <vmath/core/vector.hpp>

namespace vmath {
namespace core {

/**
 * Convert from a swizzle to a vector.
 * @return Converted vector.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
vector<T, 4> swizzle4<T, N, E1, E2, E3, E4>::to_vector4(void) const {
	return vector<T, 4>(this->data[E1], this->data[E2], this->data[E3], this->data[E4]);
}

/**
 * Implicitly convert from a swizzle to a vector.
 * @return Converted vector.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
swizzle4<T, N, E1, E2, E3, E4>::operator vector<T, 4>(void) {
	return this->to_vector4();
}

/**
 * Set this swizzle (and the underlying vector) equal to a vector.
 * @param V vector to set equal to.
 * @return The modified vector.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
template<typename U, typename>
vector<T, 4>& swizzle4<T, N, E1, E2, E3, E4>::operator=(const vector<T, 4>& V) {
	this->data[E1] = V.x;
	this->data[E2] = V.y;
	this->data[E3] = V.z;
	this->data[E4] = V.w;
	return *(vector<T, 4>*)this;
}

/**
 * Negate this swizzle.
 * @return The negated swizzle.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
vector<T, 4> swizzle4<T, N, E1, E2, E3, E4>::operator-(void) const {
	return -this->to_vector4();
}

/**
 * Add a vector to this swizzle.
 * @param V vector to add.
 * @return The vector sum.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
vector<T, 4> swizzle4<T, N, E1, E2, E3, E4>::operator+(const vector<T, 4>& V) const {
	return this->to_vector4() + V;
}

/**
 * Add a vector to this swizzle. Set this swizzle (and the underlying vector) to
 * the result.
 * @param V vector to add.
 * @return The modified vector.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
template<typename U, typename>
vector<T, 4>& swizzle4<T, N, E1, E2, E3, E4>::operator+=(const vector<T, 4>& V) {
	return *this = *this + V;
}

/**
 * Subtract a vector from this swizzle.
 * @param V vector to subtract.
 * @return The vector difference.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
vector<T, 4> swizzle4<T, N, E1, E2, E3, E4>::operator-(const vector<T, 4>& V) const {
	return this->to_vector4() - V;
}

/**
 * Subtract a vector from this swizzle. Set this swizzle (and the underlying
 * vector) to the result.
 * @param V vector to add.
 * @return The modified vector.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
template<typename U, typename>
vector<T, 4>& swizzle4<T, N, E1, E2, E3, E4>::operator-=(const vector<T, 4>& V) {
	return *this= *this - V;
}

/**
 * Multiply this swizzle by a vector.
 * @param V vector to multiply.
 * @return The vector product.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
vector<T, 4> swizzle4<T, N, E1, E2, E3, E4>::operator*(const vector<T, 4>& V) const {
	return this->to_vector4() * V;
}

/**
 * Multiply this swizzle by a vector. Set this swizzle (and the underlying
 * vector) to the result.
 * @param V vector to multiply by.
 * @return The modified vector.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
template<typename U, typename>
vector<T, 4>& swizzle4<T, N, E1, E2, E3, E4>::operator*=(const vector<T, 4>& V) {
	return *this = *this * V;
}

/**
 * Divide this swizzle by a vector.
 * @param V vector to divide by.
 * @return The vector quotient.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
vector<T, 4> swizzle4<T, N, E1, E2, E3, E4>::operator/(const vector<T, 4>& V) const {
	return this->to_vector4() / V;
}

/**
 * Divide this swizzle by a vector. Set this swizzle (and the underlying vector)
 * to the result.
 * @param V vector to multiply by.
 * @return The modified vector.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
template<typename U, typename>
vector<T, 4>& swizzle4<T, N, E1, E2, E3, E4>::operator/=(const vector<T, 4>& V) {
	return *this = *this / V;
}

/**
 * vector-scalar multiplication.
 * @param s Scalar to multiply by.
 * @return The vector-scalar product.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
vector<T, 4> swizzle4<T, N, E1, E2, E3, E4>::operator*(const T& s) const {
	return this->to_vector4() * s;
}

/**
 * vector-scalar multiplication. Set this swizzle (and the underlying vector) to
 * the result.
 * @param s Scalar to multiply by.
 * @return The vector-scalar product.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
template<typename U, typename>
vector<T, 4>& swizzle4<T, N, E1, E2, E3, E4>::operator*=(const T& s) {
	return *this = *this * s;
}

/**
 * vector-scalar division.
 * @param s Scalar to divide by.
 * @return The vector-scalar quotient.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
vector<T, 4> swizzle4<T, N, E1, E2, E3, E4>::operator/(const T& s) const {
	return this->to_vector4() / s;
}

/**
 * vector-scalar division. Set this swizzle (and the underlying vector) to the
 * result.
 * @param s Scalar to divide by.
 * @return The vector-scalar quotient.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
template<typename U, typename>
vector<T, 4>& swizzle4<T, N, E1, E2, E3, E4>::operator/=(const T& s) {
	return *this = *this / s;
}

/**
 * Check swizzle-vector equality.
 * @param V vector to check equality with.
 * @return True if they are equal, otherwise false.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
bool swizzle4<T, N, E1, E2, E3, E4>::operator==(const vector<T, 4>& V) const {
	return this->to_vector4() == V;
}

/**
 * Check swizzle-vector inequality.
 * @param V vector to check inequality with.
 * @return False if they are equal, otherwise true.
 */
template<typename T, std::size_t N, std::size_t E1, std::size_t E2, std::size_t E3, std::size_t E4>
bool swizzle4<T, N, E1, E2, E3, E4>::operator!=(const vector<T, 4>& V) const {
	return this->to_vector4() != V;
}

}
}

#endif
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <vector.hpp>
#include <string.hpp>

#include "net/network.hpp"
#include "net/ethernet_layer.hpp"

#include "drivers/rtl8139.hpp"
#include "drivers/pci.hpp"

#include "physical_allocator.hpp"
#include "scheduler.hpp"
#include "logging.hpp"

#include "fs/sysfs.hpp"

#include "tlib/errors.hpp"

#include "net/icmp_layer.hpp"

namespace {
std::vector<network::interface_descriptor> interfaces;

void rx_thread(void* data){
    auto& interface = *reinterpret_cast<network::interface_descriptor*>(data);

    auto pid = scheduler::get_pid();

    logging::logf(logging::log_level::TRACE, "network: RX Thread for interface %u started (pid:%u)\n", interface.id, pid);

    while(true){
        interface.rx_sem.acquire();

        auto packet = interface.rx_queue.pop();
        network::ethernet::decode(interface, packet);
        delete[] packet.payload;
    }
}

void tx_thread(void* data){
    auto& interface = *reinterpret_cast<network::interface_descriptor*>(data);

    auto pid = scheduler::get_pid();

    logging::logf(logging::log_level::TRACE, "network: TX Thread for interface %u started (pid:%u)\n", interface.id, pid);

    while(true){
        interface.tx_sem.acquire();

        auto packet = interface.tx_queue.pop();
        interface.hw_send(interface, packet);
        delete[] packet.payload;
    }
}

} //end of anonymous namespace

void network::init(){
    size_t index = 0;

    for(size_t i = 0; i < pci::number_of_devices(); ++i){
        auto& pci_device = pci::device(i);

        if(pci_device.class_type == pci::device_class_type::NETWORK){
            interfaces.emplace_back();

            auto& interface = interfaces.back();

            interface.id = interfaces.size() - 1;
            interface.name = std::string("net") + std::to_string(index);
            interface.pci_device = i;
            interface.enabled = false;
            interface.driver = "";
            interface.driver_data = nullptr;
            interface.tx_lock.init(1);
            interface.tx_sem.init(0);
            interface.rx_sem.init(0);

            if(pci_device.vendor_id == 0x10EC && pci_device.device_id == 0x8139){
                interface.enabled = true;
                interface.driver = "rtl8139";

                rtl8139::init_driver(interface, pci_device);
            }

            if(interface.enabled){
                //TODO This should be configurable
                interface.ip_address = network::ip::make_address(10, 0, 2, 15);
            }

            auto p = path("/net") / interface.name;

            sysfs::set_constant_value(path("/sys"), p / "name", interface.name);
            sysfs::set_constant_value(path("/sys"), p / "driver", interface.driver);
            sysfs::set_constant_value(path("/sys"), p / "enabled", interface.enabled ? "true" : "false");
            sysfs::set_constant_value(path("/sys"), p / "pci_device", std::to_string(i));
            sysfs::set_constant_value(path("/sys"), p / "mac", std::to_string(interface.mac_address));

            ++index;
        }
    }
}

void network::finalize(){
    for(auto& interface : interfaces){
        // if the interface has a driver
        if(interface.enabled){
            auto* rx_user_stack = new char[scheduler::user_stack_size];
            auto* rx_kernel_stack = new char[scheduler::kernel_stack_size];

            auto* tx_user_stack = new char[scheduler::user_stack_size];
            auto* tx_kernel_stack = new char[scheduler::kernel_stack_size];

            auto& rx_process = scheduler::create_kernel_task_args("net_rx", rx_user_stack, rx_kernel_stack, &rx_thread, &interface);
            auto& tx_process = scheduler::create_kernel_task_args("net_tx", tx_user_stack, tx_kernel_stack, &tx_thread, &interface);

            rx_process.ppid = 1;
            tx_process.ppid = 1;

            rx_process.priority = scheduler::DEFAULT_PRIORITY;
            tx_process.priority = scheduler::DEFAULT_PRIORITY;

            scheduler::queue_system_process(rx_process.pid);
            scheduler::queue_system_process(tx_process.pid);

            interface.tx_thread_pid = tx_process.pid;
            interface.rx_thread_pid = rx_process.pid;
        }
    }
}

size_t network::number_of_interfaces(){
    return interfaces.size();
}

network::interface_descriptor& network::interface(size_t index){
    return interfaces[index];
}

int64_t network::open(network::socket_domain domain, network::socket_type type, network::socket_protocol protocol){
    if(domain != socket_domain::AF_INET){
        return -std::ERROR_SOCKET_INVALID_DOMAIN;
    }

    if(type != socket_type::RAW){
        return -std::ERROR_SOCKET_INVALID_TYPE;
    }

    if(protocol != socket_protocol::ICMP){
        return -std::ERROR_SOCKET_INVALID_PROTOCOL;
    }

    return scheduler::register_new_socket(domain, type, protocol);
}

void network::close(size_t fd){
    if(scheduler::has_socket(fd)){
        scheduler::release_socket(fd);
    }
}

std::tuple<size_t, size_t> network::prepare_packet(size_t socket_fd, void* desc, char* buffer){
    if(!scheduler::has_socket(socket_fd)){
        return {-std::ERROR_SOCKET_INVALID_FD, 0};
    }

    // TODO A socket should be bound to an interface somehow
    if(!network::number_of_interfaces()){
        return {-std::ERROR_SOCKET_NO_INTERFACE, 0};
    }

    auto& interface = network::interface(0);
    auto& socket = scheduler::get_socket(socket_fd);

    switch(socket.protocol){
        case network::socket_protocol::ICMP:
            auto descriptor = static_cast<network::icmp::packet_descriptor*>(desc);
            auto packet = network::icmp::prepare_packet(interface, descriptor->target_ip, descriptor->payload_size, descriptor->type, descriptor->code);
            auto fd = socket.register_packet(packet);

            return {fd, packet.index};
    }

    return {-std::ERROR_SOCKET_UNIMPLEMENTED, 0};
}

int64_t network::finalize_packet(size_t socket_fd, size_t packet_fd){
    if(!scheduler::has_socket(socket_fd)){
        return -std::ERROR_SOCKET_INVALID_FD;
    }

    if(!scheduler::has_socket(packet_fd)){
        return -std::ERROR_SOCKET_INVALID_PACKET_FD;
    }

    auto& interface = network::interface(0);
    auto& socket = scheduler::get_socket(socket_fd);
    auto& packet = socket.get_packet(packet_fd);

    switch(socket.protocol){
        case network::socket_protocol::ICMP:
            network::icmp::finalize_packet(interface, packet);
            socket.erase_packet(packet_fd);

            return 0;
    }

    return -std::ERROR_SOCKET_UNIMPLEMENTED, 0;
}
<commit_msg>Fix finalize_packet<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <vector.hpp>
#include <string.hpp>

#include "net/network.hpp"
#include "net/ethernet_layer.hpp"

#include "drivers/rtl8139.hpp"
#include "drivers/pci.hpp"

#include "physical_allocator.hpp"
#include "scheduler.hpp"
#include "logging.hpp"

#include "fs/sysfs.hpp"

#include "tlib/errors.hpp"

#include "net/icmp_layer.hpp"

namespace {
std::vector<network::interface_descriptor> interfaces;

void rx_thread(void* data){
    auto& interface = *reinterpret_cast<network::interface_descriptor*>(data);

    auto pid = scheduler::get_pid();

    logging::logf(logging::log_level::TRACE, "network: RX Thread for interface %u started (pid:%u)\n", interface.id, pid);

    while(true){
        interface.rx_sem.acquire();

        auto packet = interface.rx_queue.pop();
        network::ethernet::decode(interface, packet);
        delete[] packet.payload;
    }
}

void tx_thread(void* data){
    auto& interface = *reinterpret_cast<network::interface_descriptor*>(data);

    auto pid = scheduler::get_pid();

    logging::logf(logging::log_level::TRACE, "network: TX Thread for interface %u started (pid:%u)\n", interface.id, pid);

    while(true){
        interface.tx_sem.acquire();

        auto packet = interface.tx_queue.pop();
        interface.hw_send(interface, packet);
        delete[] packet.payload;
    }
}

} //end of anonymous namespace

void network::init(){
    size_t index = 0;

    for(size_t i = 0; i < pci::number_of_devices(); ++i){
        auto& pci_device = pci::device(i);

        if(pci_device.class_type == pci::device_class_type::NETWORK){
            interfaces.emplace_back();

            auto& interface = interfaces.back();

            interface.id = interfaces.size() - 1;
            interface.name = std::string("net") + std::to_string(index);
            interface.pci_device = i;
            interface.enabled = false;
            interface.driver = "";
            interface.driver_data = nullptr;
            interface.tx_lock.init(1);
            interface.tx_sem.init(0);
            interface.rx_sem.init(0);

            if(pci_device.vendor_id == 0x10EC && pci_device.device_id == 0x8139){
                interface.enabled = true;
                interface.driver = "rtl8139";

                rtl8139::init_driver(interface, pci_device);
            }

            if(interface.enabled){
                //TODO This should be configurable
                interface.ip_address = network::ip::make_address(10, 0, 2, 15);
            }

            auto p = path("/net") / interface.name;

            sysfs::set_constant_value(path("/sys"), p / "name", interface.name);
            sysfs::set_constant_value(path("/sys"), p / "driver", interface.driver);
            sysfs::set_constant_value(path("/sys"), p / "enabled", interface.enabled ? "true" : "false");
            sysfs::set_constant_value(path("/sys"), p / "pci_device", std::to_string(i));
            sysfs::set_constant_value(path("/sys"), p / "mac", std::to_string(interface.mac_address));

            ++index;
        }
    }
}

void network::finalize(){
    for(auto& interface : interfaces){
        // if the interface has a driver
        if(interface.enabled){
            auto* rx_user_stack = new char[scheduler::user_stack_size];
            auto* rx_kernel_stack = new char[scheduler::kernel_stack_size];

            auto* tx_user_stack = new char[scheduler::user_stack_size];
            auto* tx_kernel_stack = new char[scheduler::kernel_stack_size];

            auto& rx_process = scheduler::create_kernel_task_args("net_rx", rx_user_stack, rx_kernel_stack, &rx_thread, &interface);
            auto& tx_process = scheduler::create_kernel_task_args("net_tx", tx_user_stack, tx_kernel_stack, &tx_thread, &interface);

            rx_process.ppid = 1;
            tx_process.ppid = 1;

            rx_process.priority = scheduler::DEFAULT_PRIORITY;
            tx_process.priority = scheduler::DEFAULT_PRIORITY;

            scheduler::queue_system_process(rx_process.pid);
            scheduler::queue_system_process(tx_process.pid);

            interface.tx_thread_pid = tx_process.pid;
            interface.rx_thread_pid = rx_process.pid;
        }
    }
}

size_t network::number_of_interfaces(){
    return interfaces.size();
}

network::interface_descriptor& network::interface(size_t index){
    return interfaces[index];
}

int64_t network::open(network::socket_domain domain, network::socket_type type, network::socket_protocol protocol){
    if(domain != socket_domain::AF_INET){
        return -std::ERROR_SOCKET_INVALID_DOMAIN;
    }

    if(type != socket_type::RAW){
        return -std::ERROR_SOCKET_INVALID_TYPE;
    }

    if(protocol != socket_protocol::ICMP){
        return -std::ERROR_SOCKET_INVALID_PROTOCOL;
    }

    return scheduler::register_new_socket(domain, type, protocol);
}

void network::close(size_t fd){
    if(scheduler::has_socket(fd)){
        scheduler::release_socket(fd);
    }
}

std::tuple<size_t, size_t> network::prepare_packet(size_t socket_fd, void* desc, char* buffer){
    if(!scheduler::has_socket(socket_fd)){
        return {-std::ERROR_SOCKET_INVALID_FD, 0};
    }

    // TODO A socket should be bound to an interface somehow
    if(!network::number_of_interfaces()){
        return {-std::ERROR_SOCKET_NO_INTERFACE, 0};
    }

    auto& interface = network::interface(0);
    auto& socket = scheduler::get_socket(socket_fd);

    switch(socket.protocol){
        case network::socket_protocol::ICMP:
            auto descriptor = static_cast<network::icmp::packet_descriptor*>(desc);
            auto packet = network::icmp::prepare_packet(interface, descriptor->target_ip, descriptor->payload_size, descriptor->type, descriptor->code);
            auto fd = socket.register_packet(packet);

            return {fd, packet.index};
    }

    return {-std::ERROR_SOCKET_UNIMPLEMENTED, 0};
}

int64_t network::finalize_packet(size_t socket_fd, size_t packet_fd){
    if(!scheduler::has_socket(socket_fd)){
        return -std::ERROR_SOCKET_INVALID_FD;
    }

    auto& interface = network::interface(0);
    auto& socket = scheduler::get_socket(socket_fd);

    if(!socket.has_packet(packet_fd)){
        return -std::ERROR_SOCKET_INVALID_PACKET_FD;
    }

    auto& packet = socket.get_packet(packet_fd);

    switch(socket.protocol){
        case network::socket_protocol::ICMP:
            network::icmp::finalize_packet(interface, packet);
            socket.erase_packet(packet_fd);

            return 0;
    }

    return -std::ERROR_SOCKET_UNIMPLEMENTED, 0;
}
<|endoftext|>


<commit_before>//============================================================================
// include/vsmc/internal/compiler/msvc.hpp
//----------------------------------------------------------------------------
//
//                         vSMC: Scalable Monte Carlo
//
// This file is distribured under the 2-clauses BSD License.
// See LICENSE for details.
//============================================================================

#ifndef VSMC_INTERNAL_COMPILER_MSVC_HPP
#define VSMC_INTERNAL_COMPILER_MSVC_HPP

#define VSMC_MSVC_NONEXIST 1000000UL

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_LONG_LONG
#define VSMC_HAS_CXX11_LONG_LONG 1
#endif
#endif

// C++11 language features

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_ACCESS_CONTROL_SFINAE
#define VSMC_HAS_CXX11_ACCESS_CONTROL_SFINAE 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_ALIAS_TEMPLATES
#define VSMC_HAS_CXX11_ALIAS_TEMPLATES 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_ALIGNAS
#define VSMC_HAS_CXX11_ALIGNAS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_ATTRIBUTES
#define VSMC_HAS_CXX11_ATTRIBUTES 1
#endif
#endif

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_AUTO_TYPE
#define VSMC_HAS_CXX11_AUTO_TYPE 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_CONSTEXPR
#define VSMC_HAS_CXX11_CONSTEXPR 1
#endif
#endif

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_DECLTYPE
#define VSMC_HAS_CXX11_DECLTYPE 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_DEFAULT_FUNCTION_TEMPLATE_ARGS
#define VSMC_HAS_CXX11_DEFAULT_FUNCTION_TEMPLATE_ARGS 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_DEFAULTED_FUNCTIONS
#define VSMC_HAS_CXX11_DEFAULTED_FUNCTIONS 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_DELEGATING_CONSTRUCTORS
#define VSMC_HAS_CXX11_DELEGATING_CONSTRUCTORS 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_DELETED_FUNCTIONS
#define VSMC_HAS_CXX11_DELETED_FUNCTIONS 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_EXPLICIT_CONVERSIONS
#define VSMC_HAS_CXX11_EXPLICIT_CONVERSIONS 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_GENERALIZED_INITIALIZERS
#define VSMC_HAS_CXX11_GENERALIZED_INITIALIZERS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_IMPLICIT_MOVES
#define VSMC_HAS_CXX11_IMPLICIT_MOVES 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_INHERITING_CONSTRUCTORS
#define VSMC_HAS_CXX11_INHERITING_CONSTRUCTORS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_INLINE_NAMESPACES
#define VSMC_HAS_CXX11_INLINE_NAMESPACES 1
#endif
#endif

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_LAMBDAS
#define VSMC_HAS_CXX11_LAMBDAS 1
#endif
#endif

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_LOCAL_TYPE_TEMPLATE_ARGS
#define VSMC_HAS_CXX11_LOCAL_TYPE_TEMPLATE_ARGS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_NOEXCEPT
#define VSMC_HAS_CXX11_NOEXCEPT 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_NONSTATIC_MEMBER_INIT
#define VSMC_HAS_CXX11_NONSTATIC_MEMBER_INIT 1
#endif
#endif

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_NULLPTR
#define VSMC_HAS_CXX11_NULLPTR 1
#endif
#endif

#if _MSC_VER >= 1700
#ifndef VSMC_HAS_CXX11_OVERRIDE_CONTROL
#define VSMC_HAS_CXX11_OVERRIDE_CONTROL 1
#endif
#endif

#if _MSC_VER >= 1700
#ifndef VSMC_HAS_CXX11_RANGE_FOR
#define VSMC_HAS_CXX11_RANGE_FOR 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_RAW_STRING_LITERALS
#define VSMC_HAS_CXX11_RAW_STRING_LITERALS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_REFERENCE_QUALIFIED_FUNCTIONS
#define VSMC_HAS_CXX11_REFERENCE_QUALIFIED_FUNCTIONS 1
#endif
#endif

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_RVALUE_REFERENCES
#define VSMC_HAS_CXX11_RVALUE_REFERENCES 1
#endif
#endif

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_STATIC_ASSERT
#define VSMC_HAS_CXX11_STATIC_ASSERT 1
#endif
#endif

#if _MSC_VER >= 1700
#ifndef VSMC_HAS_CXX11_STRONG_ENUMS
#define VSMC_HAS_CXX11_STRONG_ENUMS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_THREAD_LOCAL
#define VSMC_HAS_CXX11_THREAD_LOCAL 1
#endif
#endif

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_TRAILING_RETURN
#define VSMC_HAS_CXX11_TRAILING_RETURN 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_UNICODE_LITERALS
#define VSMC_HAS_CXX11_UNICODE_LITERALS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_UNRESTRICTED_UNIONS
#define VSMC_HAS_CXX11_UNRESTRICTED_UNIONS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_USER_LITERALS
#define VSMC_HAS_CXX11_USER_LITERALS 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_VARIADIC_TEMPLATES
#define VSMC_HAS_CXX11_VARIADIC_TEMPLATES 1
#endif
#endif

// C++11 library features

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11LIB_CHRONO
#define VSMC_HAS_CXX11LIB_CHRONO 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11LIB_CMATH
#define VSMC_HAS_CXX11LIB_CMATH 1
#endif
#endif

#if _MSC_VER >= 1700
#ifndef VSMC_HAS_CXX11LIB_FUNCTIONAL
#define VSMC_HAS_CXX11LIB_FUNCTIONAL 1
#endif
#endif

#if _MSC_VER >= 1700
#ifndef VSMC_HAS_CXX11LIB_FUTURE
#define VSMC_HAS_CXX11LIB_FUTURE 1
#endif
#endif

#if _MSC_VER >= 1700
#ifndef VSMC_HAS_CXX11LIB_MUTEX
#define VSMC_HAS_CXX11LIB_MUTEX 1
#endif
#endif

#if _MSC_VER >= 1700
#ifndef VSMC_HAS_CXX11LIB_RANDOM
#define VSMC_HAS_CXX11LIB_RANDOM 1
#endif
#endif

#if _MSC_VER >= 1700
#ifndef VSMC_HAS_CXX11LIB_THREAD
#define VSMC_HAS_CXX11LIB_THREAD 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11LIB_TUPLE
#define VSMC_HAS_CXX11LIB_TUPLE 1
#endif
#endif

// C99 library features

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_C99LIB_MATH
#define VSMC_HAS_C99LIB_MATH 1
#endif
#endif

// Target specific features

#ifndef VSMC_HAS_INTRINSIC_INT64
#define VSMC_HAS_INTRINSIC_INT64 1
#endif

#ifndef VSMC_HAS_INTRINSIC_INT64_LONG_LONG
#define VSMC_HAS_INTRINSIC_INT64_LONG_LONG 0
#endif

#endif // VSMC_INTERNAL_COMPILER_MSVC_HPP
<commit_msg>disable imcomplete defaulted and deleted functions<commit_after>//============================================================================
// include/vsmc/internal/compiler/msvc.hpp
//----------------------------------------------------------------------------
//
//                         vSMC: Scalable Monte Carlo
//
// This file is distribured under the 2-clauses BSD License.
// See LICENSE for details.
//============================================================================

#ifndef VSMC_INTERNAL_COMPILER_MSVC_HPP
#define VSMC_INTERNAL_COMPILER_MSVC_HPP

#define VSMC_MSVC_NONEXIST 1000000UL

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_LONG_LONG
#define VSMC_HAS_CXX11_LONG_LONG 1
#endif
#endif

// C++11 language features

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_ACCESS_CONTROL_SFINAE
#define VSMC_HAS_CXX11_ACCESS_CONTROL_SFINAE 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_ALIAS_TEMPLATES
#define VSMC_HAS_CXX11_ALIAS_TEMPLATES 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_ALIGNAS
#define VSMC_HAS_CXX11_ALIGNAS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_ATTRIBUTES
#define VSMC_HAS_CXX11_ATTRIBUTES 1
#endif
#endif

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_AUTO_TYPE
#define VSMC_HAS_CXX11_AUTO_TYPE 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_CONSTEXPR
#define VSMC_HAS_CXX11_CONSTEXPR 1
#endif
#endif

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_DECLTYPE
#define VSMC_HAS_CXX11_DECLTYPE 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_DEFAULT_FUNCTION_TEMPLATE_ARGS
#define VSMC_HAS_CXX11_DEFAULT_FUNCTION_TEMPLATE_ARGS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_DEFAULTED_FUNCTIONS
#define VSMC_HAS_CXX11_DEFAULTED_FUNCTIONS 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_DELEGATING_CONSTRUCTORS
#define VSMC_HAS_CXX11_DELEGATING_CONSTRUCTORS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_DELETED_FUNCTIONS
#define VSMC_HAS_CXX11_DELETED_FUNCTIONS 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_EXPLICIT_CONVERSIONS
#define VSMC_HAS_CXX11_EXPLICIT_CONVERSIONS 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_GENERALIZED_INITIALIZERS
#define VSMC_HAS_CXX11_GENERALIZED_INITIALIZERS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_IMPLICIT_MOVES
#define VSMC_HAS_CXX11_IMPLICIT_MOVES 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_INHERITING_CONSTRUCTORS
#define VSMC_HAS_CXX11_INHERITING_CONSTRUCTORS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_INLINE_NAMESPACES
#define VSMC_HAS_CXX11_INLINE_NAMESPACES 1
#endif
#endif

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_LAMBDAS
#define VSMC_HAS_CXX11_LAMBDAS 1
#endif
#endif

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_LOCAL_TYPE_TEMPLATE_ARGS
#define VSMC_HAS_CXX11_LOCAL_TYPE_TEMPLATE_ARGS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_NOEXCEPT
#define VSMC_HAS_CXX11_NOEXCEPT 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_NONSTATIC_MEMBER_INIT
#define VSMC_HAS_CXX11_NONSTATIC_MEMBER_INIT 1
#endif
#endif

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_NULLPTR
#define VSMC_HAS_CXX11_NULLPTR 1
#endif
#endif

#if _MSC_VER >= 1700
#ifndef VSMC_HAS_CXX11_OVERRIDE_CONTROL
#define VSMC_HAS_CXX11_OVERRIDE_CONTROL 1
#endif
#endif

#if _MSC_VER >= 1700
#ifndef VSMC_HAS_CXX11_RANGE_FOR
#define VSMC_HAS_CXX11_RANGE_FOR 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_RAW_STRING_LITERALS
#define VSMC_HAS_CXX11_RAW_STRING_LITERALS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_REFERENCE_QUALIFIED_FUNCTIONS
#define VSMC_HAS_CXX11_REFERENCE_QUALIFIED_FUNCTIONS 1
#endif
#endif

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_RVALUE_REFERENCES
#define VSMC_HAS_CXX11_RVALUE_REFERENCES 1
#endif
#endif

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_STATIC_ASSERT
#define VSMC_HAS_CXX11_STATIC_ASSERT 1
#endif
#endif

#if _MSC_VER >= 1700
#ifndef VSMC_HAS_CXX11_STRONG_ENUMS
#define VSMC_HAS_CXX11_STRONG_ENUMS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_THREAD_LOCAL
#define VSMC_HAS_CXX11_THREAD_LOCAL 1
#endif
#endif

#if _MSC_VER >= 1600
#ifndef VSMC_HAS_CXX11_TRAILING_RETURN
#define VSMC_HAS_CXX11_TRAILING_RETURN 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_UNICODE_LITERALS
#define VSMC_HAS_CXX11_UNICODE_LITERALS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_UNRESTRICTED_UNIONS
#define VSMC_HAS_CXX11_UNRESTRICTED_UNIONS 1
#endif
#endif

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11_USER_LITERALS
#define VSMC_HAS_CXX11_USER_LITERALS 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11_VARIADIC_TEMPLATES
#define VSMC_HAS_CXX11_VARIADIC_TEMPLATES 1
#endif
#endif

// C++11 library features

#if _MSC_VER >= VSMC_MSVC_NONEXIST
#ifndef VSMC_HAS_CXX11LIB_CHRONO
#define VSMC_HAS_CXX11LIB_CHRONO 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11LIB_CMATH
#define VSMC_HAS_CXX11LIB_CMATH 1
#endif
#endif

#if _MSC_VER >= 1700
#ifndef VSMC_HAS_CXX11LIB_FUNCTIONAL
#define VSMC_HAS_CXX11LIB_FUNCTIONAL 1
#endif
#endif

#if _MSC_VER >= 1700
#ifndef VSMC_HAS_CXX11LIB_FUTURE
#define VSMC_HAS_CXX11LIB_FUTURE 1
#endif
#endif

#if _MSC_VER >= 1700
#ifndef VSMC_HAS_CXX11LIB_MUTEX
#define VSMC_HAS_CXX11LIB_MUTEX 1
#endif
#endif

#if _MSC_VER >= 1700
#ifndef VSMC_HAS_CXX11LIB_RANDOM
#define VSMC_HAS_CXX11LIB_RANDOM 1
#endif
#endif

#if _MSC_VER >= 1700
#ifndef VSMC_HAS_CXX11LIB_THREAD
#define VSMC_HAS_CXX11LIB_THREAD 1
#endif
#endif

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_CXX11LIB_TUPLE
#define VSMC_HAS_CXX11LIB_TUPLE 1
#endif
#endif

// C99 library features

#if _MSC_VER >= 1800
#ifndef VSMC_HAS_C99LIB_MATH
#define VSMC_HAS_C99LIB_MATH 1
#endif
#endif

// Target specific features

#ifndef VSMC_HAS_INTRINSIC_INT64
#define VSMC_HAS_INTRINSIC_INT64 1
#endif

#ifndef VSMC_HAS_INTRINSIC_INT64_LONG_LONG
#define VSMC_HAS_INTRINSIC_INT64_LONG_LONG 0
#endif

#endif // VSMC_INTERNAL_COMPILER_MSVC_HPP
<|endoftext|>