<commit_before>// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <fstream>
#include <string>
#include <vector>
#include <exception>
#include <iomanip>
// StdAir
#include <stdair/stdair_demand_types.hpp>
#include <stdair/basic/ProgressStatusSet.hpp>
#include <stdair/bom/EventStruct.hpp>
#include <stdair/bom/EventQueue.hpp>
#include <stdair/bom/BookingRequestStruct.hpp>
#include <stdair/bom/SnapshotStruct.hpp>
#include <stdair/bom/CancellationStruct.hpp>
#include <stdair/bom/RMEventStruct.hpp>
#include <stdair/bom/TravelSolutionStruct.hpp>
#include <stdair/service/Logger.hpp>
#include <stdair/STDAIR_Service.hpp>
// Distribution
#include <simcrs/SIMCRS_Service.hpp>
// TRADEMGEN
#include <trademgen/TRADEMGEN_Service.hpp>
// TRAVELCCM
#include <travelccm/TRAVELCCM_Service.hpp>
// Airsched
#include <airsched/AIRSCHED_Service.hpp>
// Dsim
#include <dsim/DSIM_Types.hpp>
#include <dsim/command/Simulator.hpp>

namespace DSIM {

  // ////////////////////////////////////////////////////////////////////
  void Simulator::simulate (SIMCRS::SIMCRS_Service& ioSIMCRS_Service,
                            TRADEMGEN::TRADEMGEN_Service& ioTRADEMGEN_Service,
                            TRAVELCCM::TRAVELCCM_Service& ioTRAVELCCM_Service,
                            stdair::STDAIR_Service& ioSTDAIR_Service,
                            const stdair::DemandGenerationMethod& iDemandGenerationMethod,
                            const stdair::ForecastingMethod& iForecastingMethod,
                            const stdair::PartnershipTechnique& iPartnershipTechnique) {

    // DEBUG
    STDAIR_LOG_DEBUG ("The simulation is starting");

    // Retrieve the expected (mean value of the) number of events to be
    // generated
    //const stdair::Count_T& lExpectedNbOfEventsToBeGenerated =
      //ioTRADEMGEN_Service.getExpectedTotalNumberOfRequestsToBeGenerated();

    /**
       Initialisation step.

Generate the first event for each demand stream.
    */
    const stdair::Count_T& lActualNbOfEventsToBeGenerated =
      ioTRADEMGEN_Service.generateFirstRequests(iDemandGenerationMethod);

    // Initialise the (Boost) progress display object
    // boost::progress_display lProgressDisplay(lActualNbOfEventsToBeGenerated);

    // DEBUG
    //STDAIR_LOG_DEBUG ("Expected number of events: "
      //                << lExpectedNbOfEventsToBeGenerated << ", actual: "
        //              << lActualNbOfEventsToBeGenerated);

    /**
       Main loop.

Pop a request and get its associated type/demand stream.

Generate the next request for the same type/demand stream.

    */
    while (ioSTDAIR_Service.isQueueDone() == false) {

      // Get the next event from the event queue
      stdair::EventStruct lEventStruct;
      stdair::ProgressStatusSet lPSS = ioSTDAIR_Service.popEvent (lEventStruct);

      // DEBUG
      // STDAIR_LOG_DEBUG ("Poped event: '" << lEventStruct.describe() << "'.");

      // Check the event type
      const stdair::EventType::EN_EventType& lEventType =
        lEventStruct.getEventType();

      switch (lEventType) {
      case stdair::EventType::BKG_REQ: playBookingRequest (ioSIMCRS_Service,
                                                           ioTRADEMGEN_Service,
                                                           ioTRAVELCCM_Service,
                                                           lEventStruct,
                                                           lPSS,
                                                           iDemandGenerationMethod,
                                                           iPartnershipTechnique); break;
      case stdair::EventType::CX: playCancellation (ioSIMCRS_Service,
                                                    lEventStruct); break;
      case stdair::EventType::SNAPSHOT: playSnapshotEvent (ioSIMCRS_Service,
                                                           lEventStruct); break;
      case stdair::EventType::RM: playRMEvent (ioSIMCRS_Service,
                                               lEventStruct,
                                               iForecastingMethod,
                                               iPartnershipTechnique); break;
      default: assert (false); break;
      }

      // Update the progress display
      // ++lProgressDisplay;
    }

    // DEBUG
    STDAIR_LOG_DEBUG ("The simulation has ended");
  }

  // ////////////////////////////////////////////////////////////////////
  void Simulator::
  playBookingRequest (SIMCRS::SIMCRS_Service& ioSIMCRS_Service,
                      TRADEMGEN::TRADEMGEN_Service& ioTRADEMGEN_Service,
                      TRAVELCCM::TRAVELCCM_Service& ioTRAVELCCM_Service,
                      const stdair::EventStruct& iEventStruct,
                      stdair::ProgressStatusSet& ioPSS,
                      const stdair::DemandGenerationMethod& iDemandGenerationMethod,
                      const stdair::PartnershipTechnique& iPartnershipTechnique) {
    // Extract the corresponding demand/booking request
    const stdair::BookingRequestStruct& lPoppedRequest =
      iEventStruct.getBookingRequest();

    // Check if the request if valid
    const stdair::Date_T& lDepDate = lPoppedRequest.getPreferedDepartureDate();
    const stdair::DateTime_T& lReqTime = lPoppedRequest.getRequestDateTime();
    const stdair::Date_T& lRegDate = lReqTime.date();
    if (lDepDate > lRegDate) {
      // DEBUG
      STDAIR_LOG_DEBUG ("Poped booking request: '" << lPoppedRequest.describe()
                        << "'.");

      // Retrieve the corresponding demand stream
      const stdair::DemandGeneratorKey_T& lDemandStreamKey =
        lPoppedRequest.getDemandGeneratorKey();

      // Assess whether more events should be generated for that demand stream
      const bool stillHavingRequestsToBeGenerated =
        ioTRADEMGEN_Service.stillHavingRequestsToBeGenerated (lDemandStreamKey,
                                                              ioPSS,
                                                              iDemandGenerationMethod);

      // DEBUG
      // STDAIR_LOG_DEBUG ("=> [" << lDemandStreamKey << "] is now processed. "
      //                   << "Still generate events for that demand stream? "
      //                   << stillHavingRequestsToBeGenerated);
      STDAIR_LOG_DEBUG ("Progress status" << ioPSS.describe());

      // If there are still events to be generated for that demand stream,
      // generate and add them to the event queue
      if (stillHavingRequestsToBeGenerated) {
      stdair::BookingRequestPtr_T lNextRequest_ptr =
        ioTRADEMGEN_Service.generateNextRequest (lDemandStreamKey,
                                                 iDemandGenerationMethod);
      assert (lNextRequest_ptr != NULL);

      // Sanity check
      const stdair::Duration_T lDuration =
        lNextRequest_ptr->getRequestDateTime()
        - lPoppedRequest.getRequestDateTime();
        if (lDuration.total_milliseconds() < 0) {
          STDAIR_LOG_NOTIFICATION ("[" << lDemandStreamKey
                                   << "] The date-time of the generated event ("
                                   << lNextRequest_ptr->getRequestDateTime()
                                   << ") is lower than the date-time "
                                   << "of the current event ("
                                   << lPoppedRequest.getRequestDateTime()
                                   << ")");
          assert (false);
        }

        // DEBUG
        // STDAIR_LOG_DEBUG ("[" << lDemandStreamKey << "] Added request: '"
        //                   << lNextRequest_ptr->describe()
        //                   << "'. Is queue done? "
        //                   << ioTRADEMGEN_Service.isQueueDone());
      }

      // Retrieve a list of travel solutions corresponding the given
      // booking request.
      stdair::TravelSolutionList_T lTravelSolutionList =
        ioSIMCRS_Service.calculateSegmentPathList (lPoppedRequest);

      if (lTravelSolutionList.empty() == false) {
        // Get the availability for each travel solution.
        ioSIMCRS_Service.calculateAvailability (lTravelSolutionList, iPartnershipTechnique);

        // Get the fare quote for each travel solution.
        ioSIMCRS_Service.fareQuote (lPoppedRequest, lTravelSolutionList);

        // Get a travel solution choice.
        const stdair::TravelSolutionStruct* lChosenTS_ptr =
          ioTRAVELCCM_Service.chooseTravelSolution (lTravelSolutionList,
                                                    lPoppedRequest);
        if (lChosenTS_ptr != NULL) {
          // DEBUG
          STDAIR_LOG_DEBUG ("Chosen TS: " << lChosenTS_ptr->describe());

          // Retrieve and convert the party size
          const stdair::NbOfSeats_T& lPartySizeDouble =
            lPoppedRequest.getPartySize();
          const stdair::PartySize_T lPartySize = std::floor (lPartySizeDouble);

          // Delegate the sell to the corresponding SimCRS service
          bool saleSucceedful =
            ioSIMCRS_Service.sell (*lChosenTS_ptr, lPartySize);

          // If the sale succeeded, generate the potential cancellation event.
          if (saleSucceedful == true) {
            ioTRADEMGEN_Service.generateCancellation (*lChosenTS_ptr,
                                                      lPartySize, lReqTime,
                                                      lDepDate);
          }

          // LOG
          const stdair::DateTime_T lDepartureDateTime =
            boost::posix_time::ptime (lDepDate, boost::posix_time::hours (0));
          const stdair::Duration_T lDTDRequest = lReqTime - lDepartureDateTime;
          const double lDTD = double(lDTDRequest.total_seconds()) / 86400.0;
          std::ostringstream oStr;
          const stdair::SegmentPath_T& lSegmentPath =
            lChosenTS_ptr->getSegmentPath();
          for (stdair::SegmentPath_T::const_iterator itSegPath =
                 lSegmentPath.begin();
               itSegPath != lSegmentPath.end(); ++itSegPath) {
            oStr << *itSegPath <<  ";";
          }
          STDAIR_LOG_NOTIFICATION (oStr.str() << std::setprecision(10) << lDTD);
        }
        else {
          // DEBUG
          STDAIR_LOG_DEBUG ("There is no chosen travel solution "
                            <<"for this request: "<< lPoppedRequest.describe());
        }
      } else {
        // DEBUG
        STDAIR_LOG_DEBUG ("No travel solution has been found for: "
                          << lPoppedRequest);
      }
    }
  }

  // ////////////////////////////////////////////////////////////////////
  void Simulator::
  playCancellation (SIMCRS::SIMCRS_Service& ioSIMCRS_Service,
                    const stdair::EventStruct& iEventStruct) {
    // Retrieve the cancellation struct from the event.
    const stdair::CancellationStruct lCancellationStruct =
      iEventStruct.getCancellation();

    // DEBUG
    // STDAIR_LOG_DEBUG ("Play cancellation: "<<lCancellationStruct.describe());

    ioSIMCRS_Service.playCancellation (lCancellationStruct);
  }

  // ////////////////////////////////////////////////////////////////////
  void Simulator::
  playSnapshotEvent (SIMCRS::SIMCRS_Service& ioSIMCRS_Service,
                     const stdair::EventStruct& iEventStruct) {
    // Retrieve the snapshot struct from the event.
    const stdair::SnapshotStruct lSnapshotStruct =
      iEventStruct.getSnapshotStruct();

    // DEBUG
    // STDAIR_LOG_DEBUG ("Taking snapshots: " << lSnapshotStruct.describe());

    ioSIMCRS_Service.takeSnapshots (lSnapshotStruct);
  }

