<commit_before>/// @file   moveAction.cpp
/// @brief  Implementation of the class for a move action.
/// @author Enrico Fraccaroli
/// @date   Jul 14 2016
/// @copyright
/// Copyright (c) 2016 Enrico Fraccaroli <enrico.fraccaroli@gmail.com>
/// Permission to use, copy, modify, and distribute this software for any
/// purpose with or without fee is hereby granted, provided that the above
/// copyright notice and this permission notice appear in all copies.
///
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
/// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
/// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
/// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
/// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
/// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
/// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include "moveAction.hpp"
#include "character.hpp"
#include "room.hpp"

using namespace std::chrono;

MoveAction::MoveAction(
    Character * _actor,
    Room * _destination,
    Direction _direction,
    unsigned int _cooldown) :
    GeneralAction(_actor, system_clock::now() + seconds(_cooldown)),
    destination(_destination),
    direction(_direction)
{
    Logger::log(LogLevel::Debug, "Created move action.");
}

MoveAction::~MoveAction()
{
    Logger::log(LogLevel::Debug, "Deleted move action.");
}

bool MoveAction::check(std::string & error) const
{
    if (!GeneralAction::check(error))
    {
        return false;
    }
    if (this->destination == nullptr)
    {
        Logger::log(LogLevel::Error, "No destination has been set.");
        error = "You cannot reach the destination.";
        return false;
    }
    if (this->direction == Direction::None)
    {
        Logger::log(LogLevel::Error, "No direction has been set.");
        error = "You have lost your direction.";
        return false;
    }
    return true;
}

ActionType MoveAction::getType() const
{
    return ActionType::Move;
}

std::string MoveAction::getDescription() const
{
    return "moving";
}

std::string MoveAction::stop()
{
    return "You stop moving.";
}

ActionStatus MoveAction::perform()
{
    // Check if the cooldown is ended.
    if (!this->checkElapsed())
    {
        return ActionStatus::Running;
    }
    std::string error;
    if (!this->check(error))
    {
        actor->sendMsg(error + "\n\n");
        return ActionStatus::Error;
    }
    if (!MoveAction::canMoveTo(actor, direction, error))
    {
        // Notify that the actor can't move because too tired.
        actor->sendMsg(error + "\n");
        return ActionStatus::Error;
    }
    // Get the amount of required stamina.
    auto consumedStamina = this->getConsumedStamina(actor, actor->posture);
    // Consume the stamina.
    actor->remStamina(consumedStamina, true);
    // Move character.
    actor->moveTo(
        destination,
        actor->getNameCapital() + " goes " + direction.toString() + ".\n",
        actor->getNameCapital() + " arrives from " + direction.getOpposite().toString() + ".\n");
    return ActionStatus::Finished;
}

unsigned int MoveAction::getConsumedStamina(const Character * character, const CharacterPosture & posture)
{
    auto multiplier = 1.0;
    if (posture == CharacterPosture::Crouch)
    {
        multiplier = 0.75;
    }
    else if (posture == CharacterPosture::Prone)
    {
        multiplier = 0.50;
    }
    // BASE     [+1.0]
    // STRENGTH [-0.0 to -2.80]
    // WEIGHT   [+1.6 to +2.51]
    // CARRIED  [+0.0 to +2.48]
    return static_cast<unsigned int>((1.0
                                      - character->getAbilityLog(Ability::Strength, 0.0, 1.0)
                                      + SafeLog10(character->weight)
                                      + SafeLog10(character->getCarryingWeight())) * multiplier);
}

bool MoveAction::canMoveTo(Character * character, const Direction & direction, std::string & error)
{
    if (character->getAction()->getType() == ActionType::Combat)
    {
        error = "You cannot move while fighting.";
        return false;
    }
    // Check if the character is in a no-walk position.
    if (character->posture == CharacterPosture::Rest || character->posture == CharacterPosture::Sit)
    {
        error = "You first need to stand up.";
        return false;
    }
    // Find the exit to the destination.
    auto destExit = character->room->findExit(direction);
    if (destExit == nullptr)
    {
        error = "You cannot go that way.";
        return false;
    }
    // Check if the actor has enough stamina to execute the action.
    if (MoveAction::getConsumedStamina(character, character->posture) > character->getStamina())
    {
        error = "You are too tired to move.\n";
        return false;
    }
    // If the direction is upstairs, check if there is a stair.
    if (direction == Direction::Up)
    {
        if (!HasFlag(destExit->flags, ExitFlag::Stairs))
        {
            error = "You can't go upstairs, there are no stairs.";
            return false;
        }
    }
    // Check if the destination is correct.
    if (destExit->destination == nullptr)
    {
        error = "That direction can't take you anywhere.";
        return false;
    }
    // Check if the destination is bocked by a door.
    auto door = destExit->destination->findDoor();
    if (door != nullptr)
    {
        if (HasFlag(door->flags, ItemFlag::Closed))
        {
            error = "Maybe you have to open that door first.";
            return false;
        }
    }
    // Check if the destination has a floor.
    std::shared_ptr<Exit> destDown = destExit->destination->findExit(Direction::Down);
    if (destDown != nullptr)
    {
        if (!HasFlag(destDown->flags, ExitFlag::Stairs))
        {
            error = "Do you really want to fall in that pit?";
            return false;
        }
    }
    // Check if the destination is forbidden for mobiles.
    if (character->isMobile() && HasFlag(destExit->flags, ExitFlag::NoMob))
    {
        return false;
    }
    return true;
}
<commit_msg>Add check if the character is in close combat to canMoveTo function<commit_after>/// @file   moveAction.cpp
/// @brief  Implementation of the class for a move action.
/// @author Enrico Fraccaroli
/// @date   Jul 14 2016
/// @copyright
/// Copyright (c) 2016 Enrico Fraccaroli <enrico.fraccaroli@gmail.com>
/// Permission to use, copy, modify, and distribute this software for any
/// purpose with or without fee is hereby granted, provided that the above
/// copyright notice and this permission notice appear in all copies.
///
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
/// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
/// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
/// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
/// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
/// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
/// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#include "moveAction.hpp"
#include "character.hpp"
#include "room.hpp"

using namespace std::chrono;

MoveAction::MoveAction(
    Character * _actor,
    Room * _destination,
    Direction _direction,
    unsigned int _cooldown) :
    GeneralAction(_actor, system_clock::now() + seconds(_cooldown)),
    destination(_destination),
    direction(_direction)
{
    Logger::log(LogLevel::Debug, "Created move action.");
}

MoveAction::~MoveAction()
{
    Logger::log(LogLevel::Debug, "Deleted move action.");
}

bool MoveAction::check(std::string & error) const
{
    if (!GeneralAction::check(error))
    {
        return false;
    }
    if (this->destination == nullptr)
    {
        Logger::log(LogLevel::Error, "No destination has been set.");
        error = "You cannot reach the destination.";
        return false;
    }
    if (this->direction == Direction::None)
    {
        Logger::log(LogLevel::Error, "No direction has been set.");
        error = "You have lost your direction.";
        return false;
    }
    return true;
}

ActionType MoveAction::getType() const
{
    return ActionType::Move;
}

std::string MoveAction::getDescription() const
{
    return "moving";
}

std::string MoveAction::stop()
{
    return "You stop moving.";
}

ActionStatus MoveAction::perform()
{
    // Check if the cooldown is ended.
    if (!this->checkElapsed())
    {
        return ActionStatus::Running;
    }
    std::string error;
    if (!this->check(error))
    {
        actor->sendMsg(error + "\n\n");
        return ActionStatus::Error;
    }
    if (!MoveAction::canMoveTo(actor, direction, error))
    {
        // Notify that the actor can't move because too tired.
        actor->sendMsg(error + "\n");
        return ActionStatus::Error;
    }
    // Get the amount of required stamina.
    auto consumedStamina = this->getConsumedStamina(actor, actor->posture);
    // Consume the stamina.
    actor->remStamina(consumedStamina, true);
    // Move character.
    actor->moveTo(
        destination,
        actor->getNameCapital() + " goes " + direction.toString() + ".\n",
        actor->getNameCapital() + " arrives from " + direction.getOpposite().toString() + ".\n");
    return ActionStatus::Finished;
}

unsigned int MoveAction::getConsumedStamina(const Character * character, const CharacterPosture & posture)
{
    auto multiplier = 1.0;
    if (posture == CharacterPosture::Crouch)
    {
        multiplier = 0.75;
    }
    else if (posture == CharacterPosture::Prone)
    {
        multiplier = 0.50;
    }
    // BASE     [+1.0]
    // STRENGTH [-0.0 to -2.80]
    // WEIGHT   [+1.6 to +2.51]
    // CARRIED  [+0.0 to +2.48]
    return static_cast<unsigned int>((1.0
                                      - character->getAbilityLog(Ability::Strength, 0.0, 1.0)
                                      + SafeLog10(character->weight)
                                      + SafeLog10(character->getCarryingWeight())) * multiplier);
}

bool MoveAction::canMoveTo(Character * character, const Direction & direction, std::string & error)
{
    if (character->getAction()->getType() == ActionType::Combat)
    {
        // Check if the character is locked into close combat.
        bool lockedInCombat = false;
        // Check if he is in the same room of one of its aggressors.
        for (auto iterator : character->aggressionList)
        {
            if (iterator->aggressor != nullptr)
            {
                if (iterator->aggressor->room == character->room)
                {
                    lockedInCombat = true;
                    break;
                }
            }
        }
        // Check even the aimed character.
        if (character->aimedCharacter)
        {
            if (character->aimedCharacter->room == character->room) lockedInCombat = true;
        }
        if (lockedInCombat)
        {
            error = "You cannot move while fighting in close combat.";
        }
        return !lockedInCombat;
    }
    // Check if the character is in a no-walk position.
    if (character->posture == CharacterPosture::Rest || character->posture == CharacterPosture::Sit)
    {
        error = "You first need to stand up.";
        return false;
    }
    // Find the exit to the destination.
    auto destExit = character->room->findExit(direction);
    if (destExit == nullptr)
    {
        error = "You cannot go that way.";
        return false;
    }
    // Check if the actor has enough stamina to execute the action.
    if (MoveAction::getConsumedStamina(character, character->posture) > character->getStamina())
    {
        error = "You are too tired to move.\n";
        return false;
    }
    // If the direction is upstairs, check if there is a stair.
    if (direction == Direction::Up)
    {
        if (!HasFlag(destExit->flags, ExitFlag::Stairs))
        {
            error = "You can't go upstairs, there are no stairs.";
            return false;
        }
    }
    // Check if the destination is correct.
    if (destExit->destination == nullptr)
    {
        error = "That direction can't take you anywhere.";
        return false;
    }
    // Check if the destination is bocked by a door.
    auto door = destExit->destination->findDoor();
    if (door != nullptr)
    {
        if (HasFlag(door->flags, ItemFlag::Closed))
        {
            error = "Maybe you have to open that door first.";
            return false;
        }
    }
    // Check if the destination has a floor.
    std::shared_ptr<Exit> destDown = destExit->destination->findExit(Direction::Down);
    if (destDown != nullptr)
    {
        if (!HasFlag(destDown->flags, ExitFlag::Stairs))
        {
            error = "Do you really want to fall in that pit?";
            return false;
        }
    }
    // Check if the destination is forbidden for mobiles.
    if (character->isMobile() && HasFlag(destExit->flags, ExitFlag::NoMob))
    {
        return false;
    }
    return true;
}
<|endoftext|>


