<commit_before>/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

============================================================================*/
// Testing
#include "mitkTestingMacros.h"
#include "mitkTestFixture.h"

//MITK includes
#include "mitkArbitraryTimeGeometry.h"
#include "mitkImageStatisticsContainerNodeHelper.h"
#include "mitkImageStatisticsContainerManager.h"
#include "mitkImageStatisticsContainer.h"

class mitkImageStatisticsContainerTestSuite : public mitk::TestFixture
{
    CPPUNIT_TEST_SUITE(mitkImageStatisticsContainerTestSuite);
    MITK_TEST(StatisticNamesIO);
    MITK_TEST(InvalidKey);
    MITK_TEST(TimeSteps);
    MITK_TEST(PrintSelf);
    MITK_TEST(InternalClone);
    MITK_TEST(StatisticNames);
    MITK_TEST(Reset);
    CPPUNIT_TEST_SUITE_END();

private:
    mitk::ImageStatisticsContainer::Pointer m_StatisticsContainer;
    mitk::ImageStatisticsContainer::Pointer m_StatisticsContainer2;
    mitk::ImageStatisticsContainer::Pointer m_StatisticsContainer3;

    mitk::ImageStatisticsContainer::ImageStatisticsObject m_StatisticsObject;
    mitk::ImageStatisticsContainer::ImageStatisticsObject m_StatisticsObject2;
    mitk::ImageStatisticsContainer::ImageStatisticsObject m_StatisticsObject3;

    mitk::ArbitraryTimeGeometry::Pointer m_TimeGeometry;

    mitk::Geometry3D::Pointer m_Geometry1;
    mitk::Geometry3D::Pointer m_Geometry2;
    mitk::Geometry3D::Pointer m_Geometry3;
    mitk::Geometry3D::Pointer m_Geometry3_5;
    mitk::Geometry3D::Pointer m_Geometry4;
    mitk::Geometry3D::Pointer m_Geometry5;

    mitk::TimePointType m_Geometry1MinTP;
    mitk::TimePointType m_Geometry2MinTP;
    mitk::TimePointType m_Geometry3MinTP;
    mitk::TimePointType m_Geometry3_5MinTP;
    mitk::TimePointType m_Geometry4MinTP;
    mitk::TimePointType m_Geometry5MinTP;

    mitk::TimePointType m_Geometry1MaxTP;
    mitk::TimePointType m_Geometry2MaxTP;
    mitk::TimePointType m_Geometry3MaxTP;
    mitk::TimePointType m_Geometry3_5MaxTP;
    mitk::TimePointType m_Geometry4MaxTP;
    mitk::TimePointType m_Geometry5MaxTP;

    std::vector<std::string> estimatedDefaultStatisticNames
    {
        "Mean",
        "Median",
        "StandardDeviation",
        "RMS",
        "Max",
        "MaxPosition",
        "Min",
        "MinPosition",
        "#Voxel",
        "Volume [mm^3]",
        "Skewness",
        "Kurtosis",
        "Uniformity",
        "Entropy",
        "MPP",
        "UPP"
    };

public:
    void setUp() override
    {
        m_StatisticsContainer = mitk::ImageStatisticsContainer::New();
        m_StatisticsContainer2 = mitk::ImageStatisticsContainer::New();
        m_StatisticsContainer3 = mitk::ImageStatisticsContainer::New();

        m_Geometry1 = mitk::Geometry3D::New();
        m_Geometry2 = mitk::Geometry3D::New();
        m_Geometry3 = mitk::Geometry3D::New();
        m_Geometry3_5 = mitk::Geometry3D::New();
        m_Geometry4 = mitk::Geometry3D::New();
        m_Geometry5 = mitk::Geometry3D::New();

        m_Geometry1MinTP = 1;
        m_Geometry2MinTP = 2;
        m_Geometry3MinTP = 3;
        m_Geometry3_5MinTP = 3.5;
        m_Geometry4MinTP = 4;
        m_Geometry5MinTP = 5;

        m_Geometry1MaxTP = 1.9;
        m_Geometry2MaxTP = 2.9;
        m_Geometry3MaxTP = 3.9;
        m_Geometry3_5MaxTP = 3.9;
        m_Geometry4MaxTP = 4.9;
        m_Geometry5MaxTP = 5.9;

        m_TimeGeometry = mitk::ArbitraryTimeGeometry::New();
        m_TimeGeometry->ClearAllGeometries();
        m_TimeGeometry->AppendNewTimeStep(m_Geometry1, m_Geometry1MinTP, m_Geometry1MaxTP);
        m_TimeGeometry->AppendNewTimeStep(m_Geometry2, m_Geometry2MinTP, m_Geometry2MaxTP);
        m_TimeGeometry->AppendNewTimeStep(m_Geometry3, m_Geometry3MinTP, m_Geometry3MaxTP);
        m_TimeGeometry->AppendNewTimeStep(m_Geometry4, m_Geometry4MinTP, m_Geometry4MaxTP);
        m_TimeGeometry->AppendNewTimeStep(m_Geometry5, m_Geometry5MinTP, m_Geometry5MaxTP);
    }

    void tearDown() override
    {
        m_StatisticsContainer->Reset();
        m_StatisticsContainer2->Reset();
        m_StatisticsContainer3->Reset();

        m_StatisticsObject.Reset();
        m_StatisticsObject2.Reset();
        m_StatisticsObject3.Reset();

        m_TimeGeometry->ClearAllGeometries();
    }

    void StatisticNamesIO()
    {
        auto defaultStatisticNames = mitk::ImageStatisticsContainer::ImageStatisticsObject::GetDefaultStatisticNames();
        for (size_t i = 0; i < estimatedDefaultStatisticNames.size(); i++)
        {
            CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated default statistics names are not correct.", defaultStatisticNames.at(i), estimatedDefaultStatisticNames.at(i));
        }

        std::string testName = "testName";
        double realTypeTest = 3.14;
        m_StatisticsObject.AddStatistic(testName, realTypeTest);
        auto customStatisticNames = m_StatisticsObject.GetCustomStatisticNames();
        size_t one = 1;
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Amount of estimated custom statistics names is not correct.", customStatisticNames.size(), one);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated custom statistics names are not correct.", customStatisticNames.front(), testName);

        auto allStatisticNames = m_StatisticsObject.GetAllStatisticNames();
        estimatedDefaultStatisticNames.push_back(testName);
        for (size_t i = 0; i < estimatedDefaultStatisticNames.size(); i++)
        {
            CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated statistics names are not correct.", allStatisticNames.at(i), estimatedDefaultStatisticNames.at(i));
        }

        auto existingStatisticNames = m_StatisticsObject.GetExistingStatisticNames();
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Amount of estimated existing statistics names is not correct.", existingStatisticNames.size(), one);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated existing statistics names are not correct.", existingStatisticNames.front(), testName);

        m_StatisticsObject.Reset();
        CPPUNIT_ASSERT_MESSAGE("Custom statistics names were not removed correctly.", m_StatisticsObject.GetCustomStatisticNames().empty());
    }

    void InvalidKey()
    {
        CPPUNIT_ASSERT_THROW_MESSAGE("Exception should have been thrown because key does not exists.", m_StatisticsObject.GetValueNonConverted("Test"), mitk::Exception);
    }

    void TimeSteps()
    {
        m_StatisticsContainer->SetTimeGeometry(m_TimeGeometry);

        m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->TimeStepExists(0), true);
        m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->TimeStepExists(1), true);
        m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->TimeStepExists(2), true);
        m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->TimeStepExists(3), true);
        m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->TimeStepExists(4), true);

        CPPUNIT_ASSERT_THROW_MESSAGE("Out of timeStep geometry bounds timeStep was added but no exception was thrown.", m_StatisticsContainer->SetStatisticsForTimeStep(42, m_StatisticsObject), mitk::Exception);

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistics container does not contain the right amount of timeSteps.", static_cast<int> (m_StatisticsContainer->GetNumberOfTimeSteps()), 5);
    }

    void PrintSelf()
    {
        m_StatisticsContainer->SetTimeGeometry(m_TimeGeometry);

        m_StatisticsObject.AddStatistic("Test", 4.2);

        m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject);

        std::stringstream print;
        m_StatisticsContainer->Print(print);

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Data was changed.", static_cast<int> (print.str().length()), 1237);
    }

    void InternalClone()
    {
        auto clone = m_StatisticsContainer->Clone();

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", m_StatisticsContainer->GetGeometry(), clone->GetGeometry());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", m_StatisticsContainer->GetNumberOfTimeSteps(), clone->GetNumberOfTimeSteps());
    }

    void StatisticNames()
    {
        m_StatisticsContainer->SetTimeGeometry(m_TimeGeometry);

        m_StatisticsObject.AddStatistic("Test", 4.2);
        m_StatisticsObject2.AddStatistic("Test2", 4.2);
        m_StatisticsObject3.AddStatistic("Test3", 4.2);

        m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject);

        m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject2);
        m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject2);
        m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject2);
        m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject2);
        m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject2);

        m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject3);
        m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject3);
        m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject3);
        m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject3);
        m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject3);

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated statistics names are not correct.", mitk::GetAllStatisticNames(m_StatisticsContainer).size(), estimatedDefaultStatisticNames.size() + 1);

        std::vector<mitk::ImageStatisticsContainer::ConstPointer> containers;

        containers.push_back(m_StatisticsContainer.GetPointer());
        containers.push_back(m_StatisticsContainer2.GetPointer());
        containers.push_back(m_StatisticsContainer3.GetPointer());

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated statistics names are not correct.", mitk::GetAllStatisticNames(containers).size(), estimatedDefaultStatisticNames.size() + 1);
    }

    void Reset()
    {
        m_StatisticsContainer->SetTimeGeometry(m_TimeGeometry);

        m_StatisticsObject.AddStatistic("Test", 4.2);

        m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject);

        m_StatisticsContainer->Reset();

        m_StatisticsObject.Reset();

        m_TimeGeometry->ClearAllGeometries();

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(0).GetExistingStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(0).GetCustomStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(1).GetExistingStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(1).GetCustomStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(2).GetExistingStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(2).GetCustomStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(3).GetExistingStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(3).GetCustomStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(4).GetExistingStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(4).GetCustomStatisticNames().size(), size_t());

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic was not deleted correctly.", m_StatisticsObject.HasStatistic("Test"), false);

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Time geometry was not cleared correctly.", m_TimeGeometry->IsValid(), false);
    }
};
MITK_TEST_SUITE_REGISTRATION(mitkImageStatisticsContainer)
<commit_msg>Add a test to check if an existing statistic is overwritten<commit_after>/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