  // ////////////////////////////////////////////////////////////////////
  void Simulator::
  playRMEvent (SIMCRS::SIMCRS_Service& ioSIMCRS_Service,
               const stdair::EventStruct& iEventStruct,
               const stdair::ForecastingMethod& iForecastingMethod,
               const stdair::PartnershipTechnique& iPartnershipTechnique) {
    // Retrieve the RM event struct from the event.
    const stdair::RMEventStruct lRMEvent = iEventStruct.getRMEvent();

    // DEBUG
    STDAIR_LOG_DEBUG ("Running RM system: " << lRMEvent.describe());

    ioSIMCRS_Service.optimise (lRMEvent, iForecastingMethod, iPartnershipTechnique);
  }
}
<commit_msg>[Dev] Fixed a warning in the Simulator command (however, the code surely needs more work at that place).<commit_after>// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <fstream>
#include <string>
#include <vector>
#include <exception>
#include <iomanip>
// StdAir
#include <stdair/stdair_demand_types.hpp>
#include <stdair/basic/ProgressStatusSet.hpp>
#include <stdair/bom/EventStruct.hpp>
#include <stdair/bom/EventQueue.hpp>
#include <stdair/bom/BookingRequestStruct.hpp>
#include <stdair/bom/SnapshotStruct.hpp>
#include <stdair/bom/CancellationStruct.hpp>
#include <stdair/bom/RMEventStruct.hpp>
#include <stdair/bom/TravelSolutionStruct.hpp>
#include <stdair/service/Logger.hpp>
#include <stdair/STDAIR_Service.hpp>
// Distribution
#include <simcrs/SIMCRS_Service.hpp>
// TRADEMGEN
#include <trademgen/TRADEMGEN_Service.hpp>
// TRAVELCCM
#include <travelccm/TRAVELCCM_Service.hpp>
// Airsched
#include <airsched/AIRSCHED_Service.hpp>
// Dsim
#include <dsim/DSIM_Types.hpp>
#include <dsim/command/Simulator.hpp>

namespace DSIM {

  // ////////////////////////////////////////////////////////////////////
  void Simulator::simulate (SIMCRS::SIMCRS_Service& ioSIMCRS_Service,
                            TRADEMGEN::TRADEMGEN_Service& ioTRADEMGEN_Service,
                            TRAVELCCM::TRAVELCCM_Service& ioTRAVELCCM_Service,
                            stdair::STDAIR_Service& ioSTDAIR_Service,
                            const stdair::DemandGenerationMethod& iDemandGenerationMethod,
                            const stdair::ForecastingMethod& iForecastingMethod,
                            const stdair::PartnershipTechnique& iPartnershipTechnique) {

    // DEBUG
    STDAIR_LOG_DEBUG ("The simulation is starting");

    // Retrieve the expected (mean value of the) number of events to be
    // generated
    //const stdair::Count_T& lExpectedNbOfEventsToBeGenerated =
      //ioTRADEMGEN_Service.getExpectedTotalNumberOfRequestsToBeGenerated();

    /**
       Initialisation step.

Generate the first event for each demand stream.
    */
    //const stdair::Count_T& lActualNbOfEventsToBeGenerated =
    //  ioTRADEMGEN_Service.generateFirstRequests(iDemandGenerationMethod);

    // Initialise the (Boost) progress display object
    // boost::progress_display lProgressDisplay(lActualNbOfEventsToBeGenerated);

    // DEBUG
    //STDAIR_LOG_DEBUG ("Expected number of events: "
      //                << lExpectedNbOfEventsToBeGenerated << ", actual: "
        //              << lActualNbOfEventsToBeGenerated);

    /**
       Main loop.

Pop a request and get its associated type/demand stream.

Generate the next request for the same type/demand stream.

    */
    while (ioSTDAIR_Service.isQueueDone() == false) {

      // Get the next event from the event queue
      stdair::EventStruct lEventStruct;
      stdair::ProgressStatusSet lPSS = ioSTDAIR_Service.popEvent (lEventStruct);

      // DEBUG
      // STDAIR_LOG_DEBUG ("Poped event: '" << lEventStruct.describe() << "'.");

      // Check the event type
      const stdair::EventType::EN_EventType& lEventType =
        lEventStruct.getEventType();

      switch (lEventType) {
      case stdair::EventType::BKG_REQ: playBookingRequest (ioSIMCRS_Service,
                                                           ioTRADEMGEN_Service,
                                                           ioTRAVELCCM_Service,
                                                           lEventStruct,
                                                           lPSS,
                                                           iDemandGenerationMethod,
                                                           iPartnershipTechnique); break;
      case stdair::EventType::CX: playCancellation (ioSIMCRS_Service,
                                                    lEventStruct); break;
      case stdair::EventType::SNAPSHOT: playSnapshotEvent (ioSIMCRS_Service,
                                                           lEventStruct); break;
      case stdair::EventType::RM: playRMEvent (ioSIMCRS_Service,
                                               lEventStruct,
                                               iForecastingMethod,
                                               iPartnershipTechnique); break;
      default: assert (false); break;
      }

      // Update the progress display
      // ++lProgressDisplay;
    }

    // DEBUG
    STDAIR_LOG_DEBUG ("The simulation has ended");
  }

  // ////////////////////////////////////////////////////////////////////
  void Simulator::
  playBookingRequest (SIMCRS::SIMCRS_Service& ioSIMCRS_Service,
                      TRADEMGEN::TRADEMGEN_Service& ioTRADEMGEN_Service,
                      TRAVELCCM::TRAVELCCM_Service& ioTRAVELCCM_Service,
                      const stdair::EventStruct& iEventStruct,
                      stdair::ProgressStatusSet& ioPSS,
                      const stdair::DemandGenerationMethod& iDemandGenerationMethod,
                      const stdair::PartnershipTechnique& iPartnershipTechnique) {
    // Extract the corresponding demand/booking request
    const stdair::BookingRequestStruct& lPoppedRequest =
      iEventStruct.getBookingRequest();

    // Check if the request if valid
    const stdair::Date_T& lDepDate = lPoppedRequest.getPreferedDepartureDate();
    const stdair::DateTime_T& lReqTime = lPoppedRequest.getRequestDateTime();
    const stdair::Date_T& lRegDate = lReqTime.date();
    if (lDepDate > lRegDate) {
      // DEBUG
      STDAIR_LOG_DEBUG ("Poped booking request: '" << lPoppedRequest.describe()
                        << "'.");

      // Retrieve the corresponding demand stream
      const stdair::DemandGeneratorKey_T& lDemandStreamKey =
        lPoppedRequest.getDemandGeneratorKey();

      // Assess whether more events should be generated for that demand stream
      const bool stillHavingRequestsToBeGenerated =
        ioTRADEMGEN_Service.stillHavingRequestsToBeGenerated (lDemandStreamKey,
                                                              ioPSS,
                                                              iDemandGenerationMethod);

      // DEBUG
      // STDAIR_LOG_DEBUG ("=> [" << lDemandStreamKey << "] is now processed. "
      //                   << "Still generate events for that demand stream? "
      //                   << stillHavingRequestsToBeGenerated);
      STDAIR_LOG_DEBUG ("Progress status" << ioPSS.describe());

      // If there are still events to be generated for that demand stream,
      // generate and add them to the event queue
      if (stillHavingRequestsToBeGenerated) {
      stdair::BookingRequestPtr_T lNextRequest_ptr =
        ioTRADEMGEN_Service.generateNextRequest (lDemandStreamKey,
                                                 iDemandGenerationMethod);
      assert (lNextRequest_ptr != NULL);

      // Sanity check
      const stdair::Duration_T lDuration =
        lNextRequest_ptr->getRequestDateTime()
        - lPoppedRequest.getRequestDateTime();
        if (lDuration.total_milliseconds() < 0) {
          STDAIR_LOG_NOTIFICATION ("[" << lDemandStreamKey
                                   << "] The date-time of the generated event ("
                                   << lNextRequest_ptr->getRequestDateTime()
                                   << ") is lower than the date-time "
                                   << "of the current event ("
                                   << lPoppedRequest.getRequestDateTime()
                                   << ")");
          assert (false);
        }

        // DEBUG
        // STDAIR_LOG_DEBUG ("[" << lDemandStreamKey << "] Added request: '"
        //                   << lNextRequest_ptr->describe()
        //                   << "'. Is queue done? "
        //                   << ioTRADEMGEN_Service.isQueueDone());
      }

      // Retrieve a list of travel solutions corresponding the given
      // booking request.
      stdair::TravelSolutionList_T lTravelSolutionList =
        ioSIMCRS_Service.calculateSegmentPathList (lPoppedRequest);

      if (lTravelSolutionList.empty() == false) {
        // Get the availability for each travel solution.
        ioSIMCRS_Service.calculateAvailability (lTravelSolutionList, iPartnershipTechnique);

        // Get the fare quote for each travel solution.
        ioSIMCRS_Service.fareQuote (lPoppedRequest, lTravelSolutionList);

        // Get a travel solution choice.
        const stdair::TravelSolutionStruct* lChosenTS_ptr =
          ioTRAVELCCM_Service.chooseTravelSolution (lTravelSolutionList,
                                                    lPoppedRequest);
        if (lChosenTS_ptr != NULL) {
          // DEBUG
          STDAIR_LOG_DEBUG ("Chosen TS: " << lChosenTS_ptr->describe());

          // Retrieve and convert the party size
          const stdair::NbOfSeats_T& lPartySizeDouble =
            lPoppedRequest.getPartySize();
          const stdair::PartySize_T lPartySize = std::floor (lPartySizeDouble);

          // Delegate the sell to the corresponding SimCRS service
          bool saleSucceedful =
            ioSIMCRS_Service.sell (*lChosenTS_ptr, lPartySize);

          // If the sale succeeded, generate the potential cancellation event.
          if (saleSucceedful == true) {
            ioTRADEMGEN_Service.generateCancellation (*lChosenTS_ptr,
                                                      lPartySize, lReqTime,
                                                      lDepDate);
          }

          // LOG
          const stdair::DateTime_T lDepartureDateTime =
            boost::posix_time::ptime (lDepDate, boost::posix_time::hours (0));
          const stdair::Duration_T lDTDRequest = lReqTime - lDepartureDateTime;
          const double lDTD = double(lDTDRequest.total_seconds()) / 86400.0;
          std::ostringstream oStr;
          const stdair::SegmentPath_T& lSegmentPath =
            lChosenTS_ptr->getSegmentPath();
          for (stdair::SegmentPath_T::const_iterator itSegPath =
                 lSegmentPath.begin();
               itSegPath != lSegmentPath.end(); ++itSegPath) {
            oStr << *itSegPath <<  ";";
          }
          STDAIR_LOG_NOTIFICATION (oStr.str() << std::setprecision(10) << lDTD);
        }
        else {
          // DEBUG
          STDAIR_LOG_DEBUG ("There is no chosen travel solution "
                            <<"for this request: "<< lPoppedRequest.describe());
        }
      } else {
        // DEBUG
        STDAIR_LOG_DEBUG ("No travel solution has been found for: "
                          << lPoppedRequest);
      }
    }
  }

  // ////////////////////////////////////////////////////////////////////
  void Simulator::
  playCancellation (SIMCRS::SIMCRS_Service& ioSIMCRS_Service,
                    const stdair::EventStruct& iEventStruct) {
    // Retrieve the cancellation struct from the event.
    const stdair::CancellationStruct lCancellationStruct =
      iEventStruct.getCancellation();

    // DEBUG
    // STDAIR_LOG_DEBUG ("Play cancellation: "<<lCancellationStruct.describe());

    ioSIMCRS_Service.playCancellation (lCancellationStruct);
  }