<commit_before>/*
 * This file is part of the Camera Streaming Daemon
 *
 * Copyright (C) 2017  Intel Corporation. All rights reserved.
 *
 * 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.
 */
#include <fcntl.h>
#include <sstream>
#include <sys/ioctl.h>
#include <unistd.h>

#include "log.h"
#include "stream_v4l2.h"
#include <linux/videodev2.h>

StreamV4l2::StreamV4l2(GstreamerPipelineBuilder &_gst_builder, std::string _path,
                       std::string _device_path)
    : Stream()
    , name("")
    , path(_path)
    , device_path(_device_path)
    , gst_builder(_gst_builder)
{
    get_v4l2_info();
}

const std::string StreamV4l2::get_path() const
{
    return path;
}

const std::string StreamV4l2::get_name() const
{
    return name;
}

const std::vector<Stream::PixelFormat> &StreamV4l2::get_formats() const
{
    return formats;
}

void StreamV4l2::get_v4l2_info()
{
    int fd = open(device_path.c_str(), O_RDONLY);
    if (fd == -1) {
        log_error("Not able to load StreamV4l2 %s formats.", get_name().c_str());
        return;
    }

    struct v4l2_fmtdesc fmt = {};
    struct v4l2_frmsizeenum frame_size = {};
    struct v4l2_capability cap;
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    while (ioctl(fd, VIDIOC_ENUM_FMT, &fmt) != -1) {
        Stream::PixelFormat format{fmt.pixelformat};

        frame_size.index = 0;
        frame_size.pixel_format = fmt.pixelformat;
        while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frame_size) != -1) {
            if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
                format.frame_sizes.emplace_back(
                    FrameSize{frame_size.discrete.width, frame_size.discrete.height});
                frame_size.index++;
            } else {
                // TODO: Support different frame size types
            }
        }
        formats.push_back(format);
        fmt.index++;
    }

    if (ioctl(fd, VIDIOC_QUERYCAP, &cap) != -1)
        name = (const char *)cap.card;
    close(fd);
}

GstElement *StreamV4l2::create_gstreamer_pipeline(std::map<std::string, std::string> &params) const
{
    GError *error = nullptr;
    GstElement *pipeline;
    std::string source = "v4l2src device=";
    source.append(device_path);

    std::string pipeline_str = gst_builder.create_pipeline(source, params);
    pipeline = gst_parse_launch(pipeline_str.c_str(), &error);
    if (!pipeline) {
        log_error("Error processing pipeline for device %s: %s\n", device_path.c_str(),
                  error ? error->message : "unknown error");
        log_debug("Pipeline %s", pipeline_str.c_str());
        if (error)
            g_clear_error(&error);

        return nullptr;
    }

    return pipeline;
}
<commit_msg>v4l2: Use device name if device card name not available<commit_after>/*
 * This file is part of the Camera Streaming Daemon
 *
 * Copyright (C) 2017  Intel Corporation. All rights reserved.
 *
 * 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.
 */
#include <fcntl.h>
#include <sstream>
#include <sys/ioctl.h>
#include <unistd.h>

#include "log.h"
#include "stream_v4l2.h"
#include <linux/videodev2.h>

StreamV4l2::StreamV4l2(GstreamerPipelineBuilder &_gst_builder, std::string _path,
                       std::string _device_path)
    : Stream()
    , name("")
    , path(_path)
    , device_path(_device_path)
    , gst_builder(_gst_builder)
{
    get_v4l2_info();
}

const std::string StreamV4l2::get_path() const
{
    return path;
}

const std::string StreamV4l2::get_name() const
{
    return name;
}

const std::vector<Stream::PixelFormat> &StreamV4l2::get_formats() const
{
    return formats;
}

void StreamV4l2::get_v4l2_info()
{
    int fd = open(device_path.c_str(), O_RDONLY);
    if (fd == -1) {
        log_error("Not able to load StreamV4l2 %s formats.", get_name().c_str());
        return;
    }

    struct v4l2_fmtdesc fmt = {};
    struct v4l2_frmsizeenum frame_size = {};
    struct v4l2_capability cap;
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    while (ioctl(fd, VIDIOC_ENUM_FMT, &fmt) != -1) {
        Stream::PixelFormat format{fmt.pixelformat};

        frame_size.index = 0;
        frame_size.pixel_format = fmt.pixelformat;
        while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frame_size) != -1) {
            if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
                format.frame_sizes.emplace_back(
                    FrameSize{frame_size.discrete.width, frame_size.discrete.height});
                frame_size.index++;
            } else {
                // TODO: Support different frame size types
            }
        }
        formats.push_back(format);
        fmt.index++;
    }

    if (ioctl(fd, VIDIOC_QUERYCAP, &cap) != -1) {
        name = (const char *)cap.card;
    } else {
        name = path.substr(1);
    }
    close(fd);
}

GstElement *StreamV4l2::create_gstreamer_pipeline(std::map<std::string, std::string> &params) const
{
    GError *error = nullptr;
    GstElement *pipeline;
    std::string source = "v4l2src device=";
    source.append(device_path);

    std::string pipeline_str = gst_builder.create_pipeline(source, params);
    pipeline = gst_parse_launch(pipeline_str.c_str(), &error);
    if (!pipeline) {
        log_error("Error processing pipeline for device %s: %s\n", device_path.c_str(),
                  error ? error->message : "unknown error");
        log_debug("Pipeline %s", pipeline_str.c_str());
        if (error)
            g_clear_error(&error);

        return nullptr;
    }

    return pipeline;
}
<|endoftext|>


<commit_before>#ifndef SURFACEPOOL_HPP_INCLUDED
#define SURFACEPOOL_HPP_INCLUDED

#include "programpool.hpp"
#include "surface.hpp"

namespace gst
{
    class BasicShading;
    class BlinnPhongShading;

    typedef std::unordered_map<std::string, std::shared_ptr<MaterialShading>> MaterialCache;

    class SurfacePool {
    public:
        SurfacePool(ProgramPool & programs);
        template<typename T>
        Surface create(
            std::string const & vs_path,
            std::string const & fs_path);
        Surface create_basic(
            std::string const & vs_path,
            std::string const & fs_path);
        Surface create_blinn_phong(
            std::string const & vs_path,
            std::string const & fs_path);
    private:
        ProgramPool programs;
        MaterialCache cache;
    };
}

template<typename T>
gst::Surface gst::SurfacePool::create(
    std::string const & vs_path,
    std::string const & fs_path)
{
    auto program = programs.create(vs_path, fs_path);

    const std::string key = vs_path + fs_path;
    if (cache.count(key) == 0) {
        cache[key] = std::make_shared<T>(program);
    }
    auto material = Material(cache.at(key));

    return Surface(material, program);
}

#endif
<commit_msg>remove unused forward declarations<commit_after>#ifndef SURFACEPOOL_HPP_INCLUDED
#define SURFACEPOOL_HPP_INCLUDED

#include "programpool.hpp"
#include "surface.hpp"

namespace gst
{
    typedef std::unordered_map<std::string, std::shared_ptr<MaterialShading>> MaterialCache;

    class SurfacePool {
    public:
        SurfacePool(ProgramPool & programs);
        template<typename T>
        Surface create(
            std::string const & vs_path,
            std::string const & fs_path);
        Surface create_basic(
            std::string const & vs_path,
            std::string const & fs_path);
        Surface create_blinn_phong(
            std::string const & vs_path,
            std::string const & fs_path);
    private:
        ProgramPool programs;
        MaterialCache cache;
    };
}

template<typename T>
gst::Surface gst::SurfacePool::create(
    std::string const & vs_path,
    std::string const & fs_path)
{
    auto program = programs.create(vs_path, fs_path);

    const std::string key = vs_path + fs_path;
    if (cache.count(key) == 0) {
        cache[key] = std::make_shared<T>(program);
    }
    auto material = Material(cache.at(key));

    return Surface(material, program);
}

#endif
<|endoftext|>


<commit_before>// ///////////////////////////////////////////////////////////////////////////
// test_vector.cpp by Victor Dods, created 2013/04/02
// Copyright Leap Motion Inc.
// ///////////////////////////////////////////////////////////////////////////

#include "test_vector.hpp"

#include <iomanip>
#include <sstream>
#include <vector>
#include <complex>

#include "tenh/vector.hpp"

// this is included last because it redefines the `assert` macro,
// which would be bad for the above includes.
#include "lvd_testsystem.hpp"

using namespace Lvd;
using namespace std;
using namespace TestSystem;

namespace Test {
namespace Vector {

template <typename Scalar, Uint32 DIM>
void constructor_without_initialization (Context const &context)
{
    typedef Tenh::Vector_t<Scalar,DIM> Vector;

    Vector v(Tenh::Static<>::WITHOUT_INITIALIZATION);
}

template <typename Scalar, Uint32 DIM>
void constructor_fill_with (Context const &context)
{
    typedef Tenh::Vector_t<Scalar,DIM> Vector;

    Scalar fill = context.DataAs<Scalar>();
    Vector v(fill);
    for (typename Vector::Index i; i.is_not_at_end(); ++i)
    {
        assert_eq(v[i], fill);
    }
}

#define FORMAT(x) static_cast<ostringstream &>(ostringstream().flush() << x).str()

template <typename Scalar, Uint32 DIM>
void add_particular_tests (Directory *parent)
{
    Directory *vector = new Directory(FORMAT("Vector_t<" << Tenh::TypeStringOf_t<Scalar>::eval() << ',' << DIM << '>'), parent);
    LVD_ADD_NAMED_TEST_CASE_FUNCTION(vector, "constructor_without_initialization", constructor_without_initialization<Scalar,DIM>, RESULT_NO_ERROR);
    LVD_ADD_NAMED_TEST_CASE_FUNCTION(vector, "constructor_fill_with", constructor_fill_with<Scalar,DIM>, new Context::Data<Scalar>(42), RESULT_NO_ERROR);
}

template <typename Scalar>
void add_particular_tests_for_scalar (Directory *parent)
{
    add_particular_tests<Scalar,1>(parent);
    add_particular_tests<Scalar,2>(parent);
    add_particular_tests<Scalar,3>(parent);
    add_particular_tests<Scalar,4>(parent);
    add_particular_tests<Scalar,10>(parent);
    add_particular_tests<Scalar,100>(parent);
}

void AddTests (Directory *parent)
{
    Directory *vector = new Directory("Vector_t", parent);
    add_particular_tests_for_scalar<float>(vector);
    add_particular_tests_for_scalar<double>(vector);
    add_particular_tests_for_scalar<complex<float> >(vector);
    add_particular_tests_for_scalar<complex<double> >(vector);
}

} // end of namespace Vector
} // end of namespace Test
<commit_msg>Add a test of vector initialization with multiple values, and test Vector_t against integer types.<commit_after>// ///////////////////////////////////////////////////////////////////////////
// test_vector.cpp by Victor Dods, created 2013/04/02
// Copyright Leap Motion Inc.
// ///////////////////////////////////////////////////////////////////////////

#include "test_vector.hpp"

#include <iomanip>
#include <sstream>
#include <vector>
#include <complex>

#include "tenh/vector.hpp"

// this is included last because it redefines the `assert` macro,
// which would be bad for the above includes.
#include "lvd_testsystem.hpp"

using namespace Lvd;
using namespace std;
using namespace TestSystem;