============================================================================*/
// Testing
#include "mitkTestingMacros.h"
#include "mitkTestFixture.h"

//MITK includes
#include "mitkArbitraryTimeGeometry.h"
#include "mitkImageStatisticsContainerNodeHelper.h"
#include "mitkImageStatisticsContainerManager.h"
#include "mitkImageStatisticsContainer.h"

class mitkImageStatisticsContainerTestSuite : public mitk::TestFixture
{
    CPPUNIT_TEST_SUITE(mitkImageStatisticsContainerTestSuite);
    MITK_TEST(StatisticNamesIO);
    MITK_TEST(InvalidKey);
    MITK_TEST(TimeSteps);
    MITK_TEST(PrintSelf);
    MITK_TEST(InternalClone);
    MITK_TEST(StatisticNames);
    MITK_TEST(OverwriteStatistic);
    MITK_TEST(Reset);
    CPPUNIT_TEST_SUITE_END();

private:
    mitk::ImageStatisticsContainer::Pointer m_StatisticsContainer;
    mitk::ImageStatisticsContainer::Pointer m_StatisticsContainer2;
    mitk::ImageStatisticsContainer::Pointer m_StatisticsContainer3;

    mitk::ImageStatisticsContainer::ImageStatisticsObject m_StatisticsObject;
    mitk::ImageStatisticsContainer::ImageStatisticsObject m_StatisticsObject2;
    mitk::ImageStatisticsContainer::ImageStatisticsObject m_StatisticsObject3;

    mitk::ArbitraryTimeGeometry::Pointer m_TimeGeometry;

    mitk::Geometry3D::Pointer m_Geometry1;
    mitk::Geometry3D::Pointer m_Geometry2;
    mitk::Geometry3D::Pointer m_Geometry3;
    mitk::Geometry3D::Pointer m_Geometry3_5;
    mitk::Geometry3D::Pointer m_Geometry4;
    mitk::Geometry3D::Pointer m_Geometry5;

    mitk::TimePointType m_Geometry1MinTP;
    mitk::TimePointType m_Geometry2MinTP;
    mitk::TimePointType m_Geometry3MinTP;
    mitk::TimePointType m_Geometry3_5MinTP;
    mitk::TimePointType m_Geometry4MinTP;
    mitk::TimePointType m_Geometry5MinTP;

    mitk::TimePointType m_Geometry1MaxTP;
    mitk::TimePointType m_Geometry2MaxTP;
    mitk::TimePointType m_Geometry3MaxTP;
    mitk::TimePointType m_Geometry3_5MaxTP;
    mitk::TimePointType m_Geometry4MaxTP;
    mitk::TimePointType m_Geometry5MaxTP;

    std::vector<std::string> estimatedDefaultStatisticNames
    {
        "Mean",
        "Median",
        "StandardDeviation",
        "RMS",
        "Max",
        "MaxPosition",
        "Min",
        "MinPosition",
        "#Voxel",
        "Volume [mm^3]",
        "Skewness",
        "Kurtosis",
        "Uniformity",
        "Entropy",
        "MPP",
        "UPP"
    };

public:
    void setUp() override
    {
        m_StatisticsContainer = mitk::ImageStatisticsContainer::New();
        m_StatisticsContainer2 = mitk::ImageStatisticsContainer::New();
        m_StatisticsContainer3 = mitk::ImageStatisticsContainer::New();

        m_Geometry1 = mitk::Geometry3D::New();
        m_Geometry2 = mitk::Geometry3D::New();
        m_Geometry3 = mitk::Geometry3D::New();
        m_Geometry3_5 = mitk::Geometry3D::New();
        m_Geometry4 = mitk::Geometry3D::New();
        m_Geometry5 = mitk::Geometry3D::New();

        m_Geometry1MinTP = 1;
        m_Geometry2MinTP = 2;
        m_Geometry3MinTP = 3;
        m_Geometry3_5MinTP = 3.5;
        m_Geometry4MinTP = 4;
        m_Geometry5MinTP = 5;

        m_Geometry1MaxTP = 1.9;
        m_Geometry2MaxTP = 2.9;
        m_Geometry3MaxTP = 3.9;
        m_Geometry3_5MaxTP = 3.9;
        m_Geometry4MaxTP = 4.9;
        m_Geometry5MaxTP = 5.9;

        m_TimeGeometry = mitk::ArbitraryTimeGeometry::New();
        m_TimeGeometry->ClearAllGeometries();
        m_TimeGeometry->AppendNewTimeStep(m_Geometry1, m_Geometry1MinTP, m_Geometry1MaxTP);
        m_TimeGeometry->AppendNewTimeStep(m_Geometry2, m_Geometry2MinTP, m_Geometry2MaxTP);
        m_TimeGeometry->AppendNewTimeStep(m_Geometry3, m_Geometry3MinTP, m_Geometry3MaxTP);
        m_TimeGeometry->AppendNewTimeStep(m_Geometry4, m_Geometry4MinTP, m_Geometry4MaxTP);
        m_TimeGeometry->AppendNewTimeStep(m_Geometry5, m_Geometry5MinTP, m_Geometry5MaxTP);
    }

    void tearDown() override
    {
        m_StatisticsContainer->Reset();
        m_StatisticsContainer2->Reset();
        m_StatisticsContainer3->Reset();

        m_StatisticsObject.Reset();
        m_StatisticsObject2.Reset();
        m_StatisticsObject3.Reset();

        m_TimeGeometry->ClearAllGeometries();
    }

    void StatisticNamesIO()
    {
        auto defaultStatisticNames = mitk::ImageStatisticsContainer::ImageStatisticsObject::GetDefaultStatisticNames();
        for (size_t i = 0; i < estimatedDefaultStatisticNames.size(); i++)
        {
            CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated default statistics names are not correct.", defaultStatisticNames.at(i), estimatedDefaultStatisticNames.at(i));
        }

        std::string testName = "testName";
        double realTypeTest = 3.14;
        m_StatisticsObject.AddStatistic(testName, realTypeTest);
        auto customStatisticNames = m_StatisticsObject.GetCustomStatisticNames();
        size_t one = 1;
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Amount of estimated custom statistics names is not correct.", customStatisticNames.size(), one);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated custom statistics names are not correct.", customStatisticNames.front(), testName);

        auto allStatisticNames = m_StatisticsObject.GetAllStatisticNames();
        estimatedDefaultStatisticNames.push_back(testName);
        for (size_t i = 0; i < estimatedDefaultStatisticNames.size(); i++)
        {
            CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated statistics names are not correct.", allStatisticNames.at(i), estimatedDefaultStatisticNames.at(i));
        }