  // ////////////////////////////////////////////////////////////////////
  void Simulator::
  playSnapshotEvent (SIMCRS::SIMCRS_Service& ioSIMCRS_Service,
                     const stdair::EventStruct& iEventStruct) {
    // Retrieve the snapshot struct from the event.
    const stdair::SnapshotStruct lSnapshotStruct =
      iEventStruct.getSnapshotStruct();

    // DEBUG
    // STDAIR_LOG_DEBUG ("Taking snapshots: " << lSnapshotStruct.describe());

    ioSIMCRS_Service.takeSnapshots (lSnapshotStruct);
  }

  // ////////////////////////////////////////////////////////////////////
  void Simulator::
  playRMEvent (SIMCRS::SIMCRS_Service& ioSIMCRS_Service,
               const stdair::EventStruct& iEventStruct,
               const stdair::ForecastingMethod& iForecastingMethod,
               const stdair::PartnershipTechnique& iPartnershipTechnique) {
    // Retrieve the RM event struct from the event.
    const stdair::RMEventStruct lRMEvent = iEventStruct.getRMEvent();

    // DEBUG
    STDAIR_LOG_DEBUG ("Running RM system: " << lRMEvent.describe());

    ioSIMCRS_Service.optimise (lRMEvent, iForecastingMethod, iPartnershipTechnique);
  }
}
<|endoftext|>


<commit_before>// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#pragma once

#ifndef NAZARA_TASKSCHEDULER_HPP
#define NAZARA_TASKSCHEDULER_HPP

#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Functor.hpp>

class NAZARA_API NzTaskScheduler
{
	public:
		template<typename F> static void AddTask(F function);
		template<typename F, typename... Args> static void AddTask(F function, Args... args);
		template<typename C> static void AddTask(void (C::*function)(), C* object);
		static unsigned int GetWorkerCount();
		static bool Initialize();
		static void Uninitialize();
		static void WaitForTasks();

	private:
		static void AddTaskFunctor(NzFunctor* taskFunctor);
};

#include <Nazara/Core/TaskScheduler.inl>

#endif // NAZARA_TASKSCHEDULER_HPP
<commit_msg>Deleted TaskScheduler constructor/destructor<commit_after>// Copyright (C) 2012 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#pragma once

#ifndef NAZARA_TASKSCHEDULER_HPP
#define NAZARA_TASKSCHEDULER_HPP

#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Functor.hpp>

class NAZARA_API NzTaskScheduler
{
	public:
		NzTaskScheduler() = delete;
		~NzTaskScheduler() = delete;

		template<typename F> static void AddTask(F function);
		template<typename F, typename... Args> static void AddTask(F function, Args... args);
		template<typename C> static void AddTask(void (C::*function)(), C* object);
		static unsigned int GetWorkerCount();
		static bool Initialize();
		static void Uninitialize();
		static void WaitForTasks();

	private:
		static void AddTaskFunctor(NzFunctor* taskFunctor);
};

#include <Nazara/Core/TaskScheduler.inl>

#endif // NAZARA_TASKSCHEDULER_HPP
<|endoftext|>


<commit_before><commit_msg>glTF: crash after starting a model without an OpenGL window<commit_after><|endoftext|>


<commit_before>/****************************************************************************/
/* Copyright 2005-2006, Francis Russell                                     */
/*                                                                          */
/* Licensed under the Apache License, Version 2.0 (the License);            */
/* you may not use this file except in compliance with the License.         */
/* You may obtain a copy of the License at                                  */
/*                                                                          */
/*     http://www.apache.org/licenses/LICENSE-2.0                           */
/*                                                                          */
/* Unless required by applicable law or agreed to in writing, software      */
/* distributed under the License is distributed on an AS IS BASIS,          */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and      */
/* limitations under the License.                                           */
/*                                                                          */
/****************************************************************************/

#ifndef DESOLIN_TG_EXPRESSION_NODE_HPP
#define DESOLIN_TG_EXPRESSION_NODE_HPP

#include <set>
#include <map>
#include <string>
#include <cassert>
#include <cstddef>
#include <memory>
#include <boost/functional/hash.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/variant.hpp>
#include <boost/foreach.hpp>
#include <desolin/tg/Desolin_tg_fwd.hpp>

namespace desolin
{

namespace detail
{

template<typename exprType>
class TGElementIndex
{
};

template<>
class TGElementIndex<tg_vector>
{
private:
  const std::size_t row;

public:
  TGElementIndex(const std::size_t r) : row(r)
  {
  }

  TGElementIndex(const ElementIndex<vector>& index) : row(index.getRow())
  {
  }

  const inline std::size_t getRow() const
  {
    return row;
  }

  inline bool operator==(const TGElementIndex& i) const
  {
    return row == i.row;
  }

  inline bool operator<(const TGElementIndex& i) const
  {
    return row < i.row;
  }
};

std::size_t hash_value(const TGElementIndex<tg_vector>& index)
{
  return boost::hash<int>()(index.getRow());
}

template<>
class TGElementIndex<tg_matrix>
{
private:
  const std::size_t row;
  const std::size_t col;

public:
  TGElementIndex(const std::size_t r, const std::size_t c) : row(r), col(c)
  {
  }

  TGElementIndex(const ElementIndex<matrix>& index) : row(index.getRow()), col(index.getCol())
  {
  }

  const inline std::size_t getRow() const
  {
    return row;
  }

  const inline std::size_t getCol() const
  {
    return col;
  }

  inline bool operator==(const TGElementIndex& i) const
  {
    return row == i.row && col == i.col;
  }

  inline bool operator<(const TGElementIndex& i) const
  {
    if(row != i.row)
    {
      return row < i.row;
    }
    else
    {
      return col < i.col;
    }
  }
};

std::size_t hash_value(const TGElementIndex<tg_matrix>& index)
{
  std::size_t seed = boost::hash<std::size_t>()(index.getRow());
  boost::hash_combine(seed, index.getCol());
  return seed;
}

template<typename tgExprType, typename T_element>
class TGOutputReference
{
private:
  TGExpressionNode<T_element>* node;
  std::size_t index;

public:
  TGOutputReference(TGExpressionNode<T_element>* const n, const std::size_t i) : node(n), index(i)
  {
  }

  TGOutputReference(const TGOutputReference& ref) : node(ref.node), index(ref.index)
  {
  }

  TGOutputReference& operator=(const TGOutputReference& ref)
  {
    node = ref.node;
    index = ref.index;
    return *this;
  }

  inline bool operator==(const TGOutputReference& ref) const
  {
    return node == ref.node && index == ref.index;
  }

  bool operator<(const TGOutputReference& ref) const
  {
    if (node < ref.node) return true;
    if (index < ref.index) return true;
    return false;
  }

  inline bool isParameter() const
  {
    return node->isParameter(index);
  }

  inline std::size_t getIndex() const
  {
    return index;
  }

  inline TGExpressionNode<T_element>* getExpressionNode() const
  {
    return node;
  }

  const typename TGInternalType<tgExprType, T_element>::type& getInternal() const
  {
    return *boost::get<typename TGInternalType<tgExprType, T_element>::type*>(node->getInternal(index));
  }

  typename TGInternalType<tgExprType, T_element>::type& getInternal()
  {
    return *boost::get<typename TGInternalType<tgExprType, T_element>::type*>(node->getInternal(index));
  }
};

template<typename T_candidate, typename T_replacement, typename T_element>
struct ReplaceOutputReference
{
  bool operator()(TGOutputReference<T_candidate, T_element>& ref,
    const TGOutputReference<T_replacement, T_element>& from, const TGOutputReference<T_replacement, T_element>& to)
  {
    return false;
  }
};

template<typename T_replacement, typename T_element>
struct ReplaceOutputReference<T_replacement, T_replacement, T_element>
{
  bool operator()(TGOutputReference<T_replacement, T_element>& ref,
    const TGOutputReference<T_replacement, T_element>& from, const TGOutputReference<T_replacement, T_element>& to)
  {
    const bool replace = (from == ref);
    if (replace) ref = to;
    return replace;
  }
};

template<typename T_element>
class TGExpressionNode
{
private:
  // Forbid copying and assignment
  TGExpressionNode(const TGExpressionNode&);
  TGExpressionNode& operator=(const TGExpressionNode&);

  typedef boost::mpl::vector<TGScalar<T_element>*, TGVector<T_element>*, TGMatrix<T_element>*> internal_types;
  typedef typename boost::mpl::transform< internal_types, boost::add_const<boost::mpl::_1> >::type internal_types_const;
  std::vector<TGExpressionNode<T_element>*> dependencies;
  std::vector<TGExpressionNode<T_element>*> reverseDependencies;

  struct InternalTypeComparator : public boost::static_visitor<bool>
  {
    template<typename T>
    inline bool operator()(const T* const  a, const T* const b) const
    {
      return a->matches(*b);
    }

    template<typename T1, typename T2>
    inline bool operator()(const T1* const  a, const T2* const b) const
    {
      return false;
    }
  };

protected:
  template<typename exprType>
  static inline bool isEqual(const TGOutputReference<exprType, T_element>& ref1, const TGOutputReference<exprType, T_element>& ref2,
    const std::map<const TGExpressionNode<T_element>*, const TGExpressionNode<T_element>*>& mappings)
  {
    if (ref1.getIndex() != ref2.getIndex())
      return false;

    typedef typename std::map<const TGExpressionNode<T_element>*, const TGExpressionNode<T_element>*>::const_iterator NodeMappingIter;
    const NodeMappingIter nodeMappingIter(mappings.find(ref1.getExpressionNode()));
    assert(nodeMappingIter != mappings.end());

    return nodeMappingIter->second == ref2.getExpressionNode();
  }

  void registerDependency(TGExpressionNode<T_element>* const dependency)
  {
    assert(dependency != NULL);
    dependencies.push_back(dependency);
    dependency->registerReverseDependency(this);
  }

  void registerReverseDependency(TGExpressionNode<T_element>* const revDependency)
  {
    assert(revDependency != NULL);
    reverseDependencies.push_back(revDependency);
  }

  void unregisterReverseDependency(TGExpressionNode<T_element>* const revDependency)
  {
    assert(revDependency != NULL);
    const typename std::vector<TGExpressionNode<T_element>*>::iterator location =
      std::find(reverseDependencies.begin(), reverseDependencies.end(), revDependency);
    assert(location != reverseDependencies.end());
    reverseDependencies.erase(location);
  }

  template<typename exprType>
  void alterDependencyGeneral(const TGOutputReference<exprType, T_element>& previous, TGOutputReference<exprType, T_element>& next)
  {
    // Unlike in the general expression node class, this needs to replace all dependencies on a given node,
    // not just the first one. This is because the node replacement is not being handled by the node being
    // replaced, and this method won't be called multiple times if we have more than one dependency on the
    // node being replaced.

    for(typename std::vector<TGExpressionNode<T_element>*>::iterator depIter = dependencies.begin(); depIter != dependencies.end(); ++depIter)
    {
      if (previous.getExpressionNode() == *depIter)
      {
        *depIter = next.getExpressionNode();
        next.getExpressionNode()->registerReverseDependency(this);
        previous.getExpressionNode()->unregisterReverseDependency(this);
      }
    }

    alterDependencyImpl(previous, next);
  }

  virtual void alterDependencyImpl(const TGOutputReference<tg_scalar, T_element>& previous, TGOutputReference<tg_scalar, T_element>& next) = 0;
  virtual void alterDependencyImpl(const TGOutputReference<tg_vector, T_element>& previous, TGOutputReference<tg_vector, T_element>& next) = 0;
  virtual void alterDependencyImpl(const TGOutputReference<tg_matrix, T_element>& previous, TGOutputReference<tg_matrix, T_element>& next) = 0;

public:
  typedef typename boost::make_variant_over<internal_types>::type internal_variant_type;
  typedef typename boost::make_variant_over<internal_types_const>::type const_internal_variant_type;