namespace Test {
namespace Vector {

template <typename Scalar, Uint32 DIM>
void constructor_without_initialization (Context const &context)
{
    typedef Tenh::Vector_t<Scalar,DIM> Vector;

    Vector v(Tenh::Static<>::WITHOUT_INITIALIZATION);
}

template <typename Scalar, Uint32 DIM>
void constructor_fill_with (Context const &context)
{
    typedef Tenh::Vector_t<Scalar,DIM> Vector;

    Scalar fill = context.DataAs<Scalar>();
    Vector v(fill);
    for (typename Vector::Index i; i.is_not_at_end(); ++i)
    {
        assert_eq(v[i], fill);
    }
}

template <typename Scalar>
void check_filled_values (Context const &context)
{
    typedef Tenh::Vector_t<Scalar,4> Vector;

    Vector v(0,2,4,6);
    for (typename Vector::Index i; i.is_not_at_end(); ++i)
    {
        assert_eq(v[i], Scalar(2*i.value()));
    }
}

#define FORMAT(x) static_cast<ostringstream &>(ostringstream().flush() << x).str()

template <typename Scalar, Uint32 DIM>
void add_particular_tests (Directory *parent)
{
    Directory *vector = new Directory(FORMAT("Vector_t<" << Tenh::TypeStringOf_t<Scalar>::eval() << ',' << DIM << '>'), parent);
    LVD_ADD_NAMED_TEST_CASE_FUNCTION(vector, "constructor_without_initialization", constructor_without_initialization<Scalar,DIM>, RESULT_NO_ERROR);
    LVD_ADD_NAMED_TEST_CASE_FUNCTION(vector, "constructor_fill_with", constructor_fill_with<Scalar,DIM>, new Context::Data<Scalar>(42), RESULT_NO_ERROR);
}

template <typename Scalar>
void add_particular_tests_for_scalar (Directory *parent)
{
    add_particular_tests<Scalar,1>(parent);
    add_particular_tests<Scalar,2>(parent);
    add_particular_tests<Scalar,100>(parent);
    LVD_ADD_NAMED_TEST_CASE_FUNCTION(parent, FORMAT("check_filled_values<" << Tenh::TypeStringOf_t<Scalar>::eval() << ">"), check_filled_values<Scalar>, RESULT_NO_ERROR);

}

void AddTests (Directory *parent)
{
    Directory *vector = new Directory("Vector_t", parent);
    add_particular_tests_for_scalar<char>(vector);
    add_particular_tests_for_scalar<unsigned int>(vector);
    add_particular_tests_for_scalar<long>(vector);
    add_particular_tests_for_scalar<float>(vector);
    add_particular_tests_for_scalar<double>(vector);
    add_particular_tests_for_scalar<complex<float> >(vector);
    add_particular_tests_for_scalar<complex<double> >(vector);
}

} // end of namespace Vector
} // end of namespace Test
<|endoftext|>


<commit_before>// Copyright 2018 Google LLC
//
// 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.

#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

#include "gtest/gtest.h"
#include "absl/strings/str_cat.h"
#include "test/util/capability_util.h"
#include "test/util/file_descriptor.h"
#include "test/util/fs_util.h"
#include "test/util/temp_path.h"
#include "test/util/test_util.h"

namespace gvisor {
namespace testing {

namespace {

TEST(UnlinkTest, IsDir) {
  auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());

  EXPECT_THAT(unlink(dir.path().c_str()), SyscallFailsWithErrno(EISDIR));
}

TEST(UnlinkTest, DirNotEmpty) {
  auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());

  int fd;
  std::string path = JoinPath(dir.path(), "ExistingFile");
  EXPECT_THAT(fd = open(path.c_str(), O_RDWR | O_CREAT, 0666),
              SyscallSucceeds());
  EXPECT_THAT(close(fd), SyscallSucceeds());
  EXPECT_THAT(rmdir(dir.path().c_str()), SyscallFailsWithErrno(ENOTEMPTY));
}

TEST(UnlinkTest, Rmdir) {
  std::string path = JoinPath(GetAbsoluteTestTmpdir(), "NewDir");
  ASSERT_THAT(mkdir(path.c_str(), 0755), SyscallSucceeds());
  EXPECT_THAT(rmdir(path.c_str()), SyscallSucceeds());
}

TEST(UnlinkTest, AtDir) {
  int dirfd;
  EXPECT_THAT(dirfd = open(GetAbsoluteTestTmpdir().c_str(), O_DIRECTORY, 0),
              SyscallSucceeds());

  std::string path = JoinPath(GetAbsoluteTestTmpdir(), "NewDir");
  EXPECT_THAT(mkdir(path.c_str(), 0755), SyscallSucceeds());
  EXPECT_THAT(unlinkat(dirfd, "NewDir", AT_REMOVEDIR), SyscallSucceeds());
  ASSERT_THAT(close(dirfd), SyscallSucceeds());
}

TEST(UnlinkTest, AtDirDegradedPermissions_NoRandomSave) {
  // Drop capabilities that allow us to override file and directory permissions.
  ASSERT_NO_ERRNO(SetCapability(CAP_DAC_OVERRIDE, false));
  ASSERT_NO_ERRNO(SetCapability(CAP_DAC_READ_SEARCH, false));

  auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());

  int dirfd;
  ASSERT_THAT(dirfd = open(dir.path().c_str(), O_DIRECTORY, 0),
              SyscallSucceeds());

  std::string sub_dir = JoinPath(dir.path(), "NewDir");
  EXPECT_THAT(mkdir(sub_dir.c_str(), 0755), SyscallSucceeds());
  EXPECT_THAT(fchmod(dirfd, 0444), SyscallSucceeds());
  EXPECT_THAT(unlinkat(dirfd, "NewDir", AT_REMOVEDIR),
              SyscallFailsWithErrno(EACCES));
  ASSERT_THAT(close(dirfd), SyscallSucceeds());
}

// Files cannot be unlinked if the parent is not writable and executable.
TEST(UnlinkTest, ParentDegradedPermissions) {
  // Drop capabilities that allow us to override file and directory permissions.
  ASSERT_NO_ERRNO(SetCapability(CAP_DAC_OVERRIDE, false));
  ASSERT_NO_ERRNO(SetCapability(CAP_DAC_READ_SEARCH, false));

  auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileIn(dir.path()));

  ASSERT_THAT(chmod(dir.path().c_str(), 0000), SyscallSucceeds());

  struct stat st;
  ASSERT_THAT(stat(file.path().c_str(), &st), SyscallFailsWithErrno(EACCES));
  ASSERT_THAT(unlinkat(AT_FDCWD, file.path().c_str(), 0),
              SyscallFailsWithErrno(EACCES));

  // Non-existent files also return EACCES.
  const std::string nonexist = JoinPath(dir.path(), "doesnotexist");
  ASSERT_THAT(stat(nonexist.c_str(), &st), SyscallFailsWithErrno(EACCES));
  ASSERT_THAT(unlinkat(AT_FDCWD, nonexist.c_str(), 0),
              SyscallFailsWithErrno(EACCES));
}

TEST(UnlinkTest, AtBad) {
  int dirfd;
  EXPECT_THAT(dirfd = open(GetAbsoluteTestTmpdir().c_str(), O_DIRECTORY, 0),
              SyscallSucceeds());

  // Try removing a directory as a file.
  std::string path = JoinPath(GetAbsoluteTestTmpdir(), "NewDir");
  EXPECT_THAT(mkdir(path.c_str(), 0755), SyscallSucceeds());
  EXPECT_THAT(unlinkat(dirfd, "NewDir", 0), SyscallFailsWithErrno(EISDIR));
  EXPECT_THAT(unlinkat(dirfd, "NewDir", AT_REMOVEDIR), SyscallSucceeds());

  // Try removing a file as a directory.
  int fd;
  EXPECT_THAT(fd = openat(dirfd, "UnlinkAtFile", O_RDWR | O_CREAT, 0666),
              SyscallSucceeds());
  EXPECT_THAT(unlinkat(dirfd, "UnlinkAtFile", AT_REMOVEDIR),
              SyscallFailsWithErrno(ENOTDIR));
  ASSERT_THAT(close(fd), SyscallSucceeds());
  EXPECT_THAT(unlinkat(dirfd, "UnlinkAtFile", 0), SyscallSucceeds());

  // Cleanup.
  ASSERT_THAT(close(dirfd), SyscallSucceeds());
}

TEST(UnlinkTest, AbsTmpFile) {
  int fd;
  std::string path = JoinPath(GetAbsoluteTestTmpdir(), "ExistingFile");
  EXPECT_THAT(fd = open(path.c_str(), O_RDWR | O_CREAT, 0666),
              SyscallSucceeds());
  EXPECT_THAT(close(fd), SyscallSucceeds());
  EXPECT_THAT(unlink(path.c_str()), SyscallSucceeds());
}

TEST(UnlinkTest, TooLongName) {
  EXPECT_THAT(unlink(std::vector<char>(16384, '0').data()),
              SyscallFailsWithErrno(ENAMETOOLONG));
}

TEST(UnlinkTest, BadNamePtr) {
  EXPECT_THAT(unlink(reinterpret_cast<char*>(1)),
              SyscallFailsWithErrno(EFAULT));
}

TEST(UnlinkTest, AtFile) {
  int dirfd;
  EXPECT_THAT(dirfd = open(GetAbsoluteTestTmpdir().c_str(), O_DIRECTORY, 0666),
              SyscallSucceeds());
  int fd;
  EXPECT_THAT(fd = openat(dirfd, "UnlinkAtFile", O_RDWR | O_CREAT, 0666),
              SyscallSucceeds());
  EXPECT_THAT(close(fd), SyscallSucceeds());
  EXPECT_THAT(unlinkat(dirfd, "UnlinkAtFile", 0), SyscallSucceeds());
}

TEST(UnlinkTest, OpenFile) {
  // We can't save unlinked file unless they are on tmpfs.
  const DisableSave ds;
  auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
  int fd;
  EXPECT_THAT(fd = open(file.path().c_str(), O_RDWR, 0666), SyscallSucceeds());
  EXPECT_THAT(unlink(file.path().c_str()), SyscallSucceeds());
  EXPECT_THAT(close(fd), SyscallSucceeds());
}

TEST(UnlinkTest, CannotRemoveDots) {
  auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
  const std::string self = JoinPath(file.path(), ".");
  ASSERT_THAT(unlink(self.c_str()), SyscallFailsWithErrno(ENOTDIR));
  const std::string parent = JoinPath(file.path(), "..");
  ASSERT_THAT(unlink(parent.c_str()), SyscallFailsWithErrno(ENOTDIR));
}

TEST(UnlinkTest, CannotRemoveRoot) {
  ASSERT_THAT(unlinkat(-1, "/", AT_REMOVEDIR), SyscallFailsWithErrno(EBUSY));
}

TEST(UnlinkTest, CannotRemoveRootWithAtDir) {
  const FileDescriptor dirfd = ASSERT_NO_ERRNO_AND_VALUE(
      Open(GetAbsoluteTestTmpdir(), O_DIRECTORY, 0666));
  ASSERT_THAT(unlinkat(dirfd.get(), "/", AT_REMOVEDIR),
              SyscallFailsWithErrno(EBUSY));
}

TEST(RmdirTest, CannotRemoveDots) {
  auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  const std::string self = JoinPath(dir.path(), ".");
  ASSERT_THAT(rmdir(self.c_str()), SyscallFailsWithErrno(EINVAL));
  const std::string parent = JoinPath(dir.path(), "..");
  ASSERT_THAT(rmdir(parent.c_str()), SyscallFailsWithErrno(ENOTEMPTY));
}