        auto existingStatisticNames = m_StatisticsObject.GetExistingStatisticNames();
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Amount of estimated existing statistics names is not correct.", existingStatisticNames.size(), one);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated existing statistics names are not correct.", existingStatisticNames.front(), testName);

        m_StatisticsObject.Reset();
        CPPUNIT_ASSERT_MESSAGE("Custom statistics names were not removed correctly.", m_StatisticsObject.GetCustomStatisticNames().empty());
    }

    void InvalidKey()
    {
        CPPUNIT_ASSERT_THROW_MESSAGE("Exception should have been thrown because key does not exists.", m_StatisticsObject.GetValueNonConverted("Test"), mitk::Exception);
    }

    void TimeSteps()
    {
        m_StatisticsContainer->SetTimeGeometry(m_TimeGeometry);

        m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->TimeStepExists(0), true);
        m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->TimeStepExists(1), true);
        m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->TimeStepExists(2), true);
        m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->TimeStepExists(3), true);
        m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Previous added time step was not saved correctly.", m_StatisticsContainer->TimeStepExists(4), true);

        CPPUNIT_ASSERT_THROW_MESSAGE("Out of timeStep geometry bounds timeStep was added but no exception was thrown.", m_StatisticsContainer->SetStatisticsForTimeStep(42, m_StatisticsObject), mitk::Exception);

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistics container does not contain the right amount of timeSteps.", static_cast<int> (m_StatisticsContainer->GetNumberOfTimeSteps()), 5);
    }

    void PrintSelf()
    {
        m_StatisticsContainer->SetTimeGeometry(m_TimeGeometry);

        m_StatisticsObject.AddStatistic("Test", 4.2);

        m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject);

        std::stringstream print;
        m_StatisticsContainer->Print(print);

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Data was changed.", static_cast<int> (print.str().length()), 1237);
    }

    void InternalClone()
    {
        auto clone = m_StatisticsContainer->Clone();

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", m_StatisticsContainer->GetGeometry(), clone->GetGeometry());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Internal clone was not cloned correctly.", m_StatisticsContainer->GetNumberOfTimeSteps(), clone->GetNumberOfTimeSteps());
    }

    void StatisticNames()
    {
        m_StatisticsContainer->SetTimeGeometry(m_TimeGeometry);

        m_StatisticsObject.AddStatistic("Test", 4.2);
        m_StatisticsObject2.AddStatistic("Test2", 4.2);
        m_StatisticsObject3.AddStatistic("Test3", 4.2);

        m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject);

        m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject2);
        m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject2);
        m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject2);
        m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject2);
        m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject2);

        m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject3);
        m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject3);
        m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject3);
        m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject3);
        m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject3);

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated statistics names are not correct.", mitk::GetAllStatisticNames(m_StatisticsContainer).size(), estimatedDefaultStatisticNames.size() + 1);

    void OverwriteStatistic()
    {
        m_StatisticsContainer->SetTimeGeometry(m_TimeGeometry);

        m_StatisticsObject.AddStatistic("Test", 4.2);

        m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject);

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic was not correctly added to StatisticsObject.", boost::get<double> (m_StatisticsContainer->GetStatisticsForTimeStep(0).GetValueNonConverted("Test")), 4.2);

        // An existing statistic won't be updated by adding another statistic with same name to that object.
        m_StatisticsObject.AddStatistic("Test", 42.0);

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic was overwritten.", boost::get<double>(m_StatisticsContainer->GetStatisticsForTimeStep(0).GetValueNonConverted("Test")), 4.2);
    }
        std::vector<mitk::ImageStatisticsContainer::ConstPointer> containers;

        containers.push_back(m_StatisticsContainer.GetPointer());
        containers.push_back(m_StatisticsContainer2.GetPointer());
        containers.push_back(m_StatisticsContainer3.GetPointer());

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Estimated statistics names are not correct.", mitk::GetAllStatisticNames(containers).size(), estimatedDefaultStatisticNames.size() + 1);
    }

    void Reset()
    {
        m_StatisticsContainer->SetTimeGeometry(m_TimeGeometry);

        m_StatisticsObject.AddStatistic("Test", 4.2);

        m_StatisticsContainer->SetStatisticsForTimeStep(0, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(1, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(2, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(3, m_StatisticsObject);
        m_StatisticsContainer->SetStatisticsForTimeStep(4, m_StatisticsObject);

        m_StatisticsContainer->Reset();

        m_StatisticsObject.Reset();

        m_TimeGeometry->ClearAllGeometries();

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(0).GetExistingStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(0).GetCustomStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(1).GetExistingStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(1).GetCustomStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(2).GetExistingStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(2).GetCustomStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(3).GetExistingStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(3).GetCustomStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(4).GetExistingStatisticNames().size(), size_t());
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic object for time step was not deleted correctly.", m_StatisticsContainer->GetStatisticsForTimeStep(4).GetCustomStatisticNames().size(), size_t());

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Statistic was not deleted correctly.", m_StatisticsObject.HasStatistic("Test"), false);

        CPPUNIT_ASSERT_EQUAL_MESSAGE("Time geometry was not cleared correctly.", m_TimeGeometry->IsValid(), false);
    }
};
MITK_TEST_SUITE_REGISTRATION(mitkImageStatisticsContainer)
<|endoftext|>


<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2017 Nathan Osman
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include <qmdnsengine/bitmap.h>

#include "bitmap_p.h"

using namespace QMdnsEngine;

BitmapPrivate::BitmapPrivate()
    : length(0)
{
}

Bitmap::Bitmap()
    : d(new BitmapPrivate)
{
}

Bitmap::Bitmap(const Bitmap &other)
    : d(new BitmapPrivate)
{
    *this = other;
}

Bitmap &Bitmap::operator=(const Bitmap &other)
{
    *d = *other.d;
    return *this;
}

bool Bitmap::operator==(const Bitmap &other)
{
    return d->length == other.d->length && d->data == other.d->data;
}

Bitmap::~Bitmap()
{
    delete d;
}

quint8 Bitmap::length() const
{
    return d->length;
}

const quint8 *Bitmap::data() const
{
    return d->data;
}

void Bitmap::setData(quint8 length, const quint8 *data)
{
    d->length = length;
    for (int i = 0; i < d->length; ++i) {
        d->data[i] = data[i];
    }
}
<commit_msg>Fix comparison operator for Bitmap.<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2017 Nathan Osman
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include <qmdnsengine/bitmap.h>

#include "bitmap_p.h"

using namespace QMdnsEngine;

BitmapPrivate::BitmapPrivate()
    : length(0)
{
}

Bitmap::Bitmap()
    : d(new BitmapPrivate)
{
}

Bitmap::Bitmap(const Bitmap &other)
    : d(new BitmapPrivate)
{
    *this = other;
}

Bitmap &Bitmap::operator=(const Bitmap &other)
{
    *d = *other.d;
    return *this;
}

bool Bitmap::operator==(const Bitmap &other)
{
    if (!d->length == other.d->length) {
        return false;
    }
    for (int i = 0; i < d->length; ++i) {
        if (d->data[i] != other.d->data[i]) {
            return false;
        }
    }
    return true;
}

Bitmap::~Bitmap()
{
    delete d;
}

quint8 Bitmap::length() const
{
    return d->length;
}

const quint8 *Bitmap::data() const
{
    return d->data;
}

void Bitmap::setData(quint8 length, const quint8 *data)
{
    d->length = length;
    for (int i = 0; i < d->length; ++i) {
        d->data[i] = data[i];
    }
}
<|endoftext|>


<commit_before>#include "stack_alloc.hh"
#include "ten/thread_local.hh"
#include "ten/logging.hh"
#include <boost/context/stack_allocator.hpp>
#include <boost/context/stack_utils.hpp>
#include <sys/mman.h>
#include <algorithm>

namespace ten {

namespace stack_allocator {

size_t default_stacksize{ (size_t)256 * 1024 };
std::atomic<size_t> cache_maxsize{ (size_t)100 };

// impl

namespace {

inline void free_stack(void *ptr, size_t stack_size) {
    PCHECK(munmap(ptr, stack_size) == 0);
}

struct stack {
    void *ptr = nullptr;
    size_t size = 0;

    stack(void *p, size_t s) : ptr{p}, size{s} {}

    stack(const stack &) = delete;
    stack & operator = (const stack &) = delete;

    stack(stack &&other)               { take(other); }
    stack & operator = (stack &&other) { if (this != &other) take(other); return *this; }

    ~stack() { clear(); }

    void take(stack &other) {
        clear();
        std::swap(ptr, other.ptr);
        std::swap(size, other.size);
    }
    void clear() {
        if (ptr) {
            free_stack(ptr, size);
            ptr = nullptr;
        }
    }

    void *release() {
        void *tmp = nullptr;
        std::swap(tmp, ptr);
        return tmp;
    }
};

struct cache_tag {};
thread_cached<cache_tag, std::deque<stack>> stack_cache;

} // anon

// calling this function ensures all the above have been initialized
int initialize() { return 0; }

void *allocate(size_t stack_size) {
    // TODO: check stack_size >= min_stacksize (8k because of 4k guard page)
    auto &cache = *stack_cache;

    void *stack_ptr = nullptr;
    if (cache.empty()) {
        stack_ptr = mmap(nullptr, stack_size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_STACK, 0, 0);
        if (stack_ptr == MAP_FAILED) {
            throw bad_stack_alloc();
        }
        if (mprotect(stack_ptr, page_size, PROT_NONE) == -1) {
            free_stack(stack_ptr, stack_size);
            throw bad_stack_alloc();
        }
    } else {
        stack_ptr = cache.back().release();
        cache.pop_back();
    }
    return reinterpret_cast<void *>(reinterpret_cast<char *>(stack_ptr) + stack_size);
}

void deallocate(void *stack_end, size_t stack_size) noexcept {
    void *stack_ptr = reinterpret_cast<void *>(reinterpret_cast<char *>(stack_end) - stack_size);
    auto &cache = *stack_cache;

    try {
        if (cache.size() < cache_maxsize.load(std::memory_order_relaxed)) {
            cache.emplace_back(stack_ptr, stack_size);
        } else {
            free_stack(stack_ptr, stack_size);
        }
    } catch (std::bad_alloc &e) {
        free_stack(stack_ptr, stack_size);
    }
}

} // stack_allocator

} // ten

<commit_msg>use static_cast minimally, avoid reinterpret_cast where possible<commit_after>#include "stack_alloc.hh"
#include "ten/thread_local.hh"
#include "ten/logging.hh"
#include <boost/context/stack_allocator.hpp>
#include <boost/context/stack_utils.hpp>
#include <sys/mman.h>
#include <algorithm>

namespace ten {

namespace stack_allocator {

size_t default_stacksize{ (size_t)256 * 1024 };
std::atomic<size_t> cache_maxsize{ (size_t)100 };

// impl

namespace {

inline void free_stack(void *ptr, size_t stack_size) {
    PCHECK(munmap(ptr, stack_size) == 0);
}

struct stack {
    void *ptr = nullptr;
    size_t size = 0;

    stack(void *p, size_t s) : ptr{p}, size{s} {}

    stack(const stack &) = delete;
    stack & operator = (const stack &) = delete;

    stack(stack &&other)               { take(other); }
    stack & operator = (stack &&other) { if (this != &other) take(other); return *this; }

    ~stack() { clear(); }

    void take(stack &other) {
        clear();
        std::swap(ptr, other.ptr);
        std::swap(size, other.size);
    }
    void clear() {
        if (ptr) {
            free_stack(ptr, size);
            ptr = nullptr;
        }
    }

    void *release() {
        void *tmp = nullptr;
        std::swap(tmp, ptr);
        return tmp;
    }
};

struct cache_tag {};
thread_cached<cache_tag, std::deque<stack>> stack_cache;

} // anon

// calling this function ensures all the above have been initialized
int initialize() { return 0; }

void *allocate(size_t stack_size) {
    // TODO: check stack_size >= min_stacksize (8k because of 4k guard page)
    auto &cache = *stack_cache;

    void *stack_ptr = nullptr;
    if (cache.empty()) {
        stack_ptr = mmap(nullptr, stack_size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_STACK, 0, 0);
        if (stack_ptr == MAP_FAILED) {
            throw bad_stack_alloc();
        }
        if (mprotect(stack_ptr, page_size, PROT_NONE) == -1) {
            free_stack(stack_ptr, stack_size);
            throw bad_stack_alloc();
        }
    } else {
        stack_ptr = cache.back().release();
        cache.pop_back();
    }
    return static_cast<char *>(stack_ptr) + stack_size;
}

void deallocate(void *stack_end, size_t stack_size) noexcept {
    void *stack_ptr = static_cast<char *>(stack_end) - stack_size;
    auto &cache = *stack_cache;

    try {
        if (cache.size() < cache_maxsize.load(std::memory_order_relaxed)) {
            cache.emplace_back(stack_ptr, stack_size);
        } else {
            free_stack(stack_ptr, stack_size);
        }
    } catch (std::bad_alloc &e) {
        free_stack(stack_ptr, stack_size);
    }
}

} // stack_allocator

} // ten

<|endoftext|>


<commit_before>// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
// Copyright (c) 2008, Google Inc.
// 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 Google Inc. 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 AND CONTRIBUTORS
// "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.

// ---
// Author: Ken Ashcraft <opensource@google.com>

#include <config.h>
#include "static_vars.h"
#include <stddef.h>                     // for NULL
#include <new>                          // for operator new
#ifdef HAVE_PTHREAD
#include <pthread.h>                    // for pthread_atfork
#endif
#include "internal_logging.h"  // for CHECK_CONDITION
#include "common.h"
#include "sampler.h"           // for Sampler
#include "base/googleinit.h"

namespace tcmalloc {

#if defined(HAVE_FORK) && defined(HAVE_PTHREAD)
// These following two functions are registered via pthread_atfork to make
// sure the central_cache locks remain in a consisten state in the forked
// version of the thread.

static
void CentralCacheLockAll()
{
  Static::pageheap_lock()->Lock();
  for (int i = 0; i < kNumClasses; ++i)
    Static::central_cache()[i].Lock();
}

static
void CentralCacheUnlockAll()
{
  for (int i = 0; i < kNumClasses; ++i)
    Static::central_cache()[i].Unlock();
  Static::pageheap_lock()->Unlock();
}
#endif

SpinLock Static::pageheap_lock_(SpinLock::LINKER_INITIALIZED);
SizeMap Static::sizemap_;
CentralFreeListPadded Static::central_cache_[kNumClasses];
PageHeapAllocator<Span> Static::span_allocator_;
PageHeapAllocator<StackTrace> Static::stacktrace_allocator_;
Span Static::sampled_objects_;
PageHeapAllocator<StackTraceTable::Bucket> Static::bucket_allocator_;
StackTrace* Static::growth_stacks_ = NULL;
PageHeap* Static::pageheap_ = NULL;

void Static::InitStaticVars() {
  sizemap_.Init();
  span_allocator_.Init();
  span_allocator_.New(); // Reduce cache conflicts
  span_allocator_.New(); // Reduce cache conflicts
  stacktrace_allocator_.Init();
  bucket_allocator_.Init();
  // Do a bit of sanitizing: make sure central_cache is aligned properly
  CHECK_CONDITION((sizeof(central_cache_[0]) % 64) == 0);
  for (int i = 0; i < kNumClasses; ++i) {
    central_cache_[i].Init(i);
  }

  // It's important to have PageHeap allocated, not in static storage,
  // so that HeapLeakChecker does not consider all the byte patterns stored
  // in is caches as pointers that are sources of heap object liveness,
  // which leads to it missing some memory leaks.
  pageheap_ = new (MetaDataAlloc(sizeof(PageHeap))) PageHeap;
  DLL_Init(&sampled_objects_);
  Sampler::InitStatics();
}

#if defined(HAVE_FORK) && defined(HAVE_PTHREAD)

static inline
void SetupAtForkLocksHandler()
{
  pthread_atfork(CentralCacheLockAll,    // parent calls before fork
                 CentralCacheUnlockAll,  // parent calls after fork
                 CentralCacheUnlockAll); // child calls after fork
}
REGISTER_MODULE_INITIALIZER(tcmalloc_fork_handler, SetupAtForkLocksHandler());

#endif

static
void SetupAggressiveDecommit()
{
  Static::pageheap()->SetAggressiveDecommit(EnvToBool("TCMALLOC_AGGRESSIVE_DECOMMIT", false));
}
REGISTER_MODULE_INITIALIZER(tcmalloc_setup_aggressive_decommit, SetupAggressiveDecommit());

}  // namespace tcmalloc
<commit_msg>issue-626: Fix SetupAggressiveDecommit initialization<commit_after>// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
// Copyright (c) 2008, Google Inc.
// 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 Google Inc. 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 AND CONTRIBUTORS
// "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.

// ---
// Author: Ken Ashcraft <opensource@google.com>

#include <config.h>
#include "static_vars.h"
#include <stddef.h>                     // for NULL
#include <new>                          // for operator new
#ifdef HAVE_PTHREAD
#include <pthread.h>                    // for pthread_atfork
#endif
#include "internal_logging.h"  // for CHECK_CONDITION
#include "common.h"
#include "sampler.h"           // for Sampler
#include "base/googleinit.h"

namespace tcmalloc {

#if defined(HAVE_FORK) && defined(HAVE_PTHREAD)
// These following two functions are registered via pthread_atfork to make
// sure the central_cache locks remain in a consisten state in the forked
// version of the thread.

static
void CentralCacheLockAll()
{
  Static::pageheap_lock()->Lock();
  for (int i = 0; i < kNumClasses; ++i)
    Static::central_cache()[i].Lock();
}

static
void CentralCacheUnlockAll()
{
  for (int i = 0; i < kNumClasses; ++i)
    Static::central_cache()[i].Unlock();
  Static::pageheap_lock()->Unlock();
}
#endif

SpinLock Static::pageheap_lock_(SpinLock::LINKER_INITIALIZED);
SizeMap Static::sizemap_;
CentralFreeListPadded Static::central_cache_[kNumClasses];
PageHeapAllocator<Span> Static::span_allocator_;
PageHeapAllocator<StackTrace> Static::stacktrace_allocator_;
Span Static::sampled_objects_;
PageHeapAllocator<StackTraceTable::Bucket> Static::bucket_allocator_;
StackTrace* Static::growth_stacks_ = NULL;
PageHeap* Static::pageheap_ = NULL;

void Static::InitStaticVars() {
  sizemap_.Init();
  span_allocator_.Init();
  span_allocator_.New(); // Reduce cache conflicts
  span_allocator_.New(); // Reduce cache conflicts
  stacktrace_allocator_.Init();
  bucket_allocator_.Init();
  // Do a bit of sanitizing: make sure central_cache is aligned properly
  CHECK_CONDITION((sizeof(central_cache_[0]) % 64) == 0);
  for (int i = 0; i < kNumClasses; ++i) {
    central_cache_[i].Init(i);
  }

  // It's important to have PageHeap allocated, not in static storage,
  // so that HeapLeakChecker does not consider all the byte patterns stored
  // in is caches as pointers that are sources of heap object liveness,
  // which leads to it missing some memory leaks.
  pageheap_ = new (MetaDataAlloc(sizeof(PageHeap))) PageHeap;
  pageheap_->SetAggressiveDecommit(EnvToBool("TCMALLOC_AGGRESSIVE_DECOMMIT", false));
  DLL_Init(&sampled_objects_);
  Sampler::InitStatics();
}

#if defined(HAVE_FORK) && defined(HAVE_PTHREAD)

static inline
void SetupAtForkLocksHandler()
{
  pthread_atfork(CentralCacheLockAll,    // parent calls before fork
                 CentralCacheUnlockAll,  // parent calls after fork
                 CentralCacheUnlockAll); // child calls after fork
}
REGISTER_MODULE_INITIALIZER(tcmalloc_fork_handler, SetupAtForkLocksHandler());

#endif

}  // namespace tcmalloc
<|endoftext|>


<commit_before>#include "Tracing.h"
#include "IRMutator.h"
#include "IROperator.h"
#include "runtime/HalideRuntime.h"

namespace Halide {
namespace Internal {

using std::vector;
using std::map;
using std::string;

struct TraceEventBuilder {
    string func;
    vector<Expr> value;
    vector<Expr> coordinates;
    Type type;
    enum halide_trace_event_code_t event;
    Expr parent_id, value_index, dimensions;

    Expr build() {
        Expr values = Call::make(type_of<void *>(), Call::make_struct,
                                 value, Call::Intrinsic);
        Expr coords = Call::make(type_of<int32_t *>(), Call::make_struct,
                                 coordinates, Call::Intrinsic);
        Expr idx = value_index;
        if (!idx.defined()) {
            idx = 0;
        }

        vector<Expr> args = {Expr(func),
                             values, coords,
                             (int)type.code(), (int)type.bits(), (int)type.lanes(),
                             (int)event,
                             parent_id, idx, (int)coordinates.size()};
        return Call::make(Int(32), Call::trace, args, Call::Extern);
    }
};

class InjectTracing : public IRMutator {
public:
    const map<string, Function> &env;
    bool trace_all_loads, trace_all_stores, trace_all_realizations;

    InjectTracing(const map<string, Function> &e, const Target &t)
        : env(e) {
        trace_all_loads = t.has_feature(Target::TraceLoads);
        trace_all_stores = t.has_feature(Target::TraceStores);
        trace_all_realizations = t.has_feature(Target::TraceRealizations);
    }

private:
    using IRMutator::visit;

    void visit(const Call *op) {

        // Calls inside of an address_of don't count, but we want to
        // visit the args of the inner call.
        if (op->is_intrinsic(Call::address_of)) {
            internal_assert(op->args.size() == 1);
            const Call *c = op->args[0].as<Call>();
            const Load *l = op->args[0].as<Load>();

            internal_assert(c || l);

            std::vector<Expr> args;
            if (c) {
                args = c->args;
            } else {
                args.push_back(l->index);
            }

            bool unchanged = true;
            vector<Expr> new_args(args.size());
            for (size_t i = 0; i < args.size(); i++) {
                new_args[i] = mutate(args[i]);
                unchanged = unchanged && (new_args[i].same_as(args[i]));
            }

            if (unchanged) {
                expr = op;
                return;
            } else {
                Expr inner;
                if (c) {
                    inner = Call::make(c->type, c->name, new_args, c->call_type,
                                       c->func, c->value_index, c->image, c->param);
                } else {
                    Expr inner = Load::make(l->type, l->name, new_args[0], l->image, l->param, l->predicate);
                }
                expr = Call::make(op->type, Call::address_of, {inner}, Call::Intrinsic);
                return;
            }
        }

        IRMutator::visit(op);
        op = expr.as<Call>();
        internal_assert(op);

        bool trace_it = false;
        Expr trace_parent;
        if (op->call_type == Call::Halide) {
            Function f = env.find(op->name)->second;
            internal_assert(!f.can_be_inlined() || !f.schedule().compute_level().is_inline());

            trace_it = f.is_tracing_loads() || trace_all_loads;
            trace_parent = Variable::make(Int(32), op->name + ".trace_id");
        } else if (op->call_type == Call::Image) {
            trace_it = trace_all_loads;
            trace_parent = Variable::make(Int(32), "pipeline.trace_id");
        }

        if (trace_it) {
            string value_var_name = unique_name('t');
            Expr value_var = Variable::make(op->type, value_var_name);

            TraceEventBuilder builder;
            builder.func = op->name;
            builder.value = {value_var};
            builder.coordinates = op->args;
            builder.type = op->type;
            builder.event = halide_trace_load;
            builder.parent_id = trace_parent;
            builder.value_index = op->value_index;
            Expr trace = builder.build();

            expr = Let::make(value_var_name, op,
                             Call::make(op->type, Call::return_second,
                                        {trace, value_var}, Call::PureIntrinsic));
        }

    }

    void visit(const Provide *op) {
        IRMutator::visit(op);
        op = stmt.as<Provide>();
        internal_assert(op);

        map<string, Function>::const_iterator iter = env.find(op->name);
        if (iter == env.end()) return;
        Function f = iter->second;
        internal_assert(!f.can_be_inlined() || !f.schedule().compute_level().is_inline());

        if (f.is_tracing_stores() || trace_all_stores) {
            // Wrap each expr in a tracing call

            const vector<Expr> &values = op->values;
            vector<Expr> traces(op->values.size());

            TraceEventBuilder builder;
            builder.func = f.name();
            builder.coordinates = op->args;
            builder.event = halide_trace_store;
            builder.parent_id = Variable::make(Int(32), op->name + ".trace_id");
            for (size_t i = 0; i < values.size(); i++) {
                Type t = values[i].type();
                string value_var_name = unique_name('t');
                Expr value_var = Variable::make(t, value_var_name);

                builder.type = t;
                builder.value_index = (int)i;
                builder.value = {value_var};
                Expr trace = builder.build();

                traces[i] = Let::make(value_var_name, values[i],
                                      Call::make(t, Call::return_second,
                                                 {trace, value_var}, Call::PureIntrinsic));
            }

            stmt = Provide::make(op->name, traces, op->args);
        }
    }

    void visit(const Realize *op) {
        IRMutator::visit(op);
        op = stmt.as<Realize>();
        internal_assert(op);

        map<string, Function>::const_iterator iter = env.find(op->name);
        if (iter == env.end()) return;
        Function f = iter->second;
        if (f.is_tracing_realizations() || trace_all_realizations) {
            // Throw a tracing call before and after the realize body
            TraceEventBuilder builder;
            builder.func = op->name;
            builder.parent_id = Variable::make(Int(32), "pipeline.trace_id");
            builder.event = halide_trace_begin_realization;

            for (size_t i = 0; i < op->bounds.size(); i++) {
                builder.coordinates.push_back(op->bounds[i].min);
                builder.coordinates.push_back(op->bounds[i].extent);
            }

            // Begin realization returns a unique token to pass to further trace calls affecting this buffer.
            Expr call_before = builder.build();
            builder.event = halide_trace_end_realization;
            builder.parent_id = Variable::make(Int(32), op->name + ".trace_id");
            Expr call_after = builder.build();
            Stmt new_body = op->body;
            new_body = Block::make(new_body, Evaluate::make(call_after));
            new_body = LetStmt::make(op->name + ".trace_id", call_before, new_body);
            stmt = Realize::make(op->name, op->types, op->bounds, op->condition, new_body);
        } else if (f.is_tracing_stores() || f.is_tracing_loads()) {
            // We need a trace id defined to pass to the loads and stores
            Stmt new_body = op->body;
            new_body = LetStmt::make(op->name + ".trace_id", 0, new_body);
            stmt = Realize::make(op->name, op->types, op->bounds, op->condition, new_body);
        }

    }

    void visit(const ProducerConsumer *op) {
        IRMutator::visit(op);
        op = stmt.as<ProducerConsumer>();
        internal_assert(op);
        map<string, Function>::const_iterator iter = env.find(op->name);
        if (iter == env.end()) return;
        Function f = iter->second;
        if (f.is_tracing_realizations() || trace_all_realizations) {
            // Throw a tracing call around each pipeline event
            TraceEventBuilder builder;
            builder.func = op->name;
            builder.parent_id = Variable::make(Int(32), op->name + ".trace_id");

            // Use the size of the pure step
            const vector<string> f_args = f.args();
            for (int i = 0; i < f.dimensions(); i++) {
                Expr min = Variable::make(Int(32), f.name() + ".s0." + f_args[i] + ".min");
                Expr max = Variable::make(Int(32), f.name() + ".s0." + f_args[i] + ".max");
                Expr extent = (max + 1) - min;
                builder.coordinates.push_back(min);
                builder.coordinates.push_back(extent);
            }

            builder.event = (op->is_producer ?
                             halide_trace_produce :
                             halide_trace_consume);
            Expr begin_op_call = builder.build();

            builder.event = (op->is_producer ?
                             halide_trace_end_produce :
                             halide_trace_end_consume);
            Expr end_op_call = builder.build();

            Stmt new_body = Block::make(op->body, Evaluate::make(end_op_call));

            stmt = LetStmt::make(f.name() + ".trace_id", begin_op_call,
                                 ProducerConsumer::make(op->name, op->is_producer, new_body));
        }
    }
};

class RemoveRealizeOverOutput : public IRMutator {
    using IRMutator::visit;
    const vector<Function> &outputs;

    void visit(const Realize *op) {
        for (Function f : outputs) {
            if (op->name == f.name()) {
                stmt = mutate(op->body);
                return;
            }
        }
        IRMutator::visit(op);
    }

public:
    RemoveRealizeOverOutput(const vector<Function> &o) : outputs(o) {}
};

Stmt inject_tracing(Stmt s, const string &pipeline_name,
                    const map<string, Function> &env, const vector<Function> &outputs,
                    const Target &t) {
    Stmt original = s;
    InjectTracing tracing(env, t);

    // Add a dummy realize block for the output buffers
    for (Function output : outputs) {
        Region output_region;
        Parameter output_buf = output.output_buffers()[0];
        internal_assert(output_buf.is_buffer());
        for (int i = 0; i < output.dimensions(); i++) {
            string d = std::to_string(i);
            Expr min = Variable::make(Int(32), output_buf.name() + ".min." + d);
            Expr extent = Variable::make(Int(32), output_buf.name() + ".extent." + d);
            output_region.push_back(Range(min, extent));
        }
        s = Realize::make(output.name(), output.output_types(), output_region, const_true(), s);
    }

    // Inject tracing calls
    s = tracing.mutate(s);

    // Strip off the dummy realize blocks
    s = RemoveRealizeOverOutput(outputs).mutate(s);

    if (!s.same_as(original)) {
        // Add pipeline start and end events
        TraceEventBuilder builder;
        builder.func = pipeline_name;
        builder.event = halide_trace_begin_pipeline;
        builder.parent_id = 0;

        Expr pipeline_start = builder.build();

        builder.event = halide_trace_end_pipeline;
        builder.parent_id = Variable::make(Int(32), "pipeline.trace_id");
        Expr pipeline_end = builder.build();

        s = Block::make(s, Evaluate::make(pipeline_end));
        s = LetStmt::make("pipeline.trace_id", pipeline_start, s);
    }

    return s;
}

}
}
<commit_msg>Make the env var work as well, but mark it deprecated<commit_after>#include "Tracing.h"
#include "IRMutator.h"
#include "IROperator.h"
#include "runtime/HalideRuntime.h"

namespace Halide {
namespace Internal {

using std::vector;
using std::map;
using std::string;

struct TraceEventBuilder {
    string func;
    vector<Expr> value;
    vector<Expr> coordinates;
    Type type;
    enum halide_trace_event_code_t event;
    Expr parent_id, value_index, dimensions;

    Expr build() {
        Expr values = Call::make(type_of<void *>(), Call::make_struct,
                                 value, Call::Intrinsic);
        Expr coords = Call::make(type_of<int32_t *>(), Call::make_struct,
                                 coordinates, Call::Intrinsic);
        Expr idx = value_index;
        if (!idx.defined()) {
            idx = 0;
        }

        vector<Expr> args = {Expr(func),
                             values, coords,
                             (int)type.code(), (int)type.bits(), (int)type.lanes(),
                             (int)event,
                             parent_id, idx, (int)coordinates.size()};
        return Call::make(Int(32), Call::trace, args, Call::Extern);
    }
};

class InjectTracing : public IRMutator {
public:
    const map<string, Function> &env;
    bool trace_all_loads, trace_all_stores, trace_all_realizations;

    InjectTracing(const map<string, Function> &e, const Target &t)
        : env(e) {
        trace_all_loads = t.has_feature(Target::TraceLoads);
        trace_all_stores = t.has_feature(Target::TraceStores);
        trace_all_realizations = t.has_feature(Target::TraceRealizations);

        // Check for the deprecated tracing level environment var.
        string global_level = get_env_variable("HL_TRACE");
        if (!global_level.empty()) {
            user_warning << "Using HL_TRACE to set a global tracing level "
                         << "is deprecated. Use the target flags trace_loads, "
                         << "trace_stores, and trace_realizations instead\n";
            int l = std::stoi(global_level);
            trace_all_loads |= l > 2;
            trace_all_stores |= l > 1;
            trace_all_realizations |= l > 0;
        }
    }

private:
    using IRMutator::visit;

    void visit(const Call *op) {

        // Calls inside of an address_of don't count, but we want to
        // visit the args of the inner call.
        if (op->is_intrinsic(Call::address_of)) {
            internal_assert(op->args.size() == 1);
            const Call *c = op->args[0].as<Call>();
            const Load *l = op->args[0].as<Load>();

            internal_assert(c || l);

            std::vector<Expr> args;
            if (c) {
                args = c->args;
            } else {
                args.push_back(l->index);
            }

            bool unchanged = true;
            vector<Expr> new_args(args.size());
            for (size_t i = 0; i < args.size(); i++) {
                new_args[i] = mutate(args[i]);
                unchanged = unchanged && (new_args[i].same_as(args[i]));
            }

            if (unchanged) {
                expr = op;
                return;
            } else {
                Expr inner;
                if (c) {
                    inner = Call::make(c->type, c->name, new_args, c->call_type,
                                       c->func, c->value_index, c->image, c->param);
                } else {
                    Expr inner = Load::make(l->type, l->name, new_args[0], l->image, l->param, l->predicate);
                }
                expr = Call::make(op->type, Call::address_of, {inner}, Call::Intrinsic);
                return;
            }
        }

        IRMutator::visit(op);
        op = expr.as<Call>();
        internal_assert(op);

        bool trace_it = false;
        Expr trace_parent;
        if (op->call_type == Call::Halide) {
            Function f = env.find(op->name)->second;
            internal_assert(!f.can_be_inlined() || !f.schedule().compute_level().is_inline());

            trace_it = f.is_tracing_loads() || trace_all_loads;
            trace_parent = Variable::make(Int(32), op->name + ".trace_id");
        } else if (op->call_type == Call::Image) {
            trace_it = trace_all_loads;
            trace_parent = Variable::make(Int(32), "pipeline.trace_id");
        }

        if (trace_it) {
            string value_var_name = unique_name('t');
            Expr value_var = Variable::make(op->type, value_var_name);

            TraceEventBuilder builder;
            builder.func = op->name;
            builder.value = {value_var};
            builder.coordinates = op->args;
            builder.type = op->type;
            builder.event = halide_trace_load;
            builder.parent_id = trace_parent;
            builder.value_index = op->value_index;
            Expr trace = builder.build();

            expr = Let::make(value_var_name, op,
                             Call::make(op->type, Call::return_second,
                                        {trace, value_var}, Call::PureIntrinsic));
        }

    }

    void visit(const Provide *op) {
        IRMutator::visit(op);
        op = stmt.as<Provide>();
        internal_assert(op);

        map<string, Function>::const_iterator iter = env.find(op->name);
        if (iter == env.end()) return;
        Function f = iter->second;
        internal_assert(!f.can_be_inlined() || !f.schedule().compute_level().is_inline());

        if (f.is_tracing_stores() || trace_all_stores) {
            // Wrap each expr in a tracing call

            const vector<Expr> &values = op->values;
            vector<Expr> traces(op->values.size());

            TraceEventBuilder builder;
            builder.func = f.name();
            builder.coordinates = op->args;
            builder.event = halide_trace_store;
            builder.parent_id = Variable::make(Int(32), op->name + ".trace_id");
            for (size_t i = 0; i < values.size(); i++) {
                Type t = values[i].type();
                string value_var_name = unique_name('t');
                Expr value_var = Variable::make(t, value_var_name);

                builder.type = t;
                builder.value_index = (int)i;
                builder.value = {value_var};
                Expr trace = builder.build();

                traces[i] = Let::make(value_var_name, values[i],
                                      Call::make(t, Call::return_second,
                                                 {trace, value_var}, Call::PureIntrinsic));
            }

            stmt = Provide::make(op->name, traces, op->args);
        }
    }

    void visit(const Realize *op) {
        IRMutator::visit(op);
        op = stmt.as<Realize>();
        internal_assert(op);

        map<string, Function>::const_iterator iter = env.find(op->name);
        if (iter == env.end()) return;
        Function f = iter->second;
        if (f.is_tracing_realizations() || trace_all_realizations) {
            // Throw a tracing call before and after the realize body
            TraceEventBuilder builder;
            builder.func = op->name;
            builder.parent_id = Variable::make(Int(32), "pipeline.trace_id");
            builder.event = halide_trace_begin_realization;

            for (size_t i = 0; i < op->bounds.size(); i++) {
                builder.coordinates.push_back(op->bounds[i].min);
                builder.coordinates.push_back(op->bounds[i].extent);
            }

            // Begin realization returns a unique token to pass to further trace calls affecting this buffer.
            Expr call_before = builder.build();
            builder.event = halide_trace_end_realization;
            builder.parent_id = Variable::make(Int(32), op->name + ".trace_id");
            Expr call_after = builder.build();
            Stmt new_body = op->body;
            new_body = Block::make(new_body, Evaluate::make(call_after));
            new_body = LetStmt::make(op->name + ".trace_id", call_before, new_body);
            stmt = Realize::make(op->name, op->types, op->bounds, op->condition, new_body);
        } else if (f.is_tracing_stores() || f.is_tracing_loads()) {
            // We need a trace id defined to pass to the loads and stores
            Stmt new_body = op->body;
            new_body = LetStmt::make(op->name + ".trace_id", 0, new_body);
            stmt = Realize::make(op->name, op->types, op->bounds, op->condition, new_body);
        }

    }

    void visit(const ProducerConsumer *op) {
        IRMutator::visit(op);
        op = stmt.as<ProducerConsumer>();
        internal_assert(op);
        map<string, Function>::const_iterator iter = env.find(op->name);
        if (iter == env.end()) return;
        Function f = iter->second;
        if (f.is_tracing_realizations() || trace_all_realizations) {
            // Throw a tracing call around each pipeline event
            TraceEventBuilder builder;
            builder.func = op->name;
            builder.parent_id = Variable::make(Int(32), op->name + ".trace_id");

            // Use the size of the pure step
            const vector<string> f_args = f.args();
            for (int i = 0; i < f.dimensions(); i++) {
                Expr min = Variable::make(Int(32), f.name() + ".s0." + f_args[i] + ".min");
                Expr max = Variable::make(Int(32), f.name() + ".s0." + f_args[i] + ".max");
                Expr extent = (max + 1) - min;
                builder.coordinates.push_back(min);
                builder.coordinates.push_back(extent);
            }

            builder.event = (op->is_producer ?
                             halide_trace_produce :
                             halide_trace_consume);
            Expr begin_op_call = builder.build();

            builder.event = (op->is_producer ?
                             halide_trace_end_produce :
                             halide_trace_end_consume);
            Expr end_op_call = builder.build();

            Stmt new_body = Block::make(op->body, Evaluate::make(end_op_call));

            stmt = LetStmt::make(f.name() + ".trace_id", begin_op_call,
                                 ProducerConsumer::make(op->name, op->is_producer, new_body));
        }
    }
};

class RemoveRealizeOverOutput : public IRMutator {
    using IRMutator::visit;
    const vector<Function> &outputs;

    void visit(const Realize *op) {
        for (Function f : outputs) {
            if (op->name == f.name()) {
                stmt = mutate(op->body);
                return;
            }
        }
        IRMutator::visit(op);
    }

public:
    RemoveRealizeOverOutput(const vector<Function> &o) : outputs(o) {}
};

Stmt inject_tracing(Stmt s, const string &pipeline_name,
                    const map<string, Function> &env, const vector<Function> &outputs,
                    const Target &t) {
    Stmt original = s;
    InjectTracing tracing(env, t);

    // Add a dummy realize block for the output buffers
    for (Function output : outputs) {
        Region output_region;
        Parameter output_buf = output.output_buffers()[0];
        internal_assert(output_buf.is_buffer());
        for (int i = 0; i < output.dimensions(); i++) {
            string d = std::to_string(i);
            Expr min = Variable::make(Int(32), output_buf.name() + ".min." + d);
            Expr extent = Variable::make(Int(32), output_buf.name() + ".extent." + d);
            output_region.push_back(Range(min, extent));
        }
        s = Realize::make(output.name(), output.output_types(), output_region, const_true(), s);
    }

    // Inject tracing calls
    s = tracing.mutate(s);

    // Strip off the dummy realize blocks
    s = RemoveRealizeOverOutput(outputs).mutate(s);

    if (!s.same_as(original)) {
        // Add pipeline start and end events
        TraceEventBuilder builder;
        builder.func = pipeline_name;
        builder.event = halide_trace_begin_pipeline;
        builder.parent_id = 0;

        Expr pipeline_start = builder.build();

        builder.event = halide_trace_end_pipeline;
        builder.parent_id = Variable::make(Int(32), "pipeline.trace_id");
        Expr pipeline_end = builder.build();

        s = Block::make(s, Evaluate::make(pipeline_end));
        s = LetStmt::make("pipeline.trace_id", pipeline_start, s);
    }

    return s;
}

}
}
<|endoftext|>


<commit_before>/*
 * MSPT.cpp
 *
 *  Created on: 28 Oct 2015
 *      Author: hieu
 */

#include <cassert>
#include <boost/foreach.hpp>
#include "MSPT.h"
#include "../../PhraseBased/PhraseImpl.h"
#include "../../Phrase.h"
#include "../../System.h"
#include "../../Scores.h"
#include "../../InputPathsBase.h"
#include "../../legacy/InputFileStream.h"
#include "util/exception.hh"

#include "../../PhraseBased/InputPath.h"
#include "../../PhraseBased/TargetPhraseImpl.h"
#include "../../PhraseBased/TargetPhrases.h"

#include "../../SCFG/PhraseImpl.h"
#include "../../SCFG/TargetPhraseImpl.h"
#include "../../SCFG/InputPath.h"
#include "../../SCFG/Stack.h"
#include "../../SCFG/Stacks.h"
#include "../../SCFG/Manager.h"

using namespace std;

namespace Moses2
{

////////////////////////////////////////////////////////////////////////

MSPT::MSPT(size_t startInd, const std::string &line)
  :PhraseTable(startInd, line)
  ,m_rootPb(NULL)
  ,m_rootSCFG(NULL)
{
  ReadParameters();
}

MSPT::~MSPT()
{
  delete m_rootPb;
  delete m_rootSCFG;
}

void MSPT::InitializeForInput(const InputType &input)
{
  cerr << "InitializeForInput" << endl;
}

TargetPhrases* MSPT::Lookup(const Manager &mgr, MemPool &pool,
    InputPath &inputPath) const
{
  const SubPhrase<Moses2::Word> &phrase = inputPath.subPhrase;
  TargetPhrases *tps = m_rootPb->Find(m_input, phrase);
  return tps;
}

void MSPT::InitActiveChart(
  MemPool &pool,
  const SCFG::Manager &mgr,
  SCFG::InputPath &path) const
{
  size_t ptInd = GetPtInd();
  ActiveChartEntryMem *chartEntry = new (pool.Allocate<ActiveChartEntryMem>()) ActiveChartEntryMem(pool, *m_rootSCFG);
  path.AddActiveChartEntry(ptInd, chartEntry);
  //cerr << "InitActiveChart=" << path << endl;
}

void MSPT::Lookup(MemPool &pool,
                               const SCFG::Manager &mgr,
                               size_t maxChartSpan,
                               const SCFG::Stacks &stacks,
                               SCFG::InputPath &path) const
{
  if (path.range.GetNumWordsCovered() > maxChartSpan) {
    return;
  }

  size_t endPos = path.range.GetEndPos();

  const SCFG::InputPath *prevPath = static_cast<const SCFG::InputPath*>(path.prefixPath);
  UTIL_THROW_IF2(prevPath == NULL, "prefixPath == NULL");

  // TERMINAL
  const SCFG::Word &lastWord = path.subPhrase.Back();

  const SCFG::InputPath &subPhrasePath = *mgr.GetInputPaths().GetMatrix().GetValue(endPos, 1);

  //cerr << "BEFORE LookupGivenWord=" << *prevPath << endl;
  LookupGivenWord(pool, mgr, *prevPath, lastWord, NULL, subPhrasePath.range, path);
  //cerr << "AFTER LookupGivenWord=" << *prevPath << endl;

  // NON-TERMINAL
  //const SCFG::InputPath *prefixPath = static_cast<const SCFG::InputPath*>(path.prefixPath);
  while (prevPath) {
    const Range &prevRange = prevPath->range;
    //cerr << "prevRange=" << prevRange << endl;

    size_t startPos = prevRange.GetEndPos() + 1;
    size_t ntSize = endPos - startPos + 1;
    const SCFG::InputPath &subPhrasePath = *mgr.GetInputPaths().GetMatrix().GetValue(startPos, ntSize);

    LookupNT(pool, mgr, subPhrasePath.range, *prevPath, stacks, path);

    prevPath = static_cast<const SCFG::InputPath*>(prevPath->prefixPath);
  }
}

void MSPT::LookupGivenNode(
  MemPool &pool,
  const SCFG::Manager &mgr,
  const SCFG::ActiveChartEntry &prevEntry,
  const SCFG::Word &wordSought,
  const Moses2::Hypotheses *hypos,
  const Moses2::Range &subPhraseRange,
  SCFG::InputPath &outPath) const
{
  const ActiveChartEntryMem &prevEntryCast = static_cast<const ActiveChartEntryMem&>(prevEntry);

  const SCFGNODE &prevNode = prevEntryCast.node;
  UTIL_THROW_IF2(&prevNode == NULL, "node == NULL");

  size_t ptInd = GetPtInd();
  const SCFGNODE *nextNode = prevNode.Find(m_input, wordSought);

  /*
  if (outPath.range.GetStartPos() == 1 || outPath.range.GetStartPos() == 2) {
    cerr  << "range=" << outPath.range
          << " prevEntry=" << prevEntry.GetSymbolBind().Debug(mgr.system)
          << " wordSought=" << wordSought.Debug(mgr.system)
          << " nextNode=" << nextNode
          << endl;
  }
  */
  if (nextNode) {
    // new entries
    ActiveChartEntryMem *chartEntry = new (pool.Allocate<ActiveChartEntryMem>()) ActiveChartEntryMem(pool, *nextNode, prevEntry);

    chartEntry->AddSymbolBindElement(subPhraseRange, wordSought, hypos, *this);
    //cerr << "AFTER Add=" << symbolBind << endl;

    outPath.AddActiveChartEntry(ptInd, chartEntry);

    const SCFG::TargetPhrases *tps = nextNode->GetTargetPhrases();
    if (tps) {
      // there are some rules
      /*
      cerr << "outPath=" << outPath.range
      	  << " bind=" << chartEntry->GetSymbolBind().Debug(mgr.system)
      	  << " pt=" << GetPtInd()
        << " tps=" << tps->Debug(mgr.system) << endl;
      */
      outPath.AddTargetPhrasesToPath(pool, mgr.system, *this, *tps, chartEntry->GetSymbolBind());

    }

    //cerr << "AFTER outPath=" << outPath << endl;
  }
}

}

<commit_msg>InitializeForInput()<commit_after>/*
 * MSPT.cpp
 *
 *  Created on: 28 Oct 2015
 *      Author: hieu
 */

#include <cassert>
#include <boost/foreach.hpp>
#include "MSPT.h"
#include "../../PhraseBased/PhraseImpl.h"
#include "../../Phrase.h"
#include "../../System.h"
#include "../../Scores.h"
#include "../../InputPathsBase.h"
#include "../../legacy/InputFileStream.h"
#include "util/exception.hh"

#include "../../PhraseBased/InputPath.h"
#include "../../PhraseBased/TargetPhraseImpl.h"
#include "../../PhraseBased/TargetPhrases.h"

#include "../../SCFG/PhraseImpl.h"
#include "../../SCFG/TargetPhraseImpl.h"
#include "../../SCFG/InputPath.h"
#include "../../SCFG/Stack.h"
#include "../../SCFG/Stacks.h"
#include "../../SCFG/Manager.h"

using namespace std;

namespace Moses2
{

////////////////////////////////////////////////////////////////////////

MSPT::MSPT(size_t startInd, const std::string &line)
  :PhraseTable(startInd, line)
  ,m_rootPb(NULL)
  ,m_rootSCFG(NULL)
{
  ReadParameters();
}

MSPT::~MSPT()
{
  delete m_rootPb;
  delete m_rootSCFG;
}

void MSPT::InitializeForInput(const InputType &input)
{
  cerr << "InitializeForInput MSPT" << endl;
}

TargetPhrases* MSPT::Lookup(const Manager &mgr, MemPool &pool,
    InputPath &inputPath) const
{
  const SubPhrase<Moses2::Word> &phrase = inputPath.subPhrase;
  TargetPhrases *tps = m_rootPb->Find(m_input, phrase);
  return tps;
}

void MSPT::InitActiveChart(
  MemPool &pool,
  const SCFG::Manager &mgr,
  SCFG::InputPath &path) const
{
  size_t ptInd = GetPtInd();
  ActiveChartEntryMem *chartEntry = new (pool.Allocate<ActiveChartEntryMem>()) ActiveChartEntryMem(pool, *m_rootSCFG);
  path.AddActiveChartEntry(ptInd, chartEntry);
  //cerr << "InitActiveChart=" << path << endl;
}

void MSPT::Lookup(MemPool &pool,
                               const SCFG::Manager &mgr,
                               size_t maxChartSpan,
                               const SCFG::Stacks &stacks,
                               SCFG::InputPath &path) const
{
  if (path.range.GetNumWordsCovered() > maxChartSpan) {
    return;
  }

  size_t endPos = path.range.GetEndPos();

  const SCFG::InputPath *prevPath = static_cast<const SCFG::InputPath*>(path.prefixPath);
  UTIL_THROW_IF2(prevPath == NULL, "prefixPath == NULL");

  // TERMINAL
  const SCFG::Word &lastWord = path.subPhrase.Back();

  const SCFG::InputPath &subPhrasePath = *mgr.GetInputPaths().GetMatrix().GetValue(endPos, 1);

  //cerr << "BEFORE LookupGivenWord=" << *prevPath << endl;
  LookupGivenWord(pool, mgr, *prevPath, lastWord, NULL, subPhrasePath.range, path);
  //cerr << "AFTER LookupGivenWord=" << *prevPath << endl;

  // NON-TERMINAL
  //const SCFG::InputPath *prefixPath = static_cast<const SCFG::InputPath*>(path.prefixPath);
  while (prevPath) {
    const Range &prevRange = prevPath->range;
    //cerr << "prevRange=" << prevRange << endl;

    size_t startPos = prevRange.GetEndPos() + 1;
    size_t ntSize = endPos - startPos + 1;
    const SCFG::InputPath &subPhrasePath = *mgr.GetInputPaths().GetMatrix().GetValue(startPos, ntSize);

    LookupNT(pool, mgr, subPhrasePath.range, *prevPath, stacks, path);

    prevPath = static_cast<const SCFG::InputPath*>(prevPath->prefixPath);
  }
}

void MSPT::LookupGivenNode(
  MemPool &pool,
  const SCFG::Manager &mgr,
  const SCFG::ActiveChartEntry &prevEntry,
  const SCFG::Word &wordSought,
  const Moses2::Hypotheses *hypos,
  const Moses2::Range &subPhraseRange,
  SCFG::InputPath &outPath) const
{
  const ActiveChartEntryMem &prevEntryCast = static_cast<const ActiveChartEntryMem&>(prevEntry);

  const SCFGNODE &prevNode = prevEntryCast.node;
  UTIL_THROW_IF2(&prevNode == NULL, "node == NULL");

  size_t ptInd = GetPtInd();
  const SCFGNODE *nextNode = prevNode.Find(m_input, wordSought);

  /*
  if (outPath.range.GetStartPos() == 1 || outPath.range.GetStartPos() == 2) {
    cerr  << "range=" << outPath.range
          << " prevEntry=" << prevEntry.GetSymbolBind().Debug(mgr.system)
          << " wordSought=" << wordSought.Debug(mgr.system)
          << " nextNode=" << nextNode
          << endl;
  }
  */
  if (nextNode) {
    // new entries
    ActiveChartEntryMem *chartEntry = new (pool.Allocate<ActiveChartEntryMem>()) ActiveChartEntryMem(pool, *nextNode, prevEntry);

    chartEntry->AddSymbolBindElement(subPhraseRange, wordSought, hypos, *this);
    //cerr << "AFTER Add=" << symbolBind << endl;

    outPath.AddActiveChartEntry(ptInd, chartEntry);

    const SCFG::TargetPhrases *tps = nextNode->GetTargetPhrases();
    if (tps) {
      // there are some rules
      /*
      cerr << "outPath=" << outPath.range
      	  << " bind=" << chartEntry->GetSymbolBind().Debug(mgr.system)
      	  << " pt=" << GetPtInd()
        << " tps=" << tps->Debug(mgr.system) << endl;
      */
      outPath.AddTargetPhrasesToPath(pool, mgr.system, *this, *tps, chartEntry->GetSymbolBind());

    }

    //cerr << "AFTER outPath=" << outPath << endl;
  }
}

}

<|endoftext|>


<commit_before><commit_msg>Cyber: Retire unused tests.<commit_after><|endoftext|>