  TGExpressionNode()
  {
  }

  bool isEqual(const TGExpressionNode& node, const std::map<const TGExpressionNode<T_element>*, const TGExpressionNode<T_element>*>& mappings) const
  {
    const std::size_t numOutputs = getNumOutputs();

    if (numOutputs != node.getNumOutputs())
      return false;

    for(std::size_t index=0; index < numOutputs; ++index)
    {
      const bool equal = boost::apply_visitor(InternalTypeComparator(), getInternal(index), node.getInternal(index));
      if (!equal)
        return false;
    }

    return true;
  }

  virtual void accept(TGExpressionNodeVisitor<T_element>& visitor) = 0;
  virtual void createTaskGraphVariable() = 0;

  std::vector<TGExpressionNode<T_element>*> getDependencies() const
  {
    return dependencies;
  }

  std::vector<TGExpressionNode<T_element>*> getReverseDependencies() const
  {
    return reverseDependencies;
  }

  std::size_t numDependencies() const
  {
    return dependencies.size();
  }

  std::size_t numReverseDependencies() const
  {
    return reverseDependencies.size();
  }

  virtual std::size_t getNumOutputs() const = 0;
  virtual bool isParameter(const std::size_t index) const = 0;
  virtual internal_variant_type getInternal(const std::size_t index) = 0;
  virtual const internal_variant_type getInternal(const std::size_t index) const = 0;

  void alterDependency(const TGOutputReference<tg_scalar, T_element>& previous, TGOutputReference<tg_scalar, T_element>& next)
  {
    alterDependencyGeneral(previous, next);
  }

  void alterDependency(const TGOutputReference<tg_vector, T_element>& previous, TGOutputReference<tg_vector, T_element>& next)
  {
    alterDependencyGeneral(previous, next);
  }

  void alterDependency(const TGOutputReference<tg_matrix, T_element>& previous, TGOutputReference<tg_matrix, T_element>& next)
  {
    alterDependencyGeneral(previous, next);
  }

  virtual ~TGExpressionNode()
  {
    // We shouldn't have anything depending on this node
    assert(reverseDependencies.empty());

    BOOST_FOREACH(TGExpressionNode<T_element>* dep, dependencies)
    {
      dep->unregisterReverseDependency(this);
    }
  }
};

template<typename exprType, typename T_element>
class TGExprNode : public TGExpressionNode<T_element>
{
private:
  typedef typename TGInternalType<exprType, T_element>::type T_internal;
  std::auto_ptr<T_internal> internal;

public:
  typedef typename TGExpressionNode<T_element>::internal_variant_type internal_variant_type;
  typedef typename TGExpressionNode<T_element>::const_internal_variant_type const_internal_variant_type;

  inline bool isEqual(const TGExprNode& node, const std::map<const TGExpressionNode<T_element>*, const TGExpressionNode<T_element>*>& mappings) const
  {
    return TGExpressionNode<T_element>::isEqual(node, mappings);
  }

  TGExprNode(T_internal* const i) : internal(i)
  {
  }

  void createTaskGraphVariable()
  {
    internal->createTaskGraphVariable();
  }

  inline T_internal& getInternal()
  {
    return *internal;
  }

  T_internal* releaseInternal()
  {
    return internal.release();
  }

  inline const T_internal& getInternal() const
  {
    return *internal;
  }

  virtual std::size_t getNumOutputs() const
  {
    return 1;
  }

  bool isParameter(const std::size_t index) const
  {
    if (index == 0)
    {
      return internal->isParameter();
    }
    else
    {
      assert(false && "isParameter call for internal representation with index>0 for node with only one output.");
    }
  }

  virtual internal_variant_type getInternal(const std::size_t index)
  {
    if (index == 0)
    {
      return internal_variant_type(internal.get());
    }
    else
    {
      assert(false && "getInternal call for internal representation with index>0 for node with only one output.");
    }
  }

  virtual const internal_variant_type getInternal(const std::size_t index) const
  {
    if (index == 0)
    {
      return internal_variant_type(internal.get());
    }
    else
    {
      assert(false && "getInternal call for internal representation with index>0 for node with only one output.");
    }
  }

};

}

}
#endif
<commit_msg>Make TGOutputReference replacement function object operator() inline and const.<commit_after>/****************************************************************************/
/* Copyright 2005-2006, Francis Russell                                     */
/*                                                                          */
/* Licensed under the Apache License, Version 2.0 (the License);            */
/* you may not use this file except in compliance with the License.         */
/* You may obtain a copy of the License at                                  */
/*                                                                          */
/*     http://www.apache.org/licenses/LICENSE-2.0                           */
/*                                                                          */
/* Unless required by applicable law or agreed to in writing, software      */
/* distributed under the License is distributed on an AS IS BASIS,          */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and      */
/* limitations under the License.                                           */
/*                                                                          */
/****************************************************************************/

#ifndef DESOLIN_TG_EXPRESSION_NODE_HPP
#define DESOLIN_TG_EXPRESSION_NODE_HPP

#include <set>
#include <map>
#include <string>
#include <cassert>
#include <cstddef>
#include <memory>
#include <boost/functional/hash.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/variant.hpp>
#include <boost/foreach.hpp>
#include <desolin/tg/Desolin_tg_fwd.hpp>

namespace desolin
{

namespace detail
{

template<typename exprType>
class TGElementIndex
{
};

template<>
class TGElementIndex<tg_vector>
{
private:
  const std::size_t row;

public:
  TGElementIndex(const std::size_t r) : row(r)
  {
  }

  TGElementIndex(const ElementIndex<vector>& index) : row(index.getRow())
  {
  }

  const inline std::size_t getRow() const
  {
    return row;
  }

  inline bool operator==(const TGElementIndex& i) const
  {
    return row == i.row;
  }

  inline bool operator<(const TGElementIndex& i) const
  {
    return row < i.row;
  }
};

std::size_t hash_value(const TGElementIndex<tg_vector>& index)
{
  return boost::hash<int>()(index.getRow());
}

template<>
class TGElementIndex<tg_matrix>
{
private:
  const std::size_t row;
  const std::size_t col;

public:
  TGElementIndex(const std::size_t r, const std::size_t c) : row(r), col(c)
  {
  }

  TGElementIndex(const ElementIndex<matrix>& index) : row(index.getRow()), col(index.getCol())
  {
  }

  const inline std::size_t getRow() const
  {
    return row;
  }

  const inline std::size_t getCol() const
  {
    return col;
  }

  inline bool operator==(const TGElementIndex& i) const
  {
    return row == i.row && col == i.col;
  }

  inline bool operator<(const TGElementIndex& i) const
  {
    if(row != i.row)
    {
      return row < i.row;
    }
    else
    {
      return col < i.col;
    }
  }
};

std::size_t hash_value(const TGElementIndex<tg_matrix>& index)
{
  std::size_t seed = boost::hash<std::size_t>()(index.getRow());
  boost::hash_combine(seed, index.getCol());
  return seed;
}

template<typename tgExprType, typename T_element>
class TGOutputReference
{
private:
  TGExpressionNode<T_element>* node;
  std::size_t index;

public:
  TGOutputReference(TGExpressionNode<T_element>* const n, const std::size_t i) : node(n), index(i)
  {
  }

  TGOutputReference(const TGOutputReference& ref) : node(ref.node), index(ref.index)
  {
  }

  TGOutputReference& operator=(const TGOutputReference& ref)
  {
    node = ref.node;
    index = ref.index;
    return *this;
  }

  inline bool operator==(const TGOutputReference& ref) const
  {
    return node == ref.node && index == ref.index;
  }

  bool operator<(const TGOutputReference& ref) const
  {
    if (node < ref.node) return true;
    if (index < ref.index) return true;
    return false;
  }

  inline bool isParameter() const
  {
    return node->isParameter(index);
  }

  inline std::size_t getIndex() const
  {
    return index;
  }

  inline TGExpressionNode<T_element>* getExpressionNode() const
  {
    return node;
  }

  const typename TGInternalType<tgExprType, T_element>::type& getInternal() const
  {
    return *boost::get<typename TGInternalType<tgExprType, T_element>::type*>(node->getInternal(index));
  }

  typename TGInternalType<tgExprType, T_element>::type& getInternal()
  {
    return *boost::get<typename TGInternalType<tgExprType, T_element>::type*>(node->getInternal(index));
  }
};

template<typename T_candidate, typename T_replacement, typename T_element>
struct ReplaceOutputReference
{
  inline bool operator()(TGOutputReference<T_candidate, T_element>& ref,
    const TGOutputReference<T_replacement, T_element>& from, const TGOutputReference<T_replacement, T_element>& to) const
  {
    return false;
  }
};

template<typename T_replacement, typename T_element>
struct ReplaceOutputReference<T_replacement, T_replacement, T_element>
{
  inline bool operator()(TGOutputReference<T_replacement, T_element>& ref,
    const TGOutputReference<T_replacement, T_element>& from, const TGOutputReference<T_replacement, T_element>& to) const
  {
    const bool replace = (from == ref);
    if (replace) ref = to;
    return replace;
  }
};

template<typename T_element>
class TGExpressionNode
{
private:
  // Forbid copying and assignment
  TGExpressionNode(const TGExpressionNode&);
  TGExpressionNode& operator=(const TGExpressionNode&);

  typedef boost::mpl::vector<TGScalar<T_element>*, TGVector<T_element>*, TGMatrix<T_element>*> internal_types;
  typedef typename boost::mpl::transform< internal_types, boost::add_const<boost::mpl::_1> >::type internal_types_const;
  std::vector<TGExpressionNode<T_element>*> dependencies;
  std::vector<TGExpressionNode<T_element>*> reverseDependencies;

  struct InternalTypeComparator : public boost::static_visitor<bool>
  {
    template<typename T>
    inline bool operator()(const T* const  a, const T* const b) const
    {
      return a->matches(*b);
    }

    template<typename T1, typename T2>
    inline bool operator()(const T1* const  a, const T2* const b) const
    {
      return false;
    }
  };

protected:
  template<typename exprType>
  static inline bool isEqual(const TGOutputReference<exprType, T_element>& ref1, const TGOutputReference<exprType, T_element>& ref2,
    const std::map<const TGExpressionNode<T_element>*, const TGExpressionNode<T_element>*>& mappings)
  {
    if (ref1.getIndex() != ref2.getIndex())
      return false;

    typedef typename std::map<const TGExpressionNode<T_element>*, const TGExpressionNode<T_element>*>::const_iterator NodeMappingIter;
    const NodeMappingIter nodeMappingIter(mappings.find(ref1.getExpressionNode()));
    assert(nodeMappingIter != mappings.end());

    return nodeMappingIter->second == ref2.getExpressionNode();
  }

  void registerDependency(TGExpressionNode<T_element>* const dependency)
  {
    assert(dependency != NULL);
    dependencies.push_back(dependency);
    dependency->registerReverseDependency(this);
  }

  void registerReverseDependency(TGExpressionNode<T_element>* const revDependency)
  {
    assert(revDependency != NULL);
    reverseDependencies.push_back(revDependency);
  }

  void unregisterReverseDependency(TGExpressionNode<T_element>* const revDependency)
  {
    assert(revDependency != NULL);
    const typename std::vector<TGExpressionNode<T_element>*>::iterator location =
      std::find(reverseDependencies.begin(), reverseDependencies.end(), revDependency);
    assert(location != reverseDependencies.end());
    reverseDependencies.erase(location);
  }