TEST(RmdirTest, CanRemoveWithTrailingSlashes) {
  auto dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  const std::string slash = absl::StrCat(dir1.path(), "/");
  ASSERT_THAT(rmdir(slash.c_str()), SyscallSucceeds());
  auto dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  const std::string slashslash = absl::StrCat(dir2.path(), "//");
  ASSERT_THAT(rmdir(slashslash.c_str()), SyscallSucceeds());
}

}  // namespace

}  // namespace testing
}  // namespace gvisor
<commit_msg>Deflake unlink test.<commit_after>// Copyright 2018 Google LLC
//
// 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.

#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

#include "gtest/gtest.h"
#include "absl/strings/str_cat.h"
#include "test/util/capability_util.h"
#include "test/util/file_descriptor.h"
#include "test/util/fs_util.h"
#include "test/util/temp_path.h"
#include "test/util/test_util.h"

namespace gvisor {
namespace testing {

namespace {

TEST(UnlinkTest, IsDir) {
  auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());

  EXPECT_THAT(unlink(dir.path().c_str()), SyscallFailsWithErrno(EISDIR));
}

TEST(UnlinkTest, DirNotEmpty) {
  auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());

  int fd;
  std::string path = JoinPath(dir.path(), "ExistingFile");
  EXPECT_THAT(fd = open(path.c_str(), O_RDWR | O_CREAT, 0666),
              SyscallSucceeds());
  EXPECT_THAT(close(fd), SyscallSucceeds());
  EXPECT_THAT(rmdir(dir.path().c_str()), SyscallFailsWithErrno(ENOTEMPTY));
}

TEST(UnlinkTest, Rmdir) {
  auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  EXPECT_THAT(rmdir(dir.path().c_str()), SyscallSucceeds());
}

TEST(UnlinkTest, AtDir) {
  int dirfd;
  auto tmpdir = GetAbsoluteTestTmpdir();
  EXPECT_THAT(dirfd = open(tmpdir.c_str(), O_DIRECTORY, 0), SyscallSucceeds());

  auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(tmpdir));
  auto dir_relpath =
      ASSERT_NO_ERRNO_AND_VALUE(GetRelativePath(tmpdir, dir.path()));
  EXPECT_THAT(unlinkat(dirfd, dir_relpath.c_str(), AT_REMOVEDIR),
              SyscallSucceeds());
  ASSERT_THAT(close(dirfd), SyscallSucceeds());
}

TEST(UnlinkTest, AtDirDegradedPermissions_NoRandomSave) {
  // Drop capabilities that allow us to override file and directory permissions.
  ASSERT_NO_ERRNO(SetCapability(CAP_DAC_OVERRIDE, false));
  ASSERT_NO_ERRNO(SetCapability(CAP_DAC_READ_SEARCH, false));

  auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());

  int dirfd;
  ASSERT_THAT(dirfd = open(dir.path().c_str(), O_DIRECTORY, 0),
              SyscallSucceeds());

  std::string sub_dir = JoinPath(dir.path(), "NewDir");
  EXPECT_THAT(mkdir(sub_dir.c_str(), 0755), SyscallSucceeds());
  EXPECT_THAT(fchmod(dirfd, 0444), SyscallSucceeds());
  EXPECT_THAT(unlinkat(dirfd, "NewDir", AT_REMOVEDIR),
              SyscallFailsWithErrno(EACCES));
  ASSERT_THAT(close(dirfd), SyscallSucceeds());
}

// Files cannot be unlinked if the parent is not writable and executable.
TEST(UnlinkTest, ParentDegradedPermissions) {
  // Drop capabilities that allow us to override file and directory permissions.
  ASSERT_NO_ERRNO(SetCapability(CAP_DAC_OVERRIDE, false));
  ASSERT_NO_ERRNO(SetCapability(CAP_DAC_READ_SEARCH, false));

  auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileIn(dir.path()));

  ASSERT_THAT(chmod(dir.path().c_str(), 0000), SyscallSucceeds());

  struct stat st;
  ASSERT_THAT(stat(file.path().c_str(), &st), SyscallFailsWithErrno(EACCES));
  ASSERT_THAT(unlinkat(AT_FDCWD, file.path().c_str(), 0),
              SyscallFailsWithErrno(EACCES));

  // Non-existent files also return EACCES.
  const std::string nonexist = JoinPath(dir.path(), "doesnotexist");
  ASSERT_THAT(stat(nonexist.c_str(), &st), SyscallFailsWithErrno(EACCES));
  ASSERT_THAT(unlinkat(AT_FDCWD, nonexist.c_str(), 0),
              SyscallFailsWithErrno(EACCES));
}

TEST(UnlinkTest, AtBad) {
  int dirfd;
  EXPECT_THAT(dirfd = open(GetAbsoluteTestTmpdir().c_str(), O_DIRECTORY, 0),
              SyscallSucceeds());

  // Try removing a directory as a file.
  std::string path = JoinPath(GetAbsoluteTestTmpdir(), "NewDir");
  EXPECT_THAT(mkdir(path.c_str(), 0755), SyscallSucceeds());
  EXPECT_THAT(unlinkat(dirfd, "NewDir", 0), SyscallFailsWithErrno(EISDIR));
  EXPECT_THAT(unlinkat(dirfd, "NewDir", AT_REMOVEDIR), SyscallSucceeds());

  // Try removing a file as a directory.
  int fd;
  EXPECT_THAT(fd = openat(dirfd, "UnlinkAtFile", O_RDWR | O_CREAT, 0666),
              SyscallSucceeds());
  EXPECT_THAT(unlinkat(dirfd, "UnlinkAtFile", AT_REMOVEDIR),
              SyscallFailsWithErrno(ENOTDIR));
  ASSERT_THAT(close(fd), SyscallSucceeds());
  EXPECT_THAT(unlinkat(dirfd, "UnlinkAtFile", 0), SyscallSucceeds());

  // Cleanup.
  ASSERT_THAT(close(dirfd), SyscallSucceeds());
}

TEST(UnlinkTest, AbsTmpFile) {
  int fd;
  std::string path = JoinPath(GetAbsoluteTestTmpdir(), "ExistingFile");
  EXPECT_THAT(fd = open(path.c_str(), O_RDWR | O_CREAT, 0666),
              SyscallSucceeds());
  EXPECT_THAT(close(fd), SyscallSucceeds());
  EXPECT_THAT(unlink(path.c_str()), SyscallSucceeds());
}

TEST(UnlinkTest, TooLongName) {
  EXPECT_THAT(unlink(std::vector<char>(16384, '0').data()),
              SyscallFailsWithErrno(ENAMETOOLONG));
}

TEST(UnlinkTest, BadNamePtr) {
  EXPECT_THAT(unlink(reinterpret_cast<char*>(1)),
              SyscallFailsWithErrno(EFAULT));
}

TEST(UnlinkTest, AtFile) {
  int dirfd;
  EXPECT_THAT(dirfd = open(GetAbsoluteTestTmpdir().c_str(), O_DIRECTORY, 0666),
              SyscallSucceeds());
  int fd;
  EXPECT_THAT(fd = openat(dirfd, "UnlinkAtFile", O_RDWR | O_CREAT, 0666),
              SyscallSucceeds());
  EXPECT_THAT(close(fd), SyscallSucceeds());
  EXPECT_THAT(unlinkat(dirfd, "UnlinkAtFile", 0), SyscallSucceeds());
}

TEST(UnlinkTest, OpenFile) {
  // We can't save unlinked file unless they are on tmpfs.
  const DisableSave ds;
  auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
  int fd;
  EXPECT_THAT(fd = open(file.path().c_str(), O_RDWR, 0666), SyscallSucceeds());
  EXPECT_THAT(unlink(file.path().c_str()), SyscallSucceeds());
  EXPECT_THAT(close(fd), SyscallSucceeds());
}

TEST(UnlinkTest, CannotRemoveDots) {
  auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
  const std::string self = JoinPath(file.path(), ".");
  ASSERT_THAT(unlink(self.c_str()), SyscallFailsWithErrno(ENOTDIR));
  const std::string parent = JoinPath(file.path(), "..");
  ASSERT_THAT(unlink(parent.c_str()), SyscallFailsWithErrno(ENOTDIR));
}

TEST(UnlinkTest, CannotRemoveRoot) {
  ASSERT_THAT(unlinkat(-1, "/", AT_REMOVEDIR), SyscallFailsWithErrno(EBUSY));
}

TEST(UnlinkTest, CannotRemoveRootWithAtDir) {
  const FileDescriptor dirfd = ASSERT_NO_ERRNO_AND_VALUE(
      Open(GetAbsoluteTestTmpdir(), O_DIRECTORY, 0666));
  ASSERT_THAT(unlinkat(dirfd.get(), "/", AT_REMOVEDIR),
              SyscallFailsWithErrno(EBUSY));
}

TEST(RmdirTest, CannotRemoveDots) {
  auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  const std::string self = JoinPath(dir.path(), ".");
  ASSERT_THAT(rmdir(self.c_str()), SyscallFailsWithErrno(EINVAL));
  const std::string parent = JoinPath(dir.path(), "..");
  ASSERT_THAT(rmdir(parent.c_str()), SyscallFailsWithErrno(ENOTEMPTY));
}

TEST(RmdirTest, CanRemoveWithTrailingSlashes) {
  auto dir1 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  const std::string slash = absl::StrCat(dir1.path(), "/");
  ASSERT_THAT(rmdir(slash.c_str()), SyscallSucceeds());
  auto dir2 = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
  const std::string slashslash = absl::StrCat(dir2.path(), "//");
  ASSERT_THAT(rmdir(slashslash.c_str()), SyscallSucceeds());
}

}  // namespace

}  // namespace testing
}  // namespace gvisor
<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/yosys.h"
#include "kernel/sigtools.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

// for peepopt_pm
bool did_something;

#include "passes/pmgen/test_pmgen_pm.h"
#include "passes/pmgen/ice40_dsp_pm.h"
#include "passes/pmgen/xilinx_srl_pm.h"
#include "passes/pmgen/peepopt_pm.h"