  template<typename exprType>
  void alterDependencyGeneral(const TGOutputReference<exprType, T_element>& previous, TGOutputReference<exprType, T_element>& next)
  {
    // Unlike in the general expression node class, this needs to replace all dependencies on a given node,
    // not just the first one. This is because the node replacement is not being handled by the node being
    // replaced, and this method won't be called multiple times if we have more than one dependency on the
    // node being replaced.

    for(typename std::vector<TGExpressionNode<T_element>*>::iterator depIter = dependencies.begin(); depIter != dependencies.end(); ++depIter)
    {
      if (previous.getExpressionNode() == *depIter)
      {
        *depIter = next.getExpressionNode();
        next.getExpressionNode()->registerReverseDependency(this);
        previous.getExpressionNode()->unregisterReverseDependency(this);
      }
    }

    alterDependencyImpl(previous, next);
  }

  virtual void alterDependencyImpl(const TGOutputReference<tg_scalar, T_element>& previous, TGOutputReference<tg_scalar, T_element>& next) = 0;
  virtual void alterDependencyImpl(const TGOutputReference<tg_vector, T_element>& previous, TGOutputReference<tg_vector, T_element>& next) = 0;
  virtual void alterDependencyImpl(const TGOutputReference<tg_matrix, T_element>& previous, TGOutputReference<tg_matrix, T_element>& next) = 0;

public:
  typedef typename boost::make_variant_over<internal_types>::type internal_variant_type;
  typedef typename boost::make_variant_over<internal_types_const>::type const_internal_variant_type;

  TGExpressionNode()
  {
  }

  bool isEqual(const TGExpressionNode& node, const std::map<const TGExpressionNode<T_element>*, const TGExpressionNode<T_element>*>& mappings) const
  {
    const std::size_t numOutputs = getNumOutputs();

    if (numOutputs != node.getNumOutputs())
      return false;

    for(std::size_t index=0; index < numOutputs; ++index)
    {
      const bool equal = boost::apply_visitor(InternalTypeComparator(), getInternal(index), node.getInternal(index));
      if (!equal)
        return false;
    }

    return true;
  }

  virtual void accept(TGExpressionNodeVisitor<T_element>& visitor) = 0;
  virtual void createTaskGraphVariable() = 0;

  std::vector<TGExpressionNode<T_element>*> getDependencies() const
  {
    return dependencies;
  }

  std::vector<TGExpressionNode<T_element>*> getReverseDependencies() const
  {
    return reverseDependencies;
  }

  std::size_t numDependencies() const
  {
    return dependencies.size();
  }

  std::size_t numReverseDependencies() const
  {
    return reverseDependencies.size();
  }

  virtual std::size_t getNumOutputs() const = 0;
  virtual bool isParameter(const std::size_t index) const = 0;
  virtual internal_variant_type getInternal(const std::size_t index) = 0;
  virtual const internal_variant_type getInternal(const std::size_t index) const = 0;

  void alterDependency(const TGOutputReference<tg_scalar, T_element>& previous, TGOutputReference<tg_scalar, T_element>& next)
  {
    alterDependencyGeneral(previous, next);
  }

  void alterDependency(const TGOutputReference<tg_vector, T_element>& previous, TGOutputReference<tg_vector, T_element>& next)
  {
    alterDependencyGeneral(previous, next);
  }

  void alterDependency(const TGOutputReference<tg_matrix, T_element>& previous, TGOutputReference<tg_matrix, T_element>& next)
  {
    alterDependencyGeneral(previous, next);
  }

  virtual ~TGExpressionNode()
  {
    // We shouldn't have anything depending on this node
    assert(reverseDependencies.empty());

    BOOST_FOREACH(TGExpressionNode<T_element>* dep, dependencies)
    {
      dep->unregisterReverseDependency(this);
    }
  }
};

template<typename exprType, typename T_element>
class TGExprNode : public TGExpressionNode<T_element>
{
private:
  typedef typename TGInternalType<exprType, T_element>::type T_internal;
  std::auto_ptr<T_internal> internal;

public:
  typedef typename TGExpressionNode<T_element>::internal_variant_type internal_variant_type;
  typedef typename TGExpressionNode<T_element>::const_internal_variant_type const_internal_variant_type;

  inline bool isEqual(const TGExprNode& node, const std::map<const TGExpressionNode<T_element>*, const TGExpressionNode<T_element>*>& mappings) const
  {
    return TGExpressionNode<T_element>::isEqual(node, mappings);
  }

  TGExprNode(T_internal* const i) : internal(i)
  {
  }

  void createTaskGraphVariable()
  {
    internal->createTaskGraphVariable();
  }

  inline T_internal& getInternal()
  {
    return *internal;
  }

  T_internal* releaseInternal()
  {
    return internal.release();
  }

  inline const T_internal& getInternal() const
  {
    return *internal;
  }

  virtual std::size_t getNumOutputs() const
  {
    return 1;
  }

  bool isParameter(const std::size_t index) const
  {
    if (index == 0)
    {
      return internal->isParameter();
    }
    else
    {
      assert(false && "isParameter call for internal representation with index>0 for node with only one output.");
    }
  }

  virtual internal_variant_type getInternal(const std::size_t index)
  {
    if (index == 0)
    {
      return internal_variant_type(internal.get());
    }
    else
    {
      assert(false && "getInternal call for internal representation with index>0 for node with only one output.");
    }
  }

  virtual const internal_variant_type getInternal(const std::size_t index) const
  {
    if (index == 0)
    {
      return internal_variant_type(internal.get());
    }
    else
    {
      assert(false && "getInternal call for internal representation with index>0 for node with only one output.");
    }
  }

};

}

}
#endif
<|endoftext|>


<commit_before>/**
 * \file
 * \brief StaticFifoQueue class header
 *
 * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2014-12-06
 */

#ifndef INCLUDE_DISTORTOS_STATICFIFOQUEUE_HPP_
#define INCLUDE_DISTORTOS_STATICFIFOQUEUE_HPP_

#include "FifoQueue.hpp"

namespace distortos
{

/**
 * \brief StaticFifoQueue class is a variant of FifoQueue that has automatic storage for queue's contents.
 *
 * \param T is the type of data in queue
 * \param QueueSize is the maximum number of elements in queue
 */

template<typename T, size_t QueueSize>
class StaticFifoQueue : public FifoQueue<T>
{
public:

	/**
	 * \brief StaticFifoQueue's constructor
	 */

	explicit StaticFifoQueue() :
			FifoQueue<T>{storage_, sizeof(storage_) / sizeof(*storage_)}
	{

	}

private:

	/// storage for queue's contents
	typename FifoQueue<T>::Storage storage_[QueueSize];
};

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_STATICFIFOQUEUE_HPP_
<commit_msg>StaticFifoQueue: use std::array for storage and new FifoQueue helper constructor<commit_after>/**
 * \file
 * \brief StaticFifoQueue class header
 *
 * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-01-02
 */

#ifndef INCLUDE_DISTORTOS_STATICFIFOQUEUE_HPP_
#define INCLUDE_DISTORTOS_STATICFIFOQUEUE_HPP_

#include "FifoQueue.hpp"

namespace distortos
{

/**
 * \brief StaticFifoQueue class is a variant of FifoQueue that has automatic storage for queue's contents.
 *
 * \param T is the type of data in queue
 * \param QueueSize is the maximum number of elements in queue
 */

template<typename T, size_t QueueSize>
class StaticFifoQueue : public FifoQueue<T>
{
public:

	/**
	 * \brief StaticFifoQueue's constructor
	 */

	explicit StaticFifoQueue() :
			FifoQueue<T>{storage_}
	{

	}

private:

	/// storage for queue's contents
	std::array<typename FifoQueue<T>::Storage, QueueSize> storage_;
};

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_STATICFIFOQUEUE_HPP_
<|endoftext|>


<commit_before>#pragma once

#include <tudocomp/Coder.hpp>

namespace tdc {

template<
    typename int_coder_t,
    typename lit_coder_t
>
class VariantCoder : public Algorithm {
public:
    inline static Meta meta() {
        Meta m("coder", "variant", "Different encoding for integers and literals");
        m.option("int_coder").templated<int_coder_t>();
        m.option("lit_coder").templated<lit_coder_t>();
        return m;
    }

    VariantCoder() = delete;

    class Encoder : public tdc::Encoder {
    private:
        std::unique_ptr<typename int_coder_t::Encoder> m_int_encoder;
        std::unique_ptr<typename lit_coder_t::Encoder> m_lit_encoder;

    public:
        ENCODER_CTOR(env, out, literals),
            m_int_encoder(std::make_unique<typename int_coder_t::Encoder>(
                this->env().env_for_option("int_coder"), out, NoLiterals())),
            m_lit_encoder(std::make_unique<typename lit_coder_t::Encoder>(
                this->env().env_for_option("lit_coder"), out, literals))
        {
        }

        template<typename value_t, typename range_t>
        inline void encode(value_t v, const range_t& r) {
            m_int_encoder->encode(v, r);
        }

        template<typename value_t>
        inline void encode(value_t v, const LiteralRange& r) {
            m_lit_encoder->encode(v, r);
        }
    };

    class Decoder : public tdc::Decoder {
    private:
        std::unique_ptr<typename int_coder_t::Decoder> m_int_decoder;
        std::unique_ptr<typename lit_coder_t::Decoder> m_lit_decoder;

    public:
        DECODER_CTOR(env, in),
            m_int_decoder(std::make_unique<typename int_coder_t::Decoder>(
                this->env().env_for_option("int_coder"), in)),
            m_lit_decoder(std::make_unique<typename lit_coder_t::Decoder>(
                this->env().env_for_option("lit_coder"), in))
        {
        }

        template<typename value_t, typename range_t>
        inline value_t decode(const range_t& r) {
            return m_int_decoder->template decode<value_t>(r);
        }

        template<typename value_t>
        inline value_t decode(const LiteralRange& r) {
            return m_lit_decoder->template decode<value_t>(r);
        }
    };
};

}

<commit_msg>Remove obsolete VariantCoder<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (c) 2017-2021, The Bifrost Authors. All rights reserved.
 * Copyright (c) 2017-2021, The University of New Mexico. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * * Neither the name of The Bifrost Authors nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "assert.hpp"
#include <bifrost/config.h>
#include <bifrost/udp_transmit.h>
#include <bifrost/affinity.h>
#include "proclog.hpp"
#include "Socket.hpp"

#include <arpa/inet.h>  // For ntohs
#include <sys/socket.h> // For recvfrom

#include <queue>
#include <memory>
#include <stdexcept>
#include <cstdlib>      // For posix_memalign
#include <cstring>      // For memcpy, memset
#include <cstdint>

#include <sys/types.h>
#include <unistd.h>
#include <fstream>

#if BF_HWLOC_ENABLED
#include <hwloc.h>
class HardwareLocality {
	hwloc_topology_t _topo;
	HardwareLocality(HardwareLocality const&);
	HardwareLocality& operator=(HardwareLocality const&);
public:
	HardwareLocality() {
		hwloc_topology_init(&_topo);
		hwloc_topology_load(_topo);
	}
	~HardwareLocality() {
		hwloc_topology_destroy(_topo);
	}
	int bind_memory_to_core(int core) {
		int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE);
		int ncore      = hwloc_get_nbobjs_by_depth(_topo, core_depth);
		int ret = 0;
		if( 0 <= core && core < ncore ) {
			hwloc_obj_t    obj    = hwloc_get_obj_by_depth(_topo, core_depth, core);
			hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset);
			hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads
			hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND;
			hwloc_membind_flags_t  flags  = HWLOC_MEMBIND_THREAD;
			ret = hwloc_set_membind(_topo, cpuset, policy, flags);
			hwloc_bitmap_free(cpuset);
		}
		return ret;
	}
};
#endif // BF_HWLOC_ENABLED

class BoundThread {
#if BF_HWLOC_ENABLED
	HardwareLocality _hwloc;
#endif
public:
	BoundThread(int core) {
		bfAffinitySetCore(core);
#if BF_HWLOC_ENABLED
		assert(_hwloc.bind_memory_to_core(core) == 0);
#endif
	}
};

struct PacketStats {
	size_t ninvalid;
	size_t ninvalid_bytes;
	size_t nlate;
	size_t nlate_bytes;
	size_t nvalid;
	size_t nvalid_bytes;
};

class UDPTransmitThread : public BoundThread {
	PacketStats       _stats;

	int               _fd;

public:
	UDPTransmitThread(int fd, int core=0)
		: BoundThread(core), _fd(fd) {
		this->reset_stats();
	}
	inline ssize_t send(msghdr* packet) {
		ssize_t nsent = sendmsg(_fd, packet, 0);
		if( nsent == -1 ) {
			++_stats.ninvalid;
			_stats.ninvalid_bytes += packet->msg_iovlen;
		} else {
			++_stats.nvalid;
			_stats.nvalid_bytes += nsent;
		}
		return nsent;
	}
	inline ssize_t sendmany(mmsghdr *packets, unsigned int npackets) {
		ssize_t nsent = sendmmsg(_fd, packets, npackets, 0);
		if( nsent == -1 ) {
			_stats.ninvalid += npackets;
			_stats.ninvalid_bytes += (size_t) npackets * packets->msg_len;
		} else {
			_stats.nvalid += npackets;
			_stats.nvalid_bytes += (size_t) npackets * packets->msg_len;
		}
		return nsent;
	}
	inline const PacketStats* get_stats() const { return &_stats; }
	inline void reset_stats() {
		::memset(&_stats, 0, sizeof(_stats));
	}
};

class BFudptransmit_impl {
	UDPTransmitThread  _transmit;
	ProcLog            _type_log;
	ProcLog            _bind_log;
	ProcLog            _stat_log;
	pid_t              _pid;

	void update_stats_log() {
		const PacketStats* stats = _transmit.get_stats();
		_stat_log.update() << "ngood_bytes    : " << stats->nvalid_bytes << "\n"
		                   << "nmissing_bytes : " << stats->ninvalid_bytes << "\n"
		                   << "ninvalid       : " << stats->ninvalid << "\n"
		                   << "ninvalid_bytes : " << stats->ninvalid_bytes << "\n"
		                   << "nlate          : " << stats->nlate << "\n"
		                   << "nlate_bytes    : " << stats->nlate_bytes << "\n"
		                   << "nvalid         : " << stats->nvalid << "\n"
		                   << "nvalid_bytes   : " << stats->nvalid_bytes << "\n";
	}
public:
	inline BFudptransmit_impl(int fd,
	                          int core)
		: _transmit(fd, core),
		  _type_log("udp_transmit/type"),
		  _bind_log("udp_transmit/bind"),
		  _stat_log("udp_transmit/stats") {
		_type_log.update() << "type : " << "generic";
		_bind_log.update() << "ncore : " << 1 << "\n"
		                   << "core0 : " << core << "\n";
	}
	BFudptransmit_status send(char *packet, unsigned int len) {
		ssize_t state;
		struct msghdr msg;
		struct iovec iov[1];

		memset(&msg, 0, sizeof(msg));
		msg.msg_iov = iov;
		msg.msg_iovlen = 1;
		iov[0].iov_base = packet;
		iov[0].iov_len = len;

		state = _transmit.send( &msg );
		if( state == -1 ) {
			return BF_TRANSMIT_ERROR;
		}
		this->update_stats_log();
		return BF_TRANSMIT_CONTINUED;
	}
	BFudptransmit_status sendmany(char *packets, unsigned int len, unsigned int npackets) {
		ssize_t state;
		unsigned int i;
		struct mmsghdr *mmsg = NULL;
		struct iovec *iovs = NULL;

		mmsg = (struct mmsghdr *) malloc(sizeof(struct mmsghdr)*npackets);
		iovs = (struct iovec *) malloc(sizeof(struct iovec)*npackets);
		memset(mmsg, 0, sizeof(struct mmsghdr)*npackets);
		for(i=0; i<npackets; i++) {
			mmsg[i].msg_hdr.msg_iov = &iovs[i];
			mmsg[i].msg_hdr.msg_iovlen = 1;
			iovs[i].iov_base = (packets + i*len);
			iovs[i].iov_len = len;
		}

		state = _transmit.sendmany(mmsg, npackets);
		free(mmsg);
		free(iovs);
		if( state == -1 ) {
			return BF_TRANSMIT_ERROR;
		}
		this->update_stats_log();
		return BF_TRANSMIT_CONTINUED;
	}
};

BFstatus bfUdpTransmitCreate(BFudptransmit* obj,
                            int           fd,
                            int           core) {
	BF_ASSERT(obj, BF_STATUS_INVALID_POINTER);
	BF_TRY_RETURN_ELSE(*obj = new BFudptransmit_impl(fd, core),
		              *obj = 0);

}
BFstatus bfUdpTransmitDestroy(BFudptransmit obj) {
	BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE);
	delete obj;
	return BF_STATUS_SUCCESS;
}
BFstatus bfUdpTransmitSend(BFudptransmit obj, char* packet, unsigned int len) {
	BF_TRY_RETURN(obj->send(packet, len));
}
BFstatus bfUdpTransmitSendMany(BFudptransmit obj, char* packets, unsigned int len, unsigned int npackets) {
	BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE);
	BF_TRY_RETURN(obj->sendmany(packets, len, npackets));
}
<commit_msg>Remove unused _pid.<commit_after>/*
 * Copyright (c) 2017-2021, The Bifrost Authors. All rights reserved.
 * Copyright (c) 2017-2021, The University of New Mexico. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * * Neither the name of The Bifrost Authors nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "assert.hpp"
#include <bifrost/config.h>
#include <bifrost/udp_transmit.h>
#include <bifrost/affinity.h>
#include "proclog.hpp"
#include "Socket.hpp"

#include <arpa/inet.h>  // For ntohs
#include <sys/socket.h> // For recvfrom

#include <queue>
#include <memory>
#include <stdexcept>
#include <cstdlib>      // For posix_memalign
#include <cstring>      // For memcpy, memset
#include <cstdint>

#include <sys/types.h>
#include <unistd.h>
#include <fstream>

#if BF_HWLOC_ENABLED
#include <hwloc.h>
class HardwareLocality {
	hwloc_topology_t _topo;
	HardwareLocality(HardwareLocality const&);
	HardwareLocality& operator=(HardwareLocality const&);
public:
	HardwareLocality() {
		hwloc_topology_init(&_topo);
		hwloc_topology_load(_topo);
	}
	~HardwareLocality() {
		hwloc_topology_destroy(_topo);
	}
	int bind_memory_to_core(int core) {
		int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE);
		int ncore      = hwloc_get_nbobjs_by_depth(_topo, core_depth);
		int ret = 0;
		if( 0 <= core && core < ncore ) {
			hwloc_obj_t    obj    = hwloc_get_obj_by_depth(_topo, core_depth, core);
			hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset);
			hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads
			hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND;
			hwloc_membind_flags_t  flags  = HWLOC_MEMBIND_THREAD;
			ret = hwloc_set_membind(_topo, cpuset, policy, flags);
			hwloc_bitmap_free(cpuset);
		}
		return ret;
	}
};
#endif // BF_HWLOC_ENABLED

class BoundThread {
#if BF_HWLOC_ENABLED
	HardwareLocality _hwloc;
#endif
public:
	BoundThread(int core) {
		bfAffinitySetCore(core);
#if BF_HWLOC_ENABLED
		assert(_hwloc.bind_memory_to_core(core) == 0);
#endif
	}
};

struct PacketStats {
	size_t ninvalid;
	size_t ninvalid_bytes;
	size_t nlate;
	size_t nlate_bytes;
	size_t nvalid;
	size_t nvalid_bytes;
};

class UDPTransmitThread : public BoundThread {
	PacketStats       _stats;

	int               _fd;

public:
	UDPTransmitThread(int fd, int core=0)
		: BoundThread(core), _fd(fd) {
		this->reset_stats();
	}
	inline ssize_t send(msghdr* packet) {
		ssize_t nsent = sendmsg(_fd, packet, 0);
		if( nsent == -1 ) {
			++_stats.ninvalid;
			_stats.ninvalid_bytes += packet->msg_iovlen;
		} else {
			++_stats.nvalid;
			_stats.nvalid_bytes += nsent;
		}
		return nsent;
	}
	inline ssize_t sendmany(mmsghdr *packets, unsigned int npackets) {
		ssize_t nsent = sendmmsg(_fd, packets, npackets, 0);
		if( nsent == -1 ) {
			_stats.ninvalid += npackets;
			_stats.ninvalid_bytes += (size_t) npackets * packets->msg_len;
		} else {
			_stats.nvalid += npackets;
			_stats.nvalid_bytes += (size_t) npackets * packets->msg_len;
		}
		return nsent;
	}
	inline const PacketStats* get_stats() const { return &_stats; }
	inline void reset_stats() {
		::memset(&_stats, 0, sizeof(_stats));
	}
};

class BFudptransmit_impl {
	UDPTransmitThread  _transmit;
	ProcLog            _type_log;
	ProcLog            _bind_log;
	ProcLog            _stat_log;

	void update_stats_log() {
		const PacketStats* stats = _transmit.get_stats();
		_stat_log.update() << "ngood_bytes    : " << stats->nvalid_bytes << "\n"
		                   << "nmissing_bytes : " << stats->ninvalid_bytes << "\n"
		                   << "ninvalid       : " << stats->ninvalid << "\n"
		                   << "ninvalid_bytes : " << stats->ninvalid_bytes << "\n"
		                   << "nlate          : " << stats->nlate << "\n"
		                   << "nlate_bytes    : " << stats->nlate_bytes << "\n"
		                   << "nvalid         : " << stats->nvalid << "\n"
		                   << "nvalid_bytes   : " << stats->nvalid_bytes << "\n";
	}
public:
	inline BFudptransmit_impl(int fd,
	                          int core)
		: _transmit(fd, core),
		  _type_log("udp_transmit/type"),
		  _bind_log("udp_transmit/bind"),
		  _stat_log("udp_transmit/stats") {
		_type_log.update() << "type : " << "generic";
		_bind_log.update() << "ncore : " << 1 << "\n"
		                   << "core0 : " << core << "\n";
	}
	BFudptransmit_status send(char *packet, unsigned int len) {
		ssize_t state;
		struct msghdr msg;
		struct iovec iov[1];

		memset(&msg, 0, sizeof(msg));
		msg.msg_iov = iov;
		msg.msg_iovlen = 1;
		iov[0].iov_base = packet;
		iov[0].iov_len = len;

		state = _transmit.send( &msg );
		if( state == -1 ) {
			return BF_TRANSMIT_ERROR;
		}
		this->update_stats_log();
		return BF_TRANSMIT_CONTINUED;
	}
	BFudptransmit_status sendmany(char *packets, unsigned int len, unsigned int npackets) {
		ssize_t state;
		unsigned int i;
		struct mmsghdr *mmsg = NULL;
		struct iovec *iovs = NULL;

		mmsg = (struct mmsghdr *) malloc(sizeof(struct mmsghdr)*npackets);
		iovs = (struct iovec *) malloc(sizeof(struct iovec)*npackets);
		memset(mmsg, 0, sizeof(struct mmsghdr)*npackets);
		for(i=0; i<npackets; i++) {
			mmsg[i].msg_hdr.msg_iov = &iovs[i];
			mmsg[i].msg_hdr.msg_iovlen = 1;
			iovs[i].iov_base = (packets + i*len);
			iovs[i].iov_len = len;
		}

		state = _transmit.sendmany(mmsg, npackets);
		free(mmsg);
		free(iovs);
		if( state == -1 ) {
			return BF_TRANSMIT_ERROR;
		}
		this->update_stats_log();
		return BF_TRANSMIT_CONTINUED;
	}
};

BFstatus bfUdpTransmitCreate(BFudptransmit* obj,
                            int           fd,
                            int           core) {
	BF_ASSERT(obj, BF_STATUS_INVALID_POINTER);
	BF_TRY_RETURN_ELSE(*obj = new BFudptransmit_impl(fd, core),
		              *obj = 0);

}
BFstatus bfUdpTransmitDestroy(BFudptransmit obj) {
	BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE);
	delete obj;
	return BF_STATUS_SUCCESS;
}
BFstatus bfUdpTransmitSend(BFudptransmit obj, char* packet, unsigned int len) {
	BF_TRY_RETURN(obj->send(packet, len));
}
BFstatus bfUdpTransmitSendMany(BFudptransmit obj, char* packets, unsigned int len, unsigned int npackets) {
	BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE);
	BF_TRY_RETURN(obj->sendmany(packets, len, npackets));
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef DLL_WATCHER_HPP
#define DLL_WATCHER_HPP

#include <fstream>

#include <sys/stat.h>

#include "cpp_utils/stop_watch.hpp"

#include "rbm_training_context.hpp"
#include "layer_traits.hpp"
#include "dbn_traits.hpp"

namespace dll {

template<typename R>
struct default_rbm_watcher {
    cpp::stop_watch<std::chrono::seconds> watch;

    template<typename RBM = R>
    void training_begin(const RBM& rbm){
        std::cout << "Train RBM with \"" << RBM::desc::template trainer_t<RBM,false>::name() << "\"" << std::endl;

        rbm.display();

        std::cout << "With parameters:" << std::endl;
        std::cout << "   learning_rate=" << rbm.learning_rate << std::endl;

        if(layer_traits<RBM>::has_momentum()){
            std::cout << "   momentum=" << rbm.momentum << std::endl;
        }

        if(w_decay(layer_traits<RBM>::decay()) == decay_type::L1 || w_decay(layer_traits<RBM>::decay()) == decay_type::L1L2){
            std::cout << "   weight_cost(L1)=" << rbm.l1_weight_cost << std::endl;
        }

        if(w_decay(layer_traits<RBM>::decay()) == decay_type::L2 || w_decay(layer_traits<RBM>::decay()) == decay_type::L1L2){
            std::cout << "   weight_cost(L2)=" << rbm.l2_weight_cost << std::endl;
        }

        if(layer_traits<RBM>::sparsity_method() == sparsity_method::LEE){
            std::cout << "   Sparsity (Lee): pbias=" << rbm.pbias << std::endl;
            std::cout << "   Sparsity (Lee): pbias_lambda=" << rbm.pbias_lambda << std::endl;
        } else if(layer_traits<RBM>::sparsity_method() == sparsity_method::GLOBAL_TARGET){
            std::cout << "   sparsity_target(Global)=" << rbm.sparsity_target << std::endl;
        } else if(layer_traits<RBM>::sparsity_method() == sparsity_method::LOCAL_TARGET){
            std::cout << "   sparsity_target(Local)=" << rbm.sparsity_target << std::endl;
        }
    }

    template<typename RBM = R>
    void epoch_end(std::size_t epoch, const rbm_training_context& context, const RBM& /*rbm*/){
        char formatted[1024];
        if(layer_traits<RBM>::free_energy()){
            snprintf(formatted, 1024, "epoch %ld - Reconstruction error: %.5f - Free energy: %.3f - Sparsity: %.5f\n", epoch,
                context.reconstruction_error, context.free_energy, context.sparsity);
        } else {
            snprintf(formatted, 1024, "epoch %ld - Reconstruction error: %.5f - Sparsity: %.5f\n", epoch, context.reconstruction_error, context.sparsity);
        }
        std::cout << formatted;
    }

    template<typename RBM = R>
    void batch_end(const RBM& /* rbm */, const rbm_training_context& context, std::size_t batch, std::size_t batches){
        char formatted[1024];
        sprintf(formatted, "Batch %ld/%ld - Reconstruction error: %.5f - Sparsity: %.5f\n", batch, batches,
            context.batch_error, context.batch_sparsity);
        std::cout << formatted;
    }

    template<typename RBM = R>
    void training_end(const RBM&){
        std::cout << "Training took " << watch.elapsed() << "s" << std::endl;
    }
};