void reduce_chain(test_pmgen_pm &pm)
{
	auto &st = pm.st_reduce;
	auto &ud = pm.ud_reduce;

	if (ud.longest_chain.empty())
		return;

	log("Found chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type));

	SigSpec A;
	SigSpec Y = ud.longest_chain.front().first->getPort(ID(Y));
	auto last_cell = ud.longest_chain.back().first;

	for (auto it : ud.longest_chain) {
		auto cell = it.first;
		if (cell == last_cell) {
			A.append(cell->getPort(ID(A)));
			A.append(cell->getPort(ID(B)));
		} else {
			A.append(cell->getPort(it.second == ID(A) ? ID(B) : ID(A)));
		}
		log("    %s\n", log_id(cell));
		pm.autoremove(cell);
	}

	Cell *c;

	if (last_cell->type == ID($_AND_))
		c = pm.module->addReduceAnd(NEW_ID, A, Y);
	else if (last_cell->type == ID($_OR_))
		c = pm.module->addReduceOr(NEW_ID, A, Y);
	else if (last_cell->type == ID($_XOR_))
		c = pm.module->addReduceXor(NEW_ID, A, Y);
	else
		log_abort();

	log("    -> %s (%s)\n", log_id(c), log_id(c->type));
}

void reduce_tree(test_pmgen_pm &pm)
{
	auto &st = pm.st_reduce;
	auto &ud = pm.ud_reduce;

	if (ud.longest_chain.empty())
		return;

	SigSpec A = ud.leaves;
	SigSpec Y = st.first->getPort(ID(Y));
	pm.autoremove(st.first);

	log("Found %s tree with %d leaves for %s (%s).\n", log_id(st.first->type),
			GetSize(A), log_signal(Y), log_id(st.first));

	Cell *c;

	if (st.first->type == ID($_AND_))
		c = pm.module->addReduceAnd(NEW_ID, A, Y);
	else if (st.first->type == ID($_OR_))
		c = pm.module->addReduceOr(NEW_ID, A, Y);
	else if (st.first->type == ID($_XOR_))
		c = pm.module->addReduceXor(NEW_ID, A, Y);
	else
		log_abort();

	log("    -> %s (%s)\n", log_id(c), log_id(c->type));
}

void opt_eqpmux(test_pmgen_pm &pm)
{
	auto &st = pm.st_eqpmux;

	SigSpec Y = st.pmux->getPort(ID::Y);
	int width = GetSize(Y);

	SigSpec EQ = st.pmux->getPort(ID::B).extract(st.pmux_slice_eq*width, width);
	SigSpec NE = st.pmux->getPort(ID::B).extract(st.pmux_slice_ne*width, width);

	log("Found eqpmux circuit driving %s (eq=%s, ne=%s, pmux=%s).\n",
			log_signal(Y), log_id(st.eq), log_id(st.ne), log_id(st.pmux));

	pm.autoremove(st.pmux);
	Cell *c = pm.module->addMux(NEW_ID, NE, EQ, st.eq->getPort(ID::Y), Y);
	log("    -> %s (%s)\n", log_id(c), log_id(c->type));
}

#define GENERATE_PATTERN(pmclass, pattern) \
	generate_pattern<pmclass>([](pmclass &pm, std::function<void()> f){ return pm.run_ ## pattern(f); }, #pmclass, #pattern, design)

void pmtest_addports(Module *module)
{
	pool<SigBit> driven_bits, used_bits;
	SigMap sigmap(module);
	int icnt = 0, ocnt = 0;

	for (auto cell : module->cells())
	for (auto conn : cell->connections())
	{
		if (cell->input(conn.first))
			for (auto bit : sigmap(conn.second))
				used_bits.insert(bit);
		if (cell->output(conn.first))
			for (auto bit : sigmap(conn.second))
				driven_bits.insert(bit);
	}

	for (auto wire : vector<Wire*>(module->wires()))
	{
		SigSpec ibits, obits;
		for (auto bit : sigmap(wire)) {
			if (!used_bits.count(bit))
				obits.append(bit);
			if (!driven_bits.count(bit))
				ibits.append(bit);
		}
		if (!ibits.empty()) {
			Wire *w = module->addWire(stringf("\\i%d", icnt++), GetSize(ibits));
			w->port_input = true;
			module->connect(ibits, w);
		}
		if (!obits.empty()) {
			Wire *w = module->addWire(stringf("\\o%d", ocnt++), GetSize(obits));
			w->port_output = true;
			module->connect(w, obits);
		}
	}

	module->fixup_ports();
}

template <class pm>
void generate_pattern(std::function<void(pm&,std::function<void()>)> run, const char *pmclass, const char *pattern, Design *design)
{
	log("Generating \"%s\" patterns for pattern matcher \"%s\".\n", pattern, pmclass);

	int modcnt = 0;
	int maxmodcnt = 100;
	int maxsubcnt = 4;
	int timeout = 0;
	vector<Module*> mods;

	while (modcnt < maxmodcnt)
	{
		int submodcnt = 0, itercnt = 0, cellcnt = 0;
		Module *mod = design->addModule(NEW_ID);

		while (modcnt < maxmodcnt && submodcnt < maxsubcnt && itercnt++ < 1000)
		{
			if (timeout++ > 10000)
				log_error("pmgen generator is stuck: 10000 iterations with no matching module generated.\n");

			pm matcher(mod, mod->cells());

			matcher.rng(1);
			matcher.rngseed += modcnt;
			matcher.rng(1);
			matcher.rngseed += submodcnt;
			matcher.rng(1);
			matcher.rngseed += itercnt;
			matcher.rng(1);
			matcher.rngseed += cellcnt;
			matcher.rng(1);

			if (GetSize(mod->cells()) != cellcnt)
			{
				bool found_match = false;
				run(matcher, [&](){ found_match = true; });
				cellcnt = GetSize(mod->cells());

				if (found_match) {
					Module *m = design->addModule(stringf("\\pmtest_%s_%s_%05d",
							pmclass, pattern, modcnt++));
					log("Creating module %s with %d cells.\n", log_id(m), cellcnt);
					mod->cloneInto(m);
					pmtest_addports(m);
					mods.push_back(m);
					submodcnt++;
					timeout = 0;
				}
			}

			matcher.generate_mode = true;
			run(matcher, [](){});
		}

		if (submodcnt)
			maxsubcnt *= 2;

		design->remove(mod);
	}

	Module *m = design->addModule(stringf("\\pmtest_%s_%s", pmclass, pattern));
	log("Creating module %s with %d cells.\n", log_id(m), GetSize(mods));
	for (auto mod : mods) {
		Cell *c = m->addCell(mod->name, mod->name);
		for (auto port : mod->ports) {
			Wire *w = m->addWire(NEW_ID, GetSize(mod->wire(port)));
			c->setPort(port, w);
		}
	}
	pmtest_addports(m);
}

struct TestPmgenPass : public Pass {
	TestPmgenPass() : Pass("test_pmgen", "test pass for pmgen") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    test_pmgen -reduce_chain [options] [selection]\n");
		log("\n");
		log("Demo for recursive pmgen patterns. Map chains of AND/OR/XOR to $reduce_*.\n");
		log("\n");

		log("\n");
		log("    test_pmgen -reduce_tree [options] [selection]\n");
		log("\n");
		log("Demo for recursive pmgen patterns. Map trees of AND/OR/XOR to $reduce_*.\n");
		log("\n");

		log("\n");
		log("    test_pmgen -eqpmux [options] [selection]\n");
		log("\n");
		log("Demo for recursive pmgen patterns. Optimize EQ/NE/PMUX circuits.\n");
		log("\n");

		log("\n");
		log("    test_pmgen -generate [options] <pattern_name>\n");
		log("\n");
		log("Create modules that match the specified pattern.\n");
		log("\n");
	}

	void execute_reduce_chain(std::vector<std::string> args, RTLIL::Design *design)
	{
		log_header(design, "Executing TEST_PMGEN pass (-reduce_chain).\n");

		size_t argidx;
		for (argidx = 2; argidx < args.size(); argidx++)
		{
			// if (args[argidx] == "-singleton") {
			// 	singleton_mode = true;
			// 	continue;
			// }
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
			while (test_pmgen_pm(module, module->selected_cells()).run_reduce(reduce_chain)) {}
	}

	void execute_reduce_tree(std::vector<std::string> args, RTLIL::Design *design)
	{
		log_header(design, "Executing TEST_PMGEN pass (-reduce_tree).\n");

		size_t argidx;
		for (argidx = 2; argidx < args.size(); argidx++)
		{
			// if (args[argidx] == "-singleton") {
			// 	singleton_mode = true;
			// 	continue;
			// }
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
			test_pmgen_pm(module, module->selected_cells()).run_reduce(reduce_tree);
	}

	void execute_eqpmux(std::vector<std::string> args, RTLIL::Design *design)
	{
		log_header(design, "Executing TEST_PMGEN pass (-eqpmux).\n");

		size_t argidx;
		for (argidx = 2; argidx < args.size(); argidx++)
		{
			// if (args[argidx] == "-singleton") {
			// 	singleton_mode = true;
			// 	continue;
			// }
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
			test_pmgen_pm(module, module->selected_cells()).run_eqpmux(opt_eqpmux);
	}

	void execute_generate(std::vector<std::string> args, RTLIL::Design *design)
	{
		log_header(design, "Executing TEST_PMGEN pass (-generate).\n");

		size_t argidx;
		for (argidx = 2; argidx < args.size(); argidx++)
		{
			// if (args[argidx] == "-singleton") {
			// 	singleton_mode = true;
			// 	continue;
			// }
			break;
		}

		if (argidx+1 != args.size())
			log_cmd_error("Expected exactly one pattern.\n");

		string pattern = args[argidx];

		if (pattern == "reduce")
			return GENERATE_PATTERN(test_pmgen_pm, reduce);

		if (pattern == "eqpmux")
			return GENERATE_PATTERN(test_pmgen_pm, eqpmux);

		if (pattern == "ice40_dsp")
			return GENERATE_PATTERN(ice40_dsp_pm, ice40_dsp);

		if (pattern == "xilinx_srl_fixed")
			return GENERATE_PATTERN(xilinx_srl_pm, fixed);

		if (pattern == "peepopt-muldiv")
			return GENERATE_PATTERN(peepopt_pm, muldiv);

		if (pattern == "peepopt-shiftmul")
			return GENERATE_PATTERN(peepopt_pm, shiftmul);

		log_cmd_error("Unknown pattern: %s\n", pattern.c_str());
	}

	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		if (GetSize(args) > 1)
		{
			if (args[1] == "-reduce_chain")
				return execute_reduce_chain(args, design);
			if (args[1] == "-reduce_tree")
				return execute_reduce_tree(args, design);
			if (args[1] == "-eqpmux")
				return execute_eqpmux(args, design);
			if (args[1] == "-generate")
				return execute_generate(args, design);
		}
		help();
		log_cmd_error("Missing or unsupported mode parameter.\n");
	}
} TestPmgenPass;

PRIVATE_NAMESPACE_END
<commit_msg>Add xilinx_srl_pm.variable to test_pmgen<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/yosys.h"
#include "kernel/sigtools.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

// for peepopt_pm
bool did_something;

#include "passes/pmgen/test_pmgen_pm.h"
#include "passes/pmgen/ice40_dsp_pm.h"
#include "passes/pmgen/xilinx_srl_pm.h"
#include "passes/pmgen/peepopt_pm.h"

void reduce_chain(test_pmgen_pm &pm)
{
	auto &st = pm.st_reduce;
	auto &ud = pm.ud_reduce;

	if (ud.longest_chain.empty())
		return;

	log("Found chain of length %d (%s):\n", GetSize(ud.longest_chain), log_id(st.first->type));

	SigSpec A;
	SigSpec Y = ud.longest_chain.front().first->getPort(ID(Y));
	auto last_cell = ud.longest_chain.back().first;

	for (auto it : ud.longest_chain) {
		auto cell = it.first;
		if (cell == last_cell) {
			A.append(cell->getPort(ID(A)));
			A.append(cell->getPort(ID(B)));
		} else {
			A.append(cell->getPort(it.second == ID(A) ? ID(B) : ID(A)));
		}
		log("    %s\n", log_id(cell));
		pm.autoremove(cell);
	}

	Cell *c;

	if (last_cell->type == ID($_AND_))
		c = pm.module->addReduceAnd(NEW_ID, A, Y);
	else if (last_cell->type == ID($_OR_))
		c = pm.module->addReduceOr(NEW_ID, A, Y);
	else if (last_cell->type == ID($_XOR_))
		c = pm.module->addReduceXor(NEW_ID, A, Y);
	else
		log_abort();

	log("    -> %s (%s)\n", log_id(c), log_id(c->type));
}

void reduce_tree(test_pmgen_pm &pm)
{
	auto &st = pm.st_reduce;
	auto &ud = pm.ud_reduce;

	if (ud.longest_chain.empty())
		return;

	SigSpec A = ud.leaves;
	SigSpec Y = st.first->getPort(ID(Y));
	pm.autoremove(st.first);

	log("Found %s tree with %d leaves for %s (%s).\n", log_id(st.first->type),
			GetSize(A), log_signal(Y), log_id(st.first));

	Cell *c;

	if (st.first->type == ID($_AND_))
		c = pm.module->addReduceAnd(NEW_ID, A, Y);
	else if (st.first->type == ID($_OR_))
		c = pm.module->addReduceOr(NEW_ID, A, Y);
	else if (st.first->type == ID($_XOR_))
		c = pm.module->addReduceXor(NEW_ID, A, Y);
	else
		log_abort();

	log("    -> %s (%s)\n", log_id(c), log_id(c->type));
}

void opt_eqpmux(test_pmgen_pm &pm)
{
	auto &st = pm.st_eqpmux;

	SigSpec Y = st.pmux->getPort(ID::Y);
	int width = GetSize(Y);

	SigSpec EQ = st.pmux->getPort(ID::B).extract(st.pmux_slice_eq*width, width);
	SigSpec NE = st.pmux->getPort(ID::B).extract(st.pmux_slice_ne*width, width);

	log("Found eqpmux circuit driving %s (eq=%s, ne=%s, pmux=%s).\n",
			log_signal(Y), log_id(st.eq), log_id(st.ne), log_id(st.pmux));

	pm.autoremove(st.pmux);
	Cell *c = pm.module->addMux(NEW_ID, NE, EQ, st.eq->getPort(ID::Y), Y);
	log("    -> %s (%s)\n", log_id(c), log_id(c->type));
}

#define GENERATE_PATTERN(pmclass, pattern) \
	generate_pattern<pmclass>([](pmclass &pm, std::function<void()> f){ return pm.run_ ## pattern(f); }, #pmclass, #pattern, design)

void pmtest_addports(Module *module)
{
	pool<SigBit> driven_bits, used_bits;
	SigMap sigmap(module);
	int icnt = 0, ocnt = 0;

	for (auto cell : module->cells())
	for (auto conn : cell->connections())
	{
		if (cell->input(conn.first))
			for (auto bit : sigmap(conn.second))
				used_bits.insert(bit);
		if (cell->output(conn.first))
			for (auto bit : sigmap(conn.second))
				driven_bits.insert(bit);
	}

	for (auto wire : vector<Wire*>(module->wires()))
	{
		SigSpec ibits, obits;
		for (auto bit : sigmap(wire)) {
			if (!used_bits.count(bit))
				obits.append(bit);
			if (!driven_bits.count(bit))
				ibits.append(bit);
		}
		if (!ibits.empty()) {
			Wire *w = module->addWire(stringf("\\i%d", icnt++), GetSize(ibits));
			w->port_input = true;
			module->connect(ibits, w);
		}
		if (!obits.empty()) {
			Wire *w = module->addWire(stringf("\\o%d", ocnt++), GetSize(obits));
			w->port_output = true;
			module->connect(w, obits);
		}
	}

	module->fixup_ports();
}

template <class pm>
void generate_pattern(std::function<void(pm&,std::function<void()>)> run, const char *pmclass, const char *pattern, Design *design)
{
	log("Generating \"%s\" patterns for pattern matcher \"%s\".\n", pattern, pmclass);

	int modcnt = 0;
	int maxmodcnt = 100;
	int maxsubcnt = 4;
	int timeout = 0;
	vector<Module*> mods;

	while (modcnt < maxmodcnt)
	{
		int submodcnt = 0, itercnt = 0, cellcnt = 0;
		Module *mod = design->addModule(NEW_ID);

		while (modcnt < maxmodcnt && submodcnt < maxsubcnt && itercnt++ < 1000)
		{
			if (timeout++ > 10000)
				log_error("pmgen generator is stuck: 10000 iterations with no matching module generated.\n");

			pm matcher(mod, mod->cells());

			matcher.rng(1);
			matcher.rngseed += modcnt;
			matcher.rng(1);
			matcher.rngseed += submodcnt;
			matcher.rng(1);
			matcher.rngseed += itercnt;
			matcher.rng(1);
			matcher.rngseed += cellcnt;
			matcher.rng(1);

			if (GetSize(mod->cells()) != cellcnt)
			{
				bool found_match = false;
				run(matcher, [&](){ found_match = true; });
				cellcnt = GetSize(mod->cells());

				if (found_match) {
					Module *m = design->addModule(stringf("\\pmtest_%s_%s_%05d",
							pmclass, pattern, modcnt++));
					log("Creating module %s with %d cells.\n", log_id(m), cellcnt);
					mod->cloneInto(m);
					pmtest_addports(m);
					mods.push_back(m);
					submodcnt++;
					timeout = 0;
				}
			}

			matcher.generate_mode = true;
			run(matcher, [](){});
		}

		if (submodcnt)
			maxsubcnt *= 2;

		design->remove(mod);
	}

	Module *m = design->addModule(stringf("\\pmtest_%s_%s", pmclass, pattern));
	log("Creating module %s with %d cells.\n", log_id(m), GetSize(mods));
	for (auto mod : mods) {
		Cell *c = m->addCell(mod->name, mod->name);
		for (auto port : mod->ports) {
			Wire *w = m->addWire(NEW_ID, GetSize(mod->wire(port)));
			c->setPort(port, w);
		}
	}
	pmtest_addports(m);
}

struct TestPmgenPass : public Pass {
	TestPmgenPass() : Pass("test_pmgen", "test pass for pmgen") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    test_pmgen -reduce_chain [options] [selection]\n");
		log("\n");
		log("Demo for recursive pmgen patterns. Map chains of AND/OR/XOR to $reduce_*.\n");
		log("\n");

		log("\n");
		log("    test_pmgen -reduce_tree [options] [selection]\n");
		log("\n");
		log("Demo for recursive pmgen patterns. Map trees of AND/OR/XOR to $reduce_*.\n");
		log("\n");

		log("\n");
		log("    test_pmgen -eqpmux [options] [selection]\n");
		log("\n");
		log("Demo for recursive pmgen patterns. Optimize EQ/NE/PMUX circuits.\n");
		log("\n");

		log("\n");
		log("    test_pmgen -generate [options] <pattern_name>\n");
		log("\n");
		log("Create modules that match the specified pattern.\n");
		log("\n");
	}

	void execute_reduce_chain(std::vector<std::string> args, RTLIL::Design *design)
	{
		log_header(design, "Executing TEST_PMGEN pass (-reduce_chain).\n");

		size_t argidx;
		for (argidx = 2; argidx < args.size(); argidx++)
		{
			// if (args[argidx] == "-singleton") {
			// 	singleton_mode = true;
			// 	continue;
			// }
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
			while (test_pmgen_pm(module, module->selected_cells()).run_reduce(reduce_chain)) {}
	}

	void execute_reduce_tree(std::vector<std::string> args, RTLIL::Design *design)
	{
		log_header(design, "Executing TEST_PMGEN pass (-reduce_tree).\n");

		size_t argidx;
		for (argidx = 2; argidx < args.size(); argidx++)
		{
			// if (args[argidx] == "-singleton") {
			// 	singleton_mode = true;
			// 	continue;
			// }
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
			test_pmgen_pm(module, module->selected_cells()).run_reduce(reduce_tree);
	}

	void execute_eqpmux(std::vector<std::string> args, RTLIL::Design *design)
	{
		log_header(design, "Executing TEST_PMGEN pass (-eqpmux).\n");

		size_t argidx;
		for (argidx = 2; argidx < args.size(); argidx++)
		{
			// if (args[argidx] == "-singleton") {
			// 	singleton_mode = true;
			// 	continue;
			// }
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
			test_pmgen_pm(module, module->selected_cells()).run_eqpmux(opt_eqpmux);
	}

	void execute_generate(std::vector<std::string> args, RTLIL::Design *design)
	{
		log_header(design, "Executing TEST_PMGEN pass (-generate).\n");

		size_t argidx;
		for (argidx = 2; argidx < args.size(); argidx++)
		{
			// if (args[argidx] == "-singleton") {
			// 	singleton_mode = true;
			// 	continue;
			// }
			break;
		}

		if (argidx+1 != args.size())
			log_cmd_error("Expected exactly one pattern.\n");

		string pattern = args[argidx];

		if (pattern == "reduce")
			return GENERATE_PATTERN(test_pmgen_pm, reduce);

		if (pattern == "eqpmux")
			return GENERATE_PATTERN(test_pmgen_pm, eqpmux);

		if (pattern == "ice40_dsp")
			return GENERATE_PATTERN(ice40_dsp_pm, ice40_dsp);

		if (pattern == "xilinx_srl_fixed")
			return GENERATE_PATTERN(xilinx_srl_pm, fixed);
		if (pattern == "xilinx_srl_variable")
			return GENERATE_PATTERN(xilinx_srl_pm, variable);

		if (pattern == "peepopt-muldiv")
			return GENERATE_PATTERN(peepopt_pm, muldiv);

		if (pattern == "peepopt-shiftmul")
			return GENERATE_PATTERN(peepopt_pm, shiftmul);

		log_cmd_error("Unknown pattern: %s\n", pattern.c_str());
	}

	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		if (GetSize(args) > 1)
		{
			if (args[1] == "-reduce_chain")
				return execute_reduce_chain(args, design);
			if (args[1] == "-reduce_tree")
				return execute_reduce_tree(args, design);
			if (args[1] == "-eqpmux")
				return execute_eqpmux(args, design);
			if (args[1] == "-generate")
				return execute_generate(args, design);
		}
		help();
		log_cmd_error("Missing or unsupported mode parameter.\n");
	}
} TestPmgenPass;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>

/*============================================================================

    ^XNǗ(?)

==============================================================================*/

#include <cassert>
#include <algorithm>
#include <typeinfo>
#include "task.h"

namespace GTF
{

    CTaskManager::CTaskManager()
    {
        exNext = nullptr;
    }

    void CTaskManager::Destroy()
    {
        TaskList::iterator i, ied;

        //ʏ^XNTerminate
        i = tasks.begin();
        ied = tasks.end();
        for (; i != ied; i++){
            (*i)->Terminate();
        }
        tasks.clear();

        //obNOEh^XNTerminate
        i = bg_tasks.begin();
        ied = bg_tasks.end();
        for (; i != ied; i++){
            (*i)->Terminate();
        }
        bg_tasks.clear();

        //r^XNTerminate
        while (ex_stack.size() != 0){
            ex_stack.top()->Terminate();
            ex_stack.pop();
        }
    }

    CTaskManager::TaskPtr CTaskManager::AddTask(CTaskBase *newTask)
    {
        if (newTask->GetID() != 0){
            RemoveTaskByID(newTask->GetID());
        }

        CBackgroundTaskBase *pbgt = dynamic_cast<CBackgroundTaskBase*>(newTask);
        if (pbgt){
            //풓^XNƂAdd
            return AddTask(pbgt);
        }

        CExclusiveTaskBase *pext = dynamic_cast<CExclusiveTaskBase*>(newTask);
        if (pext){
            //r^XNƂAdd
            return AddTask(pext);
        }

        //ʏ^XNƂAdd
        tasks.emplace_back(newTask);
        auto& pnew = tasks.back();
        newTask->Initialize();
        if (newTask->GetID() != 0)
            indices[newTask->GetID()] = pnew;
        return pnew;
    }

    CTaskManager::ExTaskPtr CTaskManager::AddTask(CExclusiveTaskBase *newTask)
    {
        if (newTask->GetID() != 0){
            RemoveTaskByID(newTask->GetID());
        }

        auto pext = std::shared_ptr<CExclusiveTaskBase>(newTask);

        //r^XNƂAdd
        //ExecuteȂ̂ŁA|C^ۑ̂
        if (exNext){
            OutputLog("ALERT r^XN2ȏAddꂽ : %s / %s",
                typeid(*exNext).name(), typeid(*newTask).name());
        }
        exNext = std::move(pext);

        return exNext;
    }

    CTaskManager::BgTaskPtr CTaskManager::AddTask(CBackgroundTaskBase *newTask)
    {
        if (newTask->GetID() != 0){
            RemoveTaskByID(newTask->GetID());
        }

        bg_tasks.emplace_back(newTask);
        auto& pbgt = std::dynamic_pointer_cast<CBackgroundTaskBase>(bg_tasks.back());

        //풓^XNƂAdd
        pbgt->Initialize();
        if (newTask->GetID() != 0)
            bg_indices[newTask->GetID()] = pbgt;
        return pbgt;
    }

    void CTaskManager::Execute(unsigned int time)
    {
        TaskList::iterator i, ied;
        std::list<TaskList::iterator> deleteList;
        std::list<TaskList::iterator>::iterator idl, idl_ed;

#ifdef ARRAYBOUNDARY_DEBUG
        if(!AfxCheckMemory()){
            OutputLog("AfxCheckMemory() failed");
            return;
        }
#endif

        //r^XNAtop̂Execute
        if (ex_stack.size() != 0){
            std::shared_ptr<CExclusiveTaskBase> exTsk = ex_stack.top();
            bool ex_ret = true;
#ifdef _CATCH_WHILE_EXEC
            try{
#endif
                ex_ret = exTsk->Execute(time);
#ifdef _CATCH_WHILE_EXEC
            }catch(...){
                if (ex_stack.top() == NULL)OutputLog("catch while execute3 : NULL", SYSLOG_ERROR);
                else OutputLog("catch while execute3 : %X %s",ex_stack.top(),typeid(*ex_stack.top()).name());
            }
#endif

            if (!ex_ret)
            {
                if (!exNext){
                    //ݔr^XN̕ύX

#ifdef _CATCH_WHILE_EXEC
                    try{
#endif

                        //ʏ^XNSĔj
                        i = tasks.begin();
                        ied = tasks.end();
                        for (; i != ied; i++){
                            (*i)->Terminate();
                        }
                        tasks.clear();

#ifdef _CATCH_WHILE_EXEC
                    }catch(...){
                        if ((*i) == NULL)OutputLog("catch while terminate1 : NULL", SYSLOG_ERROR);
                        else OutputLog("catch while terminate1 : %X %s", (*i), typeid(*(*i)).name());
                    }
#endif

                    unsigned int prvID;

#ifdef _CATCH_WHILE_EXEC
                    try{
#endif

                        //ݔr^XN̔j
                        prvID = exTsk->GetID();
                        exTsk->Terminate();
                        exTsk = nullptr;
                        ex_stack.pop();

#ifdef _CATCH_WHILE_EXEC
                    }catch(...){
                        if (exTsk == NULL)OutputLog("catch while terminate2 : NULL", SYSLOG_ERROR);
                        else OutputLog("catch while terminate : %X %s", exTsk, typeid(*exTsk).name());
                    }
#endif

#ifdef _CATCH_WHILE_EXEC
                    try{
#endif

                        //̔r^XNActivate
                        if (ex_stack.size() == 0)return;
                        exTsk = ex_stack.top();
                        exTsk->Activate(prvID);

#ifdef _CATCH_WHILE_EXEC
                    }catch(...){
                        if (exTsk == NULL)OutputLog("catch while activate : NULL", SYSLOG_ERROR);
                        else OutputLog("catch while activate : %X %s", exTsk, typeid(*exTsk).name());
                    }
#endif

                    return;
                }
            }
        }

        //ʏ^XNExecute
        i = tasks.begin();
        ied = tasks.end();
        for (; i != ied; i++){
#ifdef _CATCH_WHILE_EXEC
            try{
#endif
                if ((*i)->Execute(time) == false)
                {
                    deleteList.push_back(i);
                }
#ifdef _CATCH_WHILE_EXEC
            }catch(...){
                if(*i==NULL)OutputLog("catch while execute1 : NULL",SYSLOG_ERROR);
                else OutputLog("catch while execute1 : %X , %s",*i,typeid(**i).name());
                break;
            }
#endif
        }
        //ʏ^XNfalseԂ̂
        if (deleteList.size() != 0){
            idl = deleteList.begin();
            idl_ed = deleteList.end();
            for (; idl != idl_ed; idl++){
                i = *idl;
                (*i)->Terminate();
                tasks.erase(i);
            }
            deleteList.clear();
        }

        //풓^XNExecute
        i = bg_tasks.begin();
        ied = bg_tasks.end();
        for (; i != ied; i++)
        {
#ifdef _CATCH_WHILE_EXEC
            try{
#endif
                if ((*i)->Execute(time) == false){
                    deleteList.push_back(i);
                }
#ifdef _CATCH_WHILE_EXEC
            }catch(...){
                if(*i==NULL)OutputLog("catch while execute2 : NULL",SYSLOG_ERROR);
                else OutputLog("catch while execute2 : %X %s",*i,typeid(**i).name());
            }
#endif
        }
        //풓^XNfalseԂ̂
        if (deleteList.size() != 0){
            idl = deleteList.begin();
            idl_ed = deleteList.end();
            for (; idl != idl_ed; idl++){
                i = *idl;
                (*i)->Terminate();
                bg_tasks.erase(i);
            }
            deleteList.clear();
        }

        // V^XNꍇ
        if (exNext){
            //ʏ^XNSĔj
            CleanupAllSubTasks();

            //ݔr^XNInactivate
            if (ex_stack.size() != 0){
                auto exTsk = ex_stack.top();
                if (!exTsk->Inactivate(exNext->GetID())){
                    exTsk->Terminate();
                    ex_stack.pop();
                }
            }

            //Addꂽ^XNInitializeē˂
            ex_stack.push(exNext);
            exNext->Initialize();

            exNext = nullptr;
        }
    }

    void CTaskManager::Draw()
    {
        TaskList::iterator i, ied;

        assert(tmplist.empty());
        tmplist.reserve(tasks.size());

        //ʏ^XNDraw
        i = tasks.begin();
        ied = tasks.end();
        for (; i != ied; i++){
            if ((*i)->GetDrawPriority() >= 0){
                tmplist.push_back(*i);
            }
        }

        //obNOEh^XNDraw
        i = bg_tasks.begin();
        ied = bg_tasks.end();
        for (; i != ied; i++){
            if ((*i)->GetDrawPriority() >= 0){
                tmplist.push_back(*i);
            }
        }

        //r^XNDraw
        if (ex_stack.size() != 0){
            if (ex_stack.top()->GetDrawPriority() >= 0){
                tmplist.push_back(ex_stack.top());
            }
        }

        std::sort(tmplist.begin(), tmplist.end(), CompByDrawPriority);//`vCIeBɃ\[g

        //`
        auto iv = tmplist.begin();
        auto iedv = tmplist.end();
        for (; iv != iedv; iv++)
        {
#ifdef _CATCH_WHILE_RENDER
            try{
#endif
                (*iv)->Draw();
#ifdef _CATCH_WHILE_RENDER
            }catch(...){
                OutputLog("catch while draw : %X %s", *iv, typeid(**iv).name());
            }
#endif
        }

        // ꎞXgj
        tmplist.clear();
    }

    void CTaskManager::RemoveTaskByID(unsigned int id)
    {
        TaskList::iterator i, ied;

        //ʏ^XN`FbN
        if (!tasks.empty())
        {
            i = tasks.begin();
            ied = tasks.end();
            for (; i != ied; i++){
                if (id == (*i)->GetID()){
                    (*i)->Terminate();
                    tasks.erase(i);
                    return;
                }
            }
        }

        //obNOEh^XNTerminate
        if (!bg_tasks.empty())
        {
            i = bg_tasks.begin();
            ied = bg_tasks.end();
            for (; i != ied; i++){
                if (id == (*i)->GetID()){
                    (*i)->Terminate();
                    bg_tasks.erase(i);
                    return;
                }
            }
        }
    }

    //ŏʂɂGNXN[Vu^XNQg
    CTaskManager::ExTaskPtr CTaskManager::GetTopExclusiveTask()
    {
        if (ex_stack.size() == 0)return ExTaskPtr();
        return ex_stack.top();
    }

    //wID̔r^XN܂Terminate/pop
    void CTaskManager::ReturnExclusiveTaskByID(unsigned int id)
    {
        bool act = false;
        unsigned int previd = 0;

        while (ex_stack.size() != 0){
            std::shared_ptr<CExclusiveTaskBase> task = ex_stack.top();
            if (task->GetID() == id){
                if (act){
                    task->Activate(previd);
                }
                return;
            }
            else{
                previd = task->GetID();
                act = true;
                CleanupAllSubTasks();
                task->Terminate();
                ex_stack.pop();
            }
        }
    }

    //ʏ^XNSĔj
    void CTaskManager::CleanupAllSubTasks()
    {
        std::shared_ptr<CTaskBase> delTgt;
        TaskList::iterator i, ied;

        i = tasks.begin();
        ied = tasks.end();
        for (; i != ied; i++){
            delTgt = (*i);
            delTgt->Terminate();
        }
        tasks.clear();
    }

    //fobOE^XNꗗ\
    void CTaskManager::DebugOutputTaskList()
    {
        OutputLog("\n\nCTaskManager::DebugOutputTaskList() - start");

        TaskList::iterator i, ied;

        OutputLog("ʏ^XNꗗ");
        //ʏ^XN
        i = tasks.begin();
        ied = tasks.end();
        for (; i != ied; i++){
            OutputLog(typeid(**i).name());
        }

        OutputLog("풓^XNꗗ");
        //obNOEh^XN
        i = bg_tasks.begin();
        ied = bg_tasks.end();
        for (; i != ied; i++){
            OutputLog(typeid(**i).name());
        }

        //r^XN
        OutputLog("\n");
        OutputLog("݂̃^XNF");
        if (ex_stack.empty())
            OutputLog("Ȃ");
        else
            OutputLog(typeid(*ex_stack.top()).name());

        OutputLog("\n\nCTaskManager::DebugOutputTaskList() - end\n\n");
    }

    //SȂȂA΂
    bool CTaskManager::ExEmpty()
    {
        return (ex_stack.size() == 0) ? true : false;
    }

}
<commit_msg>排他タスの追加を最適化<commit_after>

/*============================================================================

    ^XNǗ(?)

==============================================================================*/

#include <cassert>
#include <algorithm>
#include <typeinfo>
#include "task.h"

namespace GTF
{

    CTaskManager::CTaskManager()
    {
        exNext = nullptr;
    }

    void CTaskManager::Destroy()
    {
        TaskList::iterator i, ied;

        //ʏ^XNTerminate
        i = tasks.begin();
        ied = tasks.end();
        for (; i != ied; i++){
            (*i)->Terminate();
        }
        tasks.clear();

        //obNOEh^XNTerminate
        i = bg_tasks.begin();
        ied = bg_tasks.end();
        for (; i != ied; i++){
            (*i)->Terminate();
        }
        bg_tasks.clear();

        //r^XNTerminate
        while (ex_stack.size() != 0){
            ex_stack.top()->Terminate();
            ex_stack.pop();
        }
    }

    CTaskManager::TaskPtr CTaskManager::AddTask(CTaskBase *newTask)
    {
        if (newTask->GetID() != 0){
            RemoveTaskByID(newTask->GetID());
        }

        CBackgroundTaskBase *pbgt = dynamic_cast<CBackgroundTaskBase*>(newTask);
        if (pbgt){
            //풓^XNƂAdd
            return AddTask(pbgt);
        }

        CExclusiveTaskBase *pext = dynamic_cast<CExclusiveTaskBase*>(newTask);
        if (pext){
            //r^XNƂAdd
            return AddTask(pext);
        }

        //ʏ^XNƂAdd
        tasks.emplace_back(newTask);
        auto& pnew = tasks.back();
        newTask->Initialize();
        if (newTask->GetID() != 0)
            indices[newTask->GetID()] = pnew;
        return pnew;
    }

    CTaskManager::ExTaskPtr CTaskManager::AddTask(CExclusiveTaskBase *newTask)
    {
        if (newTask->GetID() != 0){
            RemoveTaskByID(newTask->GetID());
        }

        //r^XNƂAdd
        //ExecuteȂ̂ŁA|C^ۑ̂
        if (exNext){
            OutputLog("ALERT r^XN2ȏAddꂽ : %s / %s",
                typeid(*exNext).name(), typeid(*newTask).name());
        }
        exNext = std::move(std::shared_ptr<CExclusiveTaskBase>(newTask));

        return exNext;
    }

    CTaskManager::BgTaskPtr CTaskManager::AddTask(CBackgroundTaskBase *newTask)
    {
        if (newTask->GetID() != 0){
            RemoveTaskByID(newTask->GetID());
        }

        bg_tasks.emplace_back(newTask);
        auto& pbgt = std::dynamic_pointer_cast<CBackgroundTaskBase>(bg_tasks.back());

        //풓^XNƂAdd
        pbgt->Initialize();
        if (newTask->GetID() != 0)
            bg_indices[newTask->GetID()] = pbgt;
        return pbgt;
    }

    void CTaskManager::Execute(unsigned int time)
    {
        TaskList::iterator i, ied;
        std::list<TaskList::iterator> deleteList;
        std::list<TaskList::iterator>::iterator idl, idl_ed;

#ifdef ARRAYBOUNDARY_DEBUG
        if(!AfxCheckMemory()){
            OutputLog("AfxCheckMemory() failed");
            return;
        }
#endif

        //r^XNAtop̂Execute
        if (ex_stack.size() != 0){
            std::shared_ptr<CExclusiveTaskBase> exTsk = ex_stack.top();
            bool ex_ret = true;
#ifdef _CATCH_WHILE_EXEC
            try{
#endif
                ex_ret = exTsk->Execute(time);
#ifdef _CATCH_WHILE_EXEC
            }catch(...){
                if (ex_stack.top() == NULL)OutputLog("catch while execute3 : NULL", SYSLOG_ERROR);
                else OutputLog("catch while execute3 : %X %s",ex_stack.top(),typeid(*ex_stack.top()).name());
            }
#endif

            if (!ex_ret)
            {
                if (!exNext){
                    //ݔr^XN̕ύX

#ifdef _CATCH_WHILE_EXEC
                    try{
#endif

                        //ʏ^XNSĔj
                        i = tasks.begin();
                        ied = tasks.end();
                        for (; i != ied; i++){
                            (*i)->Terminate();
                        }
                        tasks.clear();

#ifdef _CATCH_WHILE_EXEC
                    }catch(...){
                        if ((*i) == NULL)OutputLog("catch while terminate1 : NULL", SYSLOG_ERROR);
                        else OutputLog("catch while terminate1 : %X %s", (*i), typeid(*(*i)).name());
                    }
#endif

                    unsigned int prvID;

#ifdef _CATCH_WHILE_EXEC
                    try{
#endif

                        //ݔr^XN̔j
                        prvID = exTsk->GetID();
                        exTsk->Terminate();
                        exTsk = nullptr;
                        ex_stack.pop();

#ifdef _CATCH_WHILE_EXEC
                    }catch(...){
                        if (exTsk == NULL)OutputLog("catch while terminate2 : NULL", SYSLOG_ERROR);
                        else OutputLog("catch while terminate : %X %s", exTsk, typeid(*exTsk).name());
                    }
#endif

#ifdef _CATCH_WHILE_EXEC
                    try{
#endif

                        //̔r^XNActivate
                        if (ex_stack.size() == 0)return;
                        exTsk = ex_stack.top();
                        exTsk->Activate(prvID);

#ifdef _CATCH_WHILE_EXEC
                    }catch(...){
                        if (exTsk == NULL)OutputLog("catch while activate : NULL", SYSLOG_ERROR);
                        else OutputLog("catch while activate : %X %s", exTsk, typeid(*exTsk).name());
                    }
#endif

                    return;
                }
            }
        }

        //ʏ^XNExecute
        i = tasks.begin();
        ied = tasks.end();
        for (; i != ied; i++){
#ifdef _CATCH_WHILE_EXEC
            try{
#endif
                if ((*i)->Execute(time) == false)
                {
                    deleteList.push_back(i);
                }
#ifdef _CATCH_WHILE_EXEC
            }catch(...){
                if(*i==NULL)OutputLog("catch while execute1 : NULL",SYSLOG_ERROR);
                else OutputLog("catch while execute1 : %X , %s",*i,typeid(**i).name());
                break;
            }
#endif
        }
        //ʏ^XNfalseԂ̂
        if (deleteList.size() != 0){
            idl = deleteList.begin();
            idl_ed = deleteList.end();
            for (; idl != idl_ed; idl++){
                i = *idl;
                (*i)->Terminate();
                tasks.erase(i);
            }
            deleteList.clear();
        }

        //풓^XNExecute
        i = bg_tasks.begin();
        ied = bg_tasks.end();
        for (; i != ied; i++)
        {
#ifdef _CATCH_WHILE_EXEC
            try{
#endif
                if ((*i)->Execute(time) == false){
                    deleteList.push_back(i);
                }
#ifdef _CATCH_WHILE_EXEC
            }catch(...){
                if(*i==NULL)OutputLog("catch while execute2 : NULL",SYSLOG_ERROR);
                else OutputLog("catch while execute2 : %X %s",*i,typeid(**i).name());
            }
#endif
        }
        //풓^XNfalseԂ̂
        if (deleteList.size() != 0){
            idl = deleteList.begin();
            idl_ed = deleteList.end();
            for (; idl != idl_ed; idl++){
                i = *idl;
                (*i)->Terminate();
                bg_tasks.erase(i);
            }
            deleteList.clear();
        }

        // V^XNꍇ
        if (exNext){
            //ʏ^XNSĔj
            CleanupAllSubTasks();

            //ݔr^XNInactivate
            if (ex_stack.size() != 0){
                auto exTsk = ex_stack.top();
                if (!exTsk->Inactivate(exNext->GetID())){
                    exTsk->Terminate();
                    ex_stack.pop();
                }
            }

            //Addꂽ^XNInitializeē˂
            ex_stack.push(exNext);
            exNext->Initialize();

            exNext = nullptr;
        }
    }

    void CTaskManager::Draw()
    {
        TaskList::iterator i, ied;

        assert(tmplist.empty());
        tmplist.reserve(tasks.size());

        //ʏ^XNDraw
        i = tasks.begin();
        ied = tasks.end();
        for (; i != ied; i++){
            if ((*i)->GetDrawPriority() >= 0){
                tmplist.push_back(*i);
            }
        }

        //obNOEh^XNDraw
        i = bg_tasks.begin();
        ied = bg_tasks.end();
        for (; i != ied; i++){
            if ((*i)->GetDrawPriority() >= 0){
                tmplist.push_back(*i);
            }
        }

        //r^XNDraw
        if (ex_stack.size() != 0){
            if (ex_stack.top()->GetDrawPriority() >= 0){
                tmplist.push_back(ex_stack.top());
            }
        }

        std::sort(tmplist.begin(), tmplist.end(), CompByDrawPriority);//`vCIeBɃ\[g

        //`
        auto iv = tmplist.begin();
        auto iedv = tmplist.end();
        for (; iv != iedv; iv++)
        {
#ifdef _CATCH_WHILE_RENDER
            try{
#endif
                (*iv)->Draw();
#ifdef _CATCH_WHILE_RENDER
            }catch(...){
                OutputLog("catch while draw : %X %s", *iv, typeid(**iv).name());
            }
#endif
        }

        // ꎞXgj
        tmplist.clear();
    }

    void CTaskManager::RemoveTaskByID(unsigned int id)
    {
        TaskList::iterator i, ied;

        //ʏ^XN`FbN
        if (!tasks.empty())
        {
            i = tasks.begin();
            ied = tasks.end();
            for (; i != ied; i++){
                if (id == (*i)->GetID()){
                    (*i)->Terminate();
                    tasks.erase(i);
                    return;
                }
            }
        }

        //obNOEh^XNTerminate
        if (!bg_tasks.empty())
        {
            i = bg_tasks.begin();
            ied = bg_tasks.end();
            for (; i != ied; i++){
                if (id == (*i)->GetID()){
                    (*i)->Terminate();
                    bg_tasks.erase(i);
                    return;
                }
            }
        }
    }

    //ŏʂɂGNXN[Vu^XNQg
    CTaskManager::ExTaskPtr CTaskManager::GetTopExclusiveTask()
    {
        if (ex_stack.size() == 0)return ExTaskPtr();
        return ex_stack.top();
    }

    //wID̔r^XN܂Terminate/pop
    void CTaskManager::ReturnExclusiveTaskByID(unsigned int id)
    {
        bool act = false;
        unsigned int previd = 0;

        while (ex_stack.size() != 0){
            std::shared_ptr<CExclusiveTaskBase> task = ex_stack.top();
            if (task->GetID() == id){
                if (act){
                    task->Activate(previd);
                }
                return;
            }
            else{
                previd = task->GetID();
                act = true;
                CleanupAllSubTasks();
                task->Terminate();
                ex_stack.pop();
            }
        }
    }

    //ʏ^XNSĔj
    void CTaskManager::CleanupAllSubTasks()
    {
        std::shared_ptr<CTaskBase> delTgt;
        TaskList::iterator i, ied;

        i = tasks.begin();
        ied = tasks.end();
        for (; i != ied; i++){
            delTgt = (*i);
            delTgt->Terminate();
        }
        tasks.clear();
    }

    //fobOE^XNꗗ\
    void CTaskManager::DebugOutputTaskList()
    {
        OutputLog("\n\nCTaskManager::DebugOutputTaskList() - start");

        TaskList::iterator i, ied;

        OutputLog("ʏ^XNꗗ");
        //ʏ^XN
        i = tasks.begin();
        ied = tasks.end();
        for (; i != ied; i++){
            OutputLog(typeid(**i).name());
        }

        OutputLog("풓^XNꗗ");
        //obNOEh^XN
        i = bg_tasks.begin();
        ied = bg_tasks.end();
        for (; i != ied; i++){
            OutputLog(typeid(**i).name());
        }

        //r^XN
        OutputLog("\n");
        OutputLog("݂̃^XNF");
        if (ex_stack.empty())
            OutputLog("Ȃ");
        else
            OutputLog(typeid(*ex_stack.top()).name());

        OutputLog("\n\nCTaskManager::DebugOutputTaskList() - end\n\n");
    }

    //SȂȂA΂
    bool CTaskManager::ExEmpty()
    {
        return (ex_stack.size() == 0) ? true : false;
    }

}
<|endoftext|>