template<typename DBN>
struct default_dbn_watcher {
    static constexpr const bool ignore_sub = false;
    static constexpr const bool replace_sub = false;

    cpp::stop_watch<std::chrono::seconds> watch;

    void pretraining_begin(const DBN& /*dbn*/, std::size_t max_epochs){
        std::cout << "DBN: Pretraining begin for " << max_epochs << " epochs" << std::endl;
    }

    template<typename RBM>
    void pretrain_layer(const DBN& /*dbn*/, std::size_t I, std::size_t input_size){
        using rbm_t = RBM;

        if(input_size > 0){
            std::cout << "DBN: Pretrain layer " << I << " (" << rbm_t::to_short_string() << ") with " << input_size << " entries" << std::endl;
        } else {
            std::cout << "DBN: Pretrain layer " << I << " (" << rbm_t::to_short_string() << ")" << std::endl;
        }
    }

    void pretraining_end(const DBN& /*dbn*/){
        std::cout << "DBN: Pretraining finished after " << watch.elapsed() << "s" << std::endl;
    }

    void pretraining_batch(const DBN& /*dbn*/, std::size_t batch){
        std::cout << "DBN: Pretraining batch " << batch << std::endl;
    }

    void fine_tuning_begin(const DBN& dbn){
        std::cout << "Train DBN with \"" << DBN::desc::template trainer_t<DBN>::name() << "\"" << std::endl;
        std::cout << "With parameters:" << std::endl;
        std::cout << "   learning_rate=" << dbn.learning_rate << std::endl;

        if(dbn_traits<DBN>::has_momentum()){
            std::cout << "   momentum=" << dbn.momentum << std::endl;
        }
    }

    void ft_epoch_end(std::size_t epoch, double error, const DBN&){
        char formatted[1024];
        snprintf(formatted, 1024, "epoch %ld - Classification error: %.5f \n", epoch, error);
        std::cout << formatted;
    }

    void fine_tuning_end(const DBN&){
        std::cout << "Training took " << watch.elapsed() << "s" << std::endl;
    }
};

template<typename DBN>
struct silent_dbn_watcher : default_dbn_watcher<DBN> {
    static constexpr const bool ignore_sub = true;
    static constexpr const bool replace_sub = false;
};

//TODO This is currently useless

template<typename R>
struct histogram_watcher {
    default_rbm_watcher<R> parent;

    template<typename RBM = R>
    void training_begin(const RBM& rbm){
        parent.training_begin(rbm);
    }

    template<typename RBM = R>
    void epoch_end(std::size_t epoch, double error, double /*free_energy*/, const RBM& rbm){
        parent.epoch_end(epoch, error, rbm);
    }

    template<typename RBM = R>
    void batch_end(const RBM& rbm, const rbm_training_context& context, std::size_t batch, std::size_t batches){
        parent.batch_end(rbm, context, batch, batches);
    }

    template<typename RBM = R>
    void training_end(const RBM& rbm){
        parent.training_end(rbm);
    }

    void generate_hidden_images(std::size_t epoch, const R& rbm){
        mkdir("reports", 0777);

        auto folder = "reports/epoch_" + std::to_string(epoch);
        mkdir(folder.c_str(), 0777);

        for(std::size_t j = 0; j < R::num_hidden; ++j){
            auto path = folder + "/h_" + std::to_string(j) + ".dat";
            std::ofstream file(path, std::ios::out);

            if(!file){
                std::cout << "Could not open file " << path << std::endl;
            } else {
                std::size_t i = R::num_visible;
                while(i > 0){
                    --i;

                    auto value = rbm.w(i,j);
                    file << static_cast<std::size_t>(value > 0 ? static_cast<std::size_t>(value * 255.0) << 8 : static_cast<std::size_t>(-value * 255.0) << 16) << " ";
                }

                file << std::endl;
                file.close();
            }
        }
    }

    void generate_histograms(std::size_t epoch, const R& rbm){
        mkdir("reports", 0777);

        auto folder = "reports/epoch_" + std::to_string(epoch);
        mkdir(folder.c_str(), 0777);

        generate_histogram(folder + "/weights.dat", rbm.w);
        generate_histogram(folder + "/visibles.dat", rbm.a);
        generate_histogram(folder + "/hiddens.dat", rbm.b);
    }

    template<typename Container>
    void generate_histogram(const std::string& path, const Container& weights){
        std::ofstream file(path, std::ios::out);

        if(!file){
            std::cout << "Could not open file " << path << std::endl;
        } else {
            for(auto& weight : weights){
                file << weight << std::endl;
            }

            file << std::endl;
            file.close();
        }
    }
};

} //end of dll namespace

#endif
<commit_msg>Complete watcher<commit_after>//=======================================================================
// Copyright (c) 2014-2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef DLL_WATCHER_HPP
#define DLL_WATCHER_HPP

#include <fstream>

#include <sys/stat.h>

#include "cpp_utils/stop_watch.hpp"

#include "rbm_training_context.hpp"
#include "layer_traits.hpp"
#include "dbn_traits.hpp"

namespace dll {

template<typename R>
struct default_rbm_watcher {
    cpp::stop_watch<std::chrono::seconds> watch;

    template<typename RBM = R>
    void training_begin(const RBM& rbm){
        std::cout << "Train RBM with \"" << RBM::desc::template trainer_t<RBM,false>::name() << "\"" << std::endl;

        rbm.display();

        std::cout << "With parameters:" << std::endl;
        std::cout << "   learning_rate=" << rbm.learning_rate << std::endl;

        if(layer_traits<RBM>::has_momentum()){
            std::cout << "   momentum=" << rbm.momentum << std::endl;
        }

        if(w_decay(layer_traits<RBM>::decay()) == decay_type::L1 || w_decay(layer_traits<RBM>::decay()) == decay_type::L1L2){
            std::cout << "   weight_cost(L1)=" << rbm.l1_weight_cost << std::endl;
        }

        if(w_decay(layer_traits<RBM>::decay()) == decay_type::L2 || w_decay(layer_traits<RBM>::decay()) == decay_type::L1L2){
            std::cout << "   weight_cost(L2)=" << rbm.l2_weight_cost << std::endl;
        }

        if(layer_traits<RBM>::sparsity_method() == sparsity_method::LEE){
            std::cout << "   Sparsity (Lee): pbias=" << rbm.pbias << std::endl;
            std::cout << "   Sparsity (Lee): pbias_lambda=" << rbm.pbias_lambda << std::endl;
        } else if(layer_traits<RBM>::sparsity_method() == sparsity_method::GLOBAL_TARGET){
            std::cout << "   sparsity_target(Global)=" << rbm.sparsity_target << std::endl;
        } else if(layer_traits<RBM>::sparsity_method() == sparsity_method::LOCAL_TARGET){
            std::cout << "   sparsity_target(Local)=" << rbm.sparsity_target << std::endl;
        }
    }

    template<typename RBM = R>
    void epoch_end(std::size_t epoch, const rbm_training_context& context, const RBM& /*rbm*/){
        char formatted[1024];
        if(layer_traits<RBM>::free_energy()){
            snprintf(formatted, 1024, "epoch %ld - Reconstruction error: %.5f - Free energy: %.3f - Sparsity: %.5f\n", epoch,
                context.reconstruction_error, context.free_energy, context.sparsity);
        } else {
            snprintf(formatted, 1024, "epoch %ld - Reconstruction error: %.5f - Sparsity: %.5f\n", epoch, context.reconstruction_error, context.sparsity);
        }
        std::cout << formatted;
    }

    template<typename RBM = R>
    void batch_end(const RBM& /* rbm */, const rbm_training_context& context, std::size_t batch, std::size_t batches){
        char formatted[1024];
        sprintf(formatted, "Batch %ld/%ld - Reconstruction error: %.5f - Sparsity: %.5f\n", batch, batches,
            context.batch_error, context.batch_sparsity);
        std::cout << formatted;
    }

    template<typename RBM = R>
    void training_end(const RBM&){
        std::cout << "Training took " << watch.elapsed() << "s" << std::endl;
    }
};

template<typename DBN>
struct default_dbn_watcher {
    static constexpr const bool ignore_sub = false;
    static constexpr const bool replace_sub = false;

    cpp::stop_watch<std::chrono::seconds> watch;

    void pretraining_begin(const DBN& /*dbn*/, std::size_t max_epochs){
        std::cout << "DBN: Pretraining begin for " << max_epochs << " epochs" << std::endl;
    }

    template<typename RBM>
    void pretrain_layer(const DBN& /*dbn*/, std::size_t I, std::size_t input_size){
        using rbm_t = RBM;

        if(input_size > 0){
            std::cout << "DBN: Pretrain layer " << I << " (" << rbm_t::to_short_string() << ") with " << input_size << " entries" << std::endl;
        } else {
            std::cout << "DBN: Pretrain layer " << I << " (" << rbm_t::to_short_string() << ")" << std::endl;
        }
    }

    void pretraining_end(const DBN& /*dbn*/){
        std::cout << "DBN: Pretraining finished after " << watch.elapsed() << "s" << std::endl;
    }

    void pretraining_batch(const DBN& /*dbn*/, std::size_t batch){
        std::cout << "DBN: Pretraining batch " << batch << std::endl;
    }

    void fine_tuning_begin(const DBN& dbn){
        std::cout << "Train DBN with \"" << DBN::desc::template trainer_t<DBN>::name() << "\"" << std::endl;
        std::cout << "With parameters:" << std::endl;
        std::cout << "   learning_rate=" << dbn.learning_rate << std::endl;

        if(dbn_traits<DBN>::has_momentum()){
            std::cout << "   momentum=" << dbn.momentum << std::endl;
        }

        if(w_decay(dbn_traits<DBN>::decay()) == decay_type::L1 || w_decay(dbn_traits<DBN>::decay()) == decay_type::L1L2){
            std::cout << "   weight_cost(L1)=" << dbn.l1_weight_cost << std::endl;
        }

        if(w_decay(dbn_traits<DBN>::decay()) == decay_type::L2 || w_decay(dbn_traits<DBN>::decay()) == decay_type::L1L2){
            std::cout << "   weight_cost(L2)=" << dbn.l2_weight_cost << std::endl;
        }
    }

    void ft_epoch_end(std::size_t epoch, double error, const DBN&){
        char formatted[1024];
        snprintf(formatted, 1024, "epoch %ld - Classification error: %.5f \n", epoch, error);
        std::cout << formatted;
    }

    void fine_tuning_end(const DBN&){
        std::cout << "Training took " << watch.elapsed() << "s" << std::endl;
    }
};

template<typename DBN>
struct silent_dbn_watcher : default_dbn_watcher<DBN> {
    static constexpr const bool ignore_sub = true;
    static constexpr const bool replace_sub = false;
};

//TODO This is currently useless

template<typename R>
struct histogram_watcher {
    default_rbm_watcher<R> parent;

    template<typename RBM = R>
    void training_begin(const RBM& rbm){
        parent.training_begin(rbm);
    }

    template<typename RBM = R>
    void epoch_end(std::size_t epoch, double error, double /*free_energy*/, const RBM& rbm){
        parent.epoch_end(epoch, error, rbm);
    }

    template<typename RBM = R>
    void batch_end(const RBM& rbm, const rbm_training_context& context, std::size_t batch, std::size_t batches){
        parent.batch_end(rbm, context, batch, batches);
    }

    template<typename RBM = R>
    void training_end(const RBM& rbm){
        parent.training_end(rbm);
    }

    void generate_hidden_images(std::size_t epoch, const R& rbm){
        mkdir("reports", 0777);

        auto folder = "reports/epoch_" + std::to_string(epoch);
        mkdir(folder.c_str(), 0777);

        for(std::size_t j = 0; j < R::num_hidden; ++j){
            auto path = folder + "/h_" + std::to_string(j) + ".dat";
            std::ofstream file(path, std::ios::out);

            if(!file){
                std::cout << "Could not open file " << path << std::endl;
            } else {
                std::size_t i = R::num_visible;
                while(i > 0){
                    --i;

                    auto value = rbm.w(i,j);
                    file << static_cast<std::size_t>(value > 0 ? static_cast<std::size_t>(value * 255.0) << 8 : static_cast<std::size_t>(-value * 255.0) << 16) << " ";
                }

                file << std::endl;
                file.close();
            }
        }
    }

    void generate_histograms(std::size_t epoch, const R& rbm){
        mkdir("reports", 0777);

        auto folder = "reports/epoch_" + std::to_string(epoch);
        mkdir(folder.c_str(), 0777);

        generate_histogram(folder + "/weights.dat", rbm.w);
        generate_histogram(folder + "/visibles.dat", rbm.a);
        generate_histogram(folder + "/hiddens.dat", rbm.b);
    }

    template<typename Container>
    void generate_histogram(const std::string& path, const Container& weights){
        std::ofstream file(path, std::ios::out);

        if(!file){
            std::cout << "Could not open file " << path << std::endl;
        } else {
            for(auto& weight : weights){
                file << weight << std::endl;
            }

            file << std::endl;
            file.close();
        }
    }
};

} //end of dll namespace

#endif
<|endoftext|>


<commit_before>/* This file is part of Ingen.
 * Copyright 2008-2011 David Robillard <http://drobilla.net>
 *
 * Ingen is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef INGEN_SHARED_RESOURCEIMPL_HPP
#define INGEN_SHARED_RESOURCEIMPL_HPP

#include "raul/URI.hpp"
#include "raul/SharedPtr.hpp"

#include "ingen/Resource.hpp"

namespace Ingen {
namespace Shared {

class URIs;

class ResourceImpl : virtual public Resource
{
public:
	ResourceImpl(URIs& uris, const Raul::URI& uri)
		: _uris(uris)
		, _uri(uri)
	{}

	URIs& uris() const { return _uris; }

	virtual void             set_uri(const Raul::URI& uri) { _uri = uri; }
	virtual const Raul::URI& uri()  const { return _uri; }

	const Properties& properties() const { return _properties; }
	Properties&       properties()       { return _properties; }

	Properties properties(Resource::Graph ctx) const;

	const Raul::Atom& get_property(const Raul::URI& uri) const;
	const Raul::Atom& set_property(const Raul::URI& uri, const Raul::Atom& value,
	                               Resource::Graph ctx=Resource::DEFAULT);
	void              remove_property(const Raul::URI& uri, const Raul::Atom& value);
	bool              has_property(const Raul::URI& uri, const Raul::Atom& value) const;
	void              add_property(const Raul::URI& uri, const Raul::Atom& value,
	                               Graph ctx=DEFAULT);
	void              set_properties(const Properties& p);
	void              add_properties(const Properties& p);
	void              remove_properties(const Properties& p);

	void dump(std::ostream& os) const;

	/** Get the ingen type from a set of Properties.
	 * If some coherent ingen type is found, true is returned and the appropriate
	 * output parameter set to true.  Otherwise false is returned.
	 */
	static bool type(const URIs&       uris,
	                 const Properties& properties,
	                 bool&             patch,
	                 bool&             node,
	                 bool&             port,
	                 bool&             is_output);

protected:
	const Raul::Atom& set_property(const Raul::URI& uri, const Raul::Atom& value) const;

	URIs& _uris;

private:
	Raul::URI          _uri;
	mutable Properties _properties;
};

} // namespace Shared
} // namespace Ingen

#endif // INGEN_SHARED_RESOURCEIMPL_HPP

<commit_msg>Missing portion of previous commit (r4045).<commit_after>/* This file is part of Ingen.
 * Copyright 2008-2011 David Robillard <http://drobilla.net>
 *
 * Ingen is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef INGEN_SHARED_RESOURCEIMPL_HPP
#define INGEN_SHARED_RESOURCEIMPL_HPP

#include "raul/URI.hpp"
#include "raul/SharedPtr.hpp"

#include "ingen/Resource.hpp"

namespace Ingen {
namespace Shared {

class URIs;

class ResourceImpl : virtual public Resource
{
public:
	ResourceImpl(URIs& uris, const Raul::URI& uri)
		: _uris(uris)
		, _uri(uri)
	{}

	URIs& uris() const { return _uris; }

	virtual void             set_uri(const Raul::URI& uri) { _uri = uri; }
	virtual const Raul::URI& uri()  const { return _uri; }

	const Properties& properties() const { return _properties; }
	Properties&       properties()       { return _properties; }

	Properties properties(Resource::Graph ctx) const;

	const Raul::Atom& get_property(const Raul::URI& uri) const;

	const Raul::Atom& set_property(const Raul::URI&  uri,
	                               const Raul::Atom& value,
	                               Resource::Graph   ctx=Resource::DEFAULT);

	/** Hook called whenever a property is added.
	 * This can be used by derived classes to implement special behaviour for
	 * particular properties (e.g. ingen:value for ports).
	 */
	virtual void on_property(const Raul::URI& uri, const Raul::Atom& value) {}

	void remove_property(const Raul::URI& uri, const Raul::Atom& value);
	bool has_property(const Raul::URI& uri, const Raul::Atom& value) const;
	void add_property(const Raul::URI&  uri,
	                  const Raul::Atom& value,
	                  Graph             ctx = DEFAULT);
	void set_properties(const Properties& p);
	void add_properties(const Properties& p);
	void remove_properties(const Properties& p);

	void dump(std::ostream& os) const;

	/** Get the ingen type from a set of Properties.
	 * If some coherent ingen type is found, true is returned and the appropriate
	 * output parameter set to true.  Otherwise false is returned.
	 */
	static bool type(const URIs&       uris,
	                 const Properties& properties,
	                 bool&             patch,
	                 bool&             node,
	                 bool&             port,
	                 bool&             is_output);

protected:
	const Raul::Atom& set_property(const Raul::URI& uri, const Raul::Atom& value) const;

	URIs& _uris;

private:
	Raul::URI          _uri;
	mutable Properties _properties;
};

} // namespace Shared
} // namespace Ingen

#endif // INGEN_SHARED_RESOURCEIMPL_HPP

<|endoftext|>