<commit_before>
#include "ev3api.h"
#include "Clock.h"
#include "app.h"
#include "SerialData.h"
#include "SerialSendTask.h"
#include "SerialReceiveTask.h"
#include "InOutManager.h"
#include "Strategy.h"
#include "StrategyManager.h"
#include "BlockMoveStrategy.h"
#include "ETSumoStrategy.h"
#include "SelfPositionManager.h"
#include "BlockMoveManager.h"
#include "SoundPlayTask.h"
#include "HSLColor.h"
#include "FieldMap.h"

using ev3api::Clock;

// C++からC言語ライブラリをインクルードするため
extern "C"{
	#include "image.h"
}

//#include "libcpp-test.h"

#define DEBUG

#ifdef DEBUG
#define _debug(x) (x)
#else
#define _debug(x)
#endif

imageData_t* image;
uint32_t sleepTime = 0;

void Draw()
{
    static char buf[256];

    InOutManager* IOManager = InOutManager::GetInstance();

    sprintf(buf, "Power: %4d, %4d, S:%d",IOManager->OutputData.LeftMotorPower, IOManager->OutputData.RightMotorPower, sleepTime);
    ev3_lcd_draw_string(buf, 0, 0);

    SelfPositionManager* SpManager = SelfPositionManager::GetInstance();
    sprintf(buf, "X:%4.1f, Y:%5.1f. A:%3.1f ",SpManager->RobotPoint.X, SpManager->RobotPoint.Y, SpManager->RobotAngle);
    ev3_lcd_draw_string(buf, 0, 12);

    sprintf(buf, "P: %2.1f, D: %4.1f  ", CurrentPID.PGain, CurrentPID.DGain);
    ev3_lcd_draw_string(buf, 0, 24);

    BlockMoveManager * BmManager = BlockMoveManager::GetInstance();
    sprintf(buf, "C:%d src:%2d, dst:%2d, Ang:%3d ",
        BmManager->CurrentCommand.BlockColor,
        BmManager->CurrentCommand.SourceBlockPosition,
        BmManager->CurrentCommand.DestinationBlockPosition,
        BmManager->GetSrcWaypointAngle(SpManager->RobotPoint.X, SpManager->RobotPoint.Y));
    ev3_lcd_draw_string(buf, 0, 36);

    auto src = BmManager->GetSrcWaypoint();
    sprintf(buf, "W* No:%d srcX:%2d, srcY:%2d  ",
        BmManager->CurrentCommand.ApproachWayPoint[BmManager->CurrentSrcWaypointNo],
        (int)src->X,
        (int)src->Y);
    ev3_lcd_draw_string(buf, 0, 48);

    RGBColor rgbMap = FieldMap::GetInstance()->GetRGBColor(
                            SpManager->RobotPoint.X, SpManager->RobotPoint.Y);
    HSLColor hslMap = HSLColor::FromRGB(rgbMap.R, rgbMap.G, rgbMap.B);

    sprintf(buf, "MAP-H:%3.2f,S:%3.2f,L%3.2f",
        hslMap.Hue,
        hslMap.Saturation,
        hslMap.Luminosity);
    ev3_lcd_draw_string(buf, 0, 60);

    sprintf(buf, "SEN-H:%3.2f,S:%3.2f,L%3.2f " ,IOManager->HSLValue.Hue,
                                                IOManager->HSLValue.Saturation,
                                                IOManager->HSLValue.Luminosity);
    ev3_lcd_draw_string(buf, 0, 72);

    sprintf(buf, "LFood: %1.4f", ColorDecision::GetLikelihoodLuminosity(hslMap.Luminosity, IOManager->HSLValue.Luminosity));
    ev3_lcd_draw_string(buf, 0, 84);

}

void Refresh()
{
    InOutManager* IOManager = InOutManager::GetInstance();
    IOManager->ReadInputSensor();

    SelfPositionManager* SpManager = SelfPositionManager::GetInstance();
    SpManager->UpdatePosition(IOManager->InputData.LeftMotorAngle, IOManager->InputData.RightMotorAngle);
    Draw();
}

void main_task(intptr_t unused)
{
    PlaySound(SensorInitialStart);
    InOutManager* IOManager = InOutManager::GetInstance();
    FieldMap * Map = FieldMap::GetInstance();
    Map->ReadImage("/ev3rt/image/Field.bmp");

    StrategyManager *StManager = new StrategyManager();
    PlaySound(SensorInitialEnd);

RESTART_:
    // 初期位置
    SelfPositionData pData;
/*
    pData.Angle = 0;
    pData.PositionX = 1360;
    pData.PositionY = 2900;
*/
    // 初期位置（ライントレース）
    pData.Angle = 270;
    pData.PositionX = 5190;
    pData.PositionY = 380;

    SelfPositionManager* SpManager = SelfPositionManager::GetInstance();
    SpManager->ResetPosition(pData);

    int i = 0;
    while(IOManager->InputData.TouchSensor == 0){
        Refresh();
		dly_tsk(10);
    }

    while(IOManager->InputData.TouchSensor == 1){
        Refresh();
		dly_tsk(10);
    }

    ev3_lcd_fill_rect(0, 0, EV3_LCD_WIDTH, EV3_LCD_HEIGHT,  EV3_LCD_WHITE);

    // StManager->SetStrategy(new BlockMoveStrategy(StManager));

    // ET相撲NEO確認用
//    StManager->SetStrategy(new ETSumoStrategy(StManager));

    // 初期値をラインの中心として格納
    auto lts = new LineTraceStrategy(StManager);
//    lts->CenterValue = IOManager->InputData.ReflectLight;
    lts->CenterValue = 120;

    // ライントレース戦略にて動作開始
    StManager->SetStrategy(lts);
    Clock* clock = new Clock();
    while(1)
    {
        uint32_t baseTime = clock->now();

        // 入力情報更新
        Refresh();

        StManager->Run();

        if(i > 200) {
            i = 0;
            ev3_lcd_fill_rect(0, 0, EV3_LCD_WIDTH, EV3_LCD_HEIGHT,  EV3_LCD_WHITE);
        }

        i++;

        // ボタン押されたらリスタート
        if(IOManager->InputData.TouchSensor == 1){
            IOManager->OutputData.LeftMotorPower = 0;
            IOManager->OutputData.RightMotorPower = 0;
            IOManager->DownARMMotor();
            IOManager->WriteOutputMotor();

            while(IOManager->InputData.TouchSensor == 1) {
                Refresh();
                dly_tsk(10);
            }
            goto RESTART_;
        }
        // 出力情報更新
        IOManager->WriteOutputMotor();
        sleepTime = clock->now() - baseTime;
		dly_tsk(50 - sleepTime);
    }
}
<commit_msg>ログ表示機能を追加<commit_after>
#include "ev3api.h"
#include "Clock.h"
#include "app.h"
#include "SerialData.h"
#include "SerialSendTask.h"
#include "SerialReceiveTask.h"
#include "InOutManager.h"
#include "Strategy.h"
#include "StrategyManager.h"
#include "BlockMoveStrategy.h"
#include "ETSumoStrategy.h"
#include "SelfPositionManager.h"
#include "BlockMoveManager.h"
#include "SoundPlayTask.h"
#include "HSLColor.h"
#include "FieldMap.h"

using ev3api::Clock;

// C++からC言語ライブラリをインクルードするため
extern "C"{
	#include "image.h"
}

//#include "libcpp-test.h"

#define DEBUG

#ifdef DEBUG
#define _debug(x) (x)
#else
#define _debug(x)
#endif

imageData_t* image;
uint32_t sleepTime = 0;

void Draw()
{
    static char buf[256];

    InOutManager* IOManager = InOutManager::GetInstance();

    sprintf(buf, "Power: %4d, %4d, S:%d ",IOManager->OutputData.LeftMotorPower, IOManager->OutputData.RightMotorPower, sleepTime);
    ev3_lcd_draw_string(buf, 0, 0);

    SelfPositionManager* SpManager = SelfPositionManager::GetInstance();
    sprintf(buf, "X:%4.1f, Y:%5.1f. A:%3.1f ",SpManager->RobotPoint.X, SpManager->RobotPoint.Y, SpManager->RobotAngle);
    ev3_lcd_draw_string(buf, 0, 12);

    sprintf(buf, "P: %2.1f, D: %4.1f  ", CurrentPID.PGain, CurrentPID.DGain);
    ev3_lcd_draw_string(buf, 0, 24);

    BlockMoveManager * BmManager = BlockMoveManager::GetInstance();
    sprintf(buf, "C:%d src:%2d, dst:%2d, Ang:%3d ",
        BmManager->CurrentCommand.BlockColor,
        BmManager->CurrentCommand.SourceBlockPosition,
        BmManager->CurrentCommand.DestinationBlockPosition,
        BmManager->GetSrcWaypointAngle(SpManager->RobotPoint.X, SpManager->RobotPoint.Y));
    ev3_lcd_draw_string(buf, 0, 36);

    auto src = BmManager->GetSrcWaypoint();
    sprintf(buf, "W* No:%d srcX:%2d, srcY:%2d  ",
        BmManager->CurrentCommand.ApproachWayPoint[BmManager->CurrentSrcWaypointNo],
        (int)src->X,
        (int)src->Y);
    ev3_lcd_draw_string(buf, 0, 48);

    RGBColor rgbMap = FieldMap::GetInstance()->GetRGBColor(
                            SpManager->RobotPoint.X, SpManager->RobotPoint.Y);
    HSLColor hslMap = HSLColor::FromRGB(rgbMap.R, rgbMap.G, rgbMap.B);

    sprintf(buf, "MAP-H:%3.2f,S:%3.2f,L%3.2f",
        hslMap.Hue,
        hslMap.Saturation,
        hslMap.Luminosity);
    ev3_lcd_draw_string(buf, 0, 60);

    sprintf(buf, "SEN-H:%3.2f,S:%3.2f,L%3.2f " ,IOManager->HSLValue.Hue,
                                                IOManager->HSLValue.Saturation,
                                                IOManager->HSLValue.Luminosity);
    ev3_lcd_draw_string(buf, 0, 72);

    sprintf(buf, "LFood: %1.4f", ColorDecision::GetLikelihoodLuminosity(hslMap.Luminosity, IOManager->HSLValue.Luminosity));
    ev3_lcd_draw_string(buf, 0, 84);

}

void Refresh()
{
    InOutManager* IOManager = InOutManager::GetInstance();
    IOManager->ReadInputSensor();

    SelfPositionManager* SpManager = SelfPositionManager::GetInstance();
    SpManager->UpdatePosition(IOManager->InputData.LeftMotorAngle, IOManager->InputData.RightMotorAngle);
    Draw();
}

void main_task(intptr_t unused)
{
    PlaySound(SensorInitialStart);
    InOutManager* IOManager = InOutManager::GetInstance();
    FieldMap * Map = FieldMap::GetInstance();
    Map->ReadImage("/ev3rt/image/Field.bmp");
    StrategyManager *StManager = new StrategyManager();
    PlaySound(SensorInitialEnd);

RESTART_:
    // 初期位置
    SelfPositionData pData;
/*
    pData.Angle = 0;
    pData.PositionX = 1360;
    pData.PositionY = 2900;
*/
    // 初期位置（ライントレース）
    pData.Angle = 270;
    pData.PositionX = 5190;
    pData.PositionY = 380;

    SelfPositionManager* SpManager = SelfPositionManager::GetInstance();
    SpManager->ResetPosition(pData);

    int i = 0;
    while(IOManager->InputData.TouchSensor == 0){
        Refresh();
		dly_tsk(10);
    }

    while(IOManager->InputData.TouchSensor == 1){
        Refresh();
		dly_tsk(10);
    }

    ev3_lcd_fill_rect(0, 0, EV3_LCD_WIDTH, EV3_LCD_HEIGHT,  EV3_LCD_WHITE);

    // StManager->SetStrategy(new BlockMoveStrategy(StManager));

    // ET相撲NEO確認用
//    StManager->SetStrategy(new ETSumoStrategy(StManager));

    // 初期値をラインの中心として格納
    auto lts = new LineTraceStrategy(StManager);
//    lts->CenterValue = IOManager->InputData.ReflectLight;
    lts->CenterValue = 120;

    // ライントレース戦略にて動作開始
    StManager->SetStrategy(lts);
    Clock* clock = new Clock();
    while(1)
    {
        uint32_t baseTime = clock->now();

        // 入力情報更新
        Refresh();

        StManager->Run();

        if(i > 200) {
            i = 0;
            ev3_lcd_fill_rect(0, 0, EV3_LCD_WIDTH, EV3_LCD_HEIGHT,  EV3_LCD_WHITE);
        }

        i++;

        // ボタン押されたらリスタート
        if(IOManager->InputData.TouchSensor == 1){
            IOManager->OutputData.LeftMotorPower = 0;
            IOManager->OutputData.RightMotorPower = 0;
            IOManager->DownARMMotor();
            IOManager->WriteOutputMotor();

            while(IOManager->InputData.TouchSensor == 1) {
                Refresh();
                dly_tsk(10);
            }
            goto RESTART_;
        }
        // 出力情報更新
        IOManager->WriteOutputMotor();
        sleepTime = clock->now() - baseTime;
		dly_tsk(50 - sleepTime);
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 BrewPi/Elco Jacobs/Matthew McGowan.
 *
 * This file is part of BrewPi.
 *
 * BrewPi is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * BrewPi is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with BrewPi.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "Brewpi.h"
#include "fixstl.h"
#include "UI.h"
#include "Buzzer.h"
#include "eGuiSettings.h"
#include "ConnectedDevicesManager.h"
#include "PiLink.h"
#include "Display.h"
#include "UIController.h"
#include "Actuator.h"
#include "Board.h"

#include "../eGUI_screens/devicetest/device_test_screen.h"
#include "../eGUI_screens/controller/controller_screen.h"
#include "../eGUI_screens/startup/startup_screen.h"
#include "../eGUI_screens/screen_model.h"

extern "C" {
#include "d4d.h"
}

DisplayType realDisplay;
DisplayType DISPLAY_REF display = realDisplay;

eGuiSettingsClass eGuiSettings;

uint8_t UI::init() {
    eGuiSettings.init();
    display.init();

    if (!D4D_Init(NULL))
        return 1;

    D4D_SetOrientation(D4D_ORIENT_LANDSCAPE);
    #if BREWPI_BUZZER
	buzzer.init(!shieldIsV2());
	buzzer.beep(2, 100);
    #endif

    return 0;
}

uint32_t UI::showStartupPage()
{
    // Check if touch screen has been calibrated
    if (!eGuiSettings.loadTouchCalib()) {
        // could not load valid settings from flash memory
        calibrateTouchScreen();
    }

    uiController.beginStartup();
    return 0;
}

/**
 * Since the startup page waits for the user, it has variable duration. This allows
 * the main loop to continue running while the startup screen is displayed.
 */
void UI::showControllerPage() {
    display.printStationaryText();
    display.printState();
}

extern ValueActuator alarm;
void UI::ticks()
{
    D4D_TimeTickPut();
    D4D_CheckTouchScreen();
    D4D_Poll();

    #if BREWPI_BUZZER
	buzzer.setActive(alarm.isActive() && !buzzer.isActive());
    #endif
}

UIController uiController;

void UI::update()
{
    uiController.updateScreen();

    display.printState();
    display.printAllTemperatures();
    display.printMode();
    display.updateBacklight();
}

Timer* timer = nullptr;

void cancelCalibration()
{
    D4D_InterruptCalibrationScreen();
}

void createTimer()
{
    timer = new Timer(3*1000, cancelCalibration);
    if (timer)
        timer->start();
}

void destroyTimer()
{
    delete timer;
    timer = NULL;
}

/**
 * Show touch screen calibration screen store settings afterwards
 */
void calibrateTouchScreen() {

    createTimer();
    D4D_CalibrateTouchScreen();
    destroyTimer();
    eGuiSettings.storeTouchCalib();

}

bool UI::inStartup() {
    return uiController.inStartup();
}
<commit_msg>increase timeout from 3s to 60s.<commit_after>/*
 * Copyright 2015 BrewPi/Elco Jacobs/Matthew McGowan.
 *
 * This file is part of BrewPi.
 *
 * BrewPi is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * BrewPi is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with BrewPi.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "Brewpi.h"
#include "fixstl.h"
#include "UI.h"
#include "Buzzer.h"
#include "eGuiSettings.h"
#include "ConnectedDevicesManager.h"
#include "PiLink.h"
#include "Display.h"
#include "UIController.h"
#include "Actuator.h"
#include "Board.h"

#include "../eGUI_screens/devicetest/device_test_screen.h"
#include "../eGUI_screens/controller/controller_screen.h"
#include "../eGUI_screens/startup/startup_screen.h"
#include "../eGUI_screens/screen_model.h"

extern "C" {
#include "d4d.h"
}

DisplayType realDisplay;
DisplayType DISPLAY_REF display = realDisplay;

eGuiSettingsClass eGuiSettings;

uint8_t UI::init() {
    eGuiSettings.init();
    display.init();

    if (!D4D_Init(NULL))
        return 1;

    D4D_SetOrientation(D4D_ORIENT_LANDSCAPE);
    #if BREWPI_BUZZER
	buzzer.init(!shieldIsV2());
	buzzer.beep(2, 100);
    #endif

    return 0;
}

uint32_t UI::showStartupPage()
{
    // Check if touch screen has been calibrated
    if (!eGuiSettings.loadTouchCalib()) {
        // could not load valid settings from flash memory
        calibrateTouchScreen();
    }

    uiController.beginStartup();
    return 0;
}

/**
 * Since the startup page waits for the user, it has variable duration. This allows
 * the main loop to continue running while the startup screen is displayed.
 */
void UI::showControllerPage() {
    display.printStationaryText();
    display.printState();
}

extern ValueActuator alarm;
void UI::ticks()
{
    D4D_TimeTickPut();
    D4D_CheckTouchScreen();
    D4D_Poll();

    #if BREWPI_BUZZER
	buzzer.setActive(alarm.isActive() && !buzzer.isActive());
    #endif
}

UIController uiController;

void UI::update()
{
    uiController.updateScreen();

    display.printState();
    display.printAllTemperatures();
    display.printMode();
    display.updateBacklight();
}

Timer* timer = nullptr;

void cancelCalibration()
{
    D4D_InterruptCalibrationScreen();
}

void createTimer()
{
    timer = new Timer(60*1000, cancelCalibration);
    if (timer)
        timer->start();
}

void destroyTimer()
{
    delete timer;
    timer = NULL;
}

/**
 * Show touch screen calibration screen store settings afterwards
 */
void calibrateTouchScreen() {

    createTimer();
    D4D_CalibrateTouchScreen();
    destroyTimer();
    eGuiSettings.storeTouchCalib();

}

bool UI::inStartup() {
    return uiController.inStartup();
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You 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.
 ****************************************************************************/

/**
 * @file
 * @brief Predicate --- Standard Predicate Implementation
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#include <ironbee/predicate/standard_predicate.hpp>

#include <ironbee/predicate/call_factory.hpp>
#include <ironbee/predicate/call_helpers.hpp>
#include <ironbee/predicate/functional.hpp>
#include <ironbee/predicate/merge_graph.hpp>
#include <ironbee/predicate/validate.hpp>

using namespace std;

namespace IronBee {
namespace Predicate {
namespace Standard {

namespace {

const string CALL_NAME_ISLITERAL("isLiteral");
const string CALL_FINISH_ALL("finishAll");
const string CALL_FINISH_SOME("finishAny");

//! Scoped Memory Pool Lite
static ScopedMemoryPoolLite s_mpl;
//! True Value
static const Value c_true_value =
    Value::create_string(s_mpl, ByteString::create(s_mpl, ""));
//! True literal.
static const node_p c_true(new Literal(c_true_value));
//! False literal.
static const node_p c_false(new Literal());

/**
 * Is argument a literal?
 **/
class IsLiteral :
    public Call
{
public:
    //! See Call::name()
    const std::string& name() const
    {
        return CALL_NAME_ISLITERAL;
    }

    /**
     * See Node::transform().
     *
     * Will replace self with true or false based on child.
     **/
    bool transform(
        MergeGraph&        merge_graph,
        const CallFactory& call_factory,
        Environment        environment,
        NodeReporter       reporter
    )
    {
        node_p me = shared_from_this();
        node_p replacement = c_false;
        if (children().front()->is_literal()) {
            replacement = c_true;
        }
        merge_graph.replace(me, replacement);

        return true;
    }

    //! See Node::eval_calculate()
    void eval_calculate(GraphEvalState&, EvalContext) const
    {
        BOOST_THROW_EXCEPTION(
            einval() << errinfo_what(
                "IsLiteral evaluated.  Did you not transform?"
            )
        );
    }

    //! See Node::validate().
    bool validate(NodeReporter reporter) const
    {
        return Validate::n_children(reporter, 1);
    }
};

/**
 * Is argument finished?
 **/
class IsFinished :
    public Functional::Primary
{
public:
    //! Constructor.
    IsFinished() : Functional::Primary(0, 1) {}

protected:
    //! See Functional::Primary::eval_primary().
    void eval_primary(
        MemoryManager                  mm,
        const node_cp&                 me,
        boost::any&                    substate,
        NodeEvalState&                 my_state,
        const Functional::value_vec_t& secondary_args,
        const NodeEvalState&           primary_arg
    ) const
    {
        if (primary_arg.is_finished()) {
            my_state.finish(c_true_value);
        }
    }
};

/**
 * Is primary argument a list longer than specified length.
 **/
class IsLonger :
    public Functional::Primary
{
public:
    //! Constructor.
    IsLonger() : Functional::Primary(0, 2) {}

protected:
    //! See Functional::Base::validate_argument().
    void validate_argument(
        int          n,
        Value        v,
        NodeReporter reporter
    ) const
    {
        if (n == 0) {
            Validate::value_is_type(v, Value::NUMBER, reporter);
        }
    }

    //! See Functional::Primary::eval_primary().
    void eval_primary(
        MemoryManager                  mm,
        const node_cp&                 me,
        boost::any&                    substate,
        NodeEvalState&                 my_state,
        const Functional::value_vec_t& secondary_args,
        const NodeEvalState&           primary_arg
    ) const
    {
        if (! primary_arg.value()) {
            return;
        }
        if (primary_arg.value().type() != Value::LIST) {
            my_state.finish();
            return;
        }
        if (
            primary_arg.value().as_list().size() >
            size_t(secondary_args[0].as_number())
        ) {
            my_state.finish(c_true_value);
            return;
        }
        if (primary_arg.is_finished()) {
            my_state.finish();
        }
    }
};

/**
 * Is argument a list?
 **/
class IsList :
    public Functional::Primary
{
public:
    //! Constructor.
    IsList() : Functional::Primary(0, 1) {}

protected:
    //! See Functional::Primary::eval_primary().
    void eval_primary(
        MemoryManager                  mm,
        const node_cp&                 me,
        boost::any&                    substate,
        NodeEvalState&                 my_state,
        const Functional::value_vec_t& secondary_args,
        const NodeEvalState&           primary_arg
    ) const
    {
        if (! primary_arg.value().is_null()) {
            if (primary_arg.value().type() == Value::LIST) {
                my_state.finish(c_true_value);
            }
            else {
                my_state.finish();
            }
        }
    }
};

/**
 * Finish with the value of the first child that finishes.
 *
 * This is unlike OR in that the requirements are less. A node only need
 * finish, not finish true.
 **/
 class FinishAny :
    public Call
{
public:
    //! See Call:name()
    virtual const std::string& name() const;

    //! See Node::validate()
    virtual bool validate(NodeReporter reporter) const;

    /**
     * If any node is a literal or transformed to finished,
     * this node replaces itself with that node.
     *
     * @sa See Node::trasform()
     */
    virtual bool transform(
        MergeGraph&        merge_graph,
        const CallFactory& call_factory,
        Environment        environment,
        NodeReporter       reporter
    );

protected:
    virtual void eval_calculate(
        GraphEvalState& graph_eval_state,
        EvalContext     context
    ) const;
};

/**
 * Finish with a list of the values. This finishes when all values are finished.
 *
 * This is effectively list.
 **/
 class FinishAll :
    public Call
{
public:
    //! See Call:name()
    virtual const std::string& name() const;

    //! See Node::validate()
    virtual bool validate(NodeReporter reporter) const;

    /**
     * If all nodesa are a literal or transformed to finished,
     * this node replaces itself with a constant list of those values.
     *
     * @sa See Node::trasform()
     */
    virtual bool transform(
        MergeGraph&        merge_graph,
        const CallFactory& call_factory,
        Environment        environment,
        NodeReporter       reporter
    );

protected:

    virtual void eval_initialize(
        GraphEvalState& graph_eval_state,
        EvalContext     context
    ) const;

    virtual void eval_calculate(
        GraphEvalState& graph_eval_state,
        EvalContext     context
    ) const;
};

bool FinishAll::transform(
    MergeGraph&        merge_graph,
    const CallFactory& call_factory,
    Environment        environment,
    NodeReporter       reporter
)
{
    node_p me = shared_from_this();

    if (children().size() == 0) {
        node_p replacement(new Literal());
        merge_graph.replace(me, replacement);
        return true;
    }

    {
        boost::shared_ptr<ScopedMemoryPoolLite> mpl(
            new ScopedMemoryPoolLite()
        );
        IronBee::List<Value> my_value = IronBee::List<Value>::create(*mpl);
        bool replace = true;

        BOOST_FOREACH(const node_p& child, children()) {
            if (! child->is_literal()) {
                replace = false;
                break;
            }
            Value v = literal_value(child);
            my_value.push_back(v);
        }

        if (replace) {
            node_p replacement(new Literal(mpl,
                Value::alias_list(*mpl, my_value)
            ));
            merge_graph.replace(me, replacement);
            return true;
        }
    }

    return false;
}

const std::string& FinishAll::name() const
{
    return CALL_FINISH_ALL;
}

bool FinishAll::validate(NodeReporter reporter) const
{
    return true;
}

void FinishAll::eval_initialize(
    GraphEvalState& graph_eval_state,
    EvalContext     context
) const
{
    NodeEvalState& my_state = graph_eval_state[index()];
    node_list_t::const_iterator last_unfinished = children().begin();
    my_state.state() = last_unfinished;
    my_state.setup_local_list(context.memory_manager());
}

void FinishAll::eval_calculate(
    GraphEvalState& graph_eval_state,
    EvalContext     context
) const
{
    NodeEvalState& my_state = graph_eval_state[index()];

    node_list_t::const_iterator last_unfinished =
        boost::any_cast<node_list_t::const_iterator>(my_state.state());
    while (last_unfinished != children().end()) {
        size_t index = (*last_unfinished)->index();
        graph_eval_state.eval(*last_unfinished, context);
        Value v = graph_eval_state.value((*last_unfinished)->index());
        if (! graph_eval_state.is_finished(index)) {
            break;
        }

        my_state.append_to_list(v);
        ++last_unfinished;
    }

    if (last_unfinished == children().end()) {
        my_state.finish();
    }

    my_state.state() = last_unfinished;
}

bool FinishAny::transform(
    MergeGraph&        merge_graph,
    const CallFactory& call_factory,
    Environment        environment,
    NodeReporter       reporter
)
{
    node_p me = shared_from_this();

    if (children().size() == 0) {
        node_p replacement(new Literal());
        merge_graph.replace(me, replacement);
        return true;
    }

    BOOST_FOREACH(const node_p& child, children()) {
        if (child->is_literal()) {
            node_p c(child);
            merge_graph.replace(me, c);
            return true;
        }
    }

    return false;
}

const std::string& FinishAny::name() const
{
    return CALL_FINISH_SOME;
}

bool FinishAny::validate(NodeReporter reporter) const
{
    return true;
}

void FinishAny::eval_calculate(
    GraphEvalState& graph_eval_state,
    EvalContext     context
) const
{
    for (
        node_list_t::const_iterator i = children().begin();
        i != children().end();
        ++i
    )
    {
        graph_eval_state.eval(*i, context);

        if (graph_eval_state.is_finished((*i)->index())) {
            Value v = graph_eval_state.value((*i)->index());
            NodeEvalState& my_state = graph_eval_state[index()];
            my_state.finish(v);
            return;
        }
    }
}

} // Anonymous

void load_predicate(CallFactory& to)
{
    to
        .add<IsLiteral>()
        .add<FinishAll>()
        .add<FinishAny>()
        .add("isFinished", Functional::generate<IsFinished>)
        .add("isLonger", Functional::generate<IsLonger>)
        .add("isList", Functional::generate<IsList>)
        ;
}

} // Standard
} // Predicate
} // IronBee
<commit_msg>standard_predicate.cpp: FinishAll incorrectly did not attempt to finish nodes past the first-unfinished node. This change corrects that.<commit_after>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You 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.
 ****************************************************************************/

/**
 * @file
 * @brief Predicate --- Standard Predicate Implementation
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#include <ironbee/predicate/standard_predicate.hpp>

#include <ironbee/predicate/call_factory.hpp>
#include <ironbee/predicate/call_helpers.hpp>
#include <ironbee/predicate/functional.hpp>
#include <ironbee/predicate/merge_graph.hpp>
#include <ironbee/predicate/validate.hpp>

using namespace std;

namespace IronBee {
namespace Predicate {
namespace Standard {

namespace {

const string CALL_NAME_ISLITERAL("isLiteral");
const string CALL_FINISH_ALL("finishAll");
const string CALL_FINISH_SOME("finishAny");

//! Scoped Memory Pool Lite
static ScopedMemoryPoolLite s_mpl;
//! True Value
static const Value c_true_value =
    Value::create_string(s_mpl, ByteString::create(s_mpl, ""));
//! True literal.
static const node_p c_true(new Literal(c_true_value));
//! False literal.
static const node_p c_false(new Literal());

/**
 * Is argument a literal?
 **/
class IsLiteral :
    public Call
{
public:
    //! See Call::name()
    const std::string& name() const
    {
        return CALL_NAME_ISLITERAL;
    }

    /**
     * See Node::transform().
     *
     * Will replace self with true or false based on child.
     **/
    bool transform(
        MergeGraph&        merge_graph,
        const CallFactory& call_factory,
        Environment        environment,
        NodeReporter       reporter
    )
    {
        node_p me = shared_from_this();
        node_p replacement = c_false;
        if (children().front()->is_literal()) {
            replacement = c_true;
        }
        merge_graph.replace(me, replacement);

        return true;
    }

    //! See Node::eval_calculate()
    void eval_calculate(GraphEvalState&, EvalContext) const
    {
        BOOST_THROW_EXCEPTION(
            einval() << errinfo_what(
                "IsLiteral evaluated.  Did you not transform?"
            )
        );
    }

    //! See Node::validate().
    bool validate(NodeReporter reporter) const
    {
        return Validate::n_children(reporter, 1);
    }
};

/**
 * Is argument finished?
 **/
class IsFinished :
    public Functional::Primary
{
public:
    //! Constructor.
    IsFinished() : Functional::Primary(0, 1) {}

protected:
    //! See Functional::Primary::eval_primary().
    void eval_primary(
        MemoryManager                  mm,
        const node_cp&                 me,
        boost::any&                    substate,
        NodeEvalState&                 my_state,
        const Functional::value_vec_t& secondary_args,
        const NodeEvalState&           primary_arg
    ) const
    {
        if (primary_arg.is_finished()) {
            my_state.finish(c_true_value);
        }
    }
};

/**
 * Is primary argument a list longer than specified length.
 **/
class IsLonger :
    public Functional::Primary
{
public:
    //! Constructor.
    IsLonger() : Functional::Primary(0, 2) {}

protected:
    //! See Functional::Base::validate_argument().
    void validate_argument(
        int          n,
        Value        v,
        NodeReporter reporter
    ) const
    {
        if (n == 0) {
            Validate::value_is_type(v, Value::NUMBER, reporter);
        }
    }

    //! See Functional::Primary::eval_primary().
    void eval_primary(
        MemoryManager                  mm,
        const node_cp&                 me,
        boost::any&                    substate,
        NodeEvalState&                 my_state,
        const Functional::value_vec_t& secondary_args,
        const NodeEvalState&           primary_arg
    ) const
    {
        if (! primary_arg.value()) {
            return;
        }
        if (primary_arg.value().type() != Value::LIST) {
            my_state.finish();
            return;
        }
        if (
            primary_arg.value().as_list().size() >
            size_t(secondary_args[0].as_number())
        ) {
            my_state.finish(c_true_value);
            return;
        }
        if (primary_arg.is_finished()) {
            my_state.finish();
        }
    }
};

/**
 * Is argument a list?
 **/
class IsList :
    public Functional::Primary
{
public:
    //! Constructor.
    IsList() : Functional::Primary(0, 1) {}

protected:
    //! See Functional::Primary::eval_primary().
    void eval_primary(
        MemoryManager                  mm,
        const node_cp&                 me,
        boost::any&                    substate,
        NodeEvalState&                 my_state,
        const Functional::value_vec_t& secondary_args,
        const NodeEvalState&           primary_arg
    ) const
    {
        if (! primary_arg.value().is_null()) {
            if (primary_arg.value().type() == Value::LIST) {
                my_state.finish(c_true_value);
            }
            else {
                my_state.finish();
            }
        }
    }
};

/**
 * Finish with the value of the first child that finishes.
 *
 * This is unlike OR in that the requirements are less. A node only need
 * finish, not finish true.
 **/
 class FinishAny :
    public Call
{
public:
    //! See Call:name()
    virtual const std::string& name() const;

    //! See Node::validate()
    virtual bool validate(NodeReporter reporter) const;

    /**
     * If any node is a literal or transformed to finished,
     * this node replaces itself with that node.
     *
     * @sa See Node::trasform()
     */
    virtual bool transform(
        MergeGraph&        merge_graph,
        const CallFactory& call_factory,
        Environment        environment,
        NodeReporter       reporter
    );

protected:
    virtual void eval_calculate(
        GraphEvalState& graph_eval_state,
        EvalContext     context
    ) const;
};

/**
 * Finish with a list of the values. This finishes when all values are finished.
 *
 * This is effectively list.
 **/
 class FinishAll :
    public Call
{
public:
    //! See Call:name()
    virtual const std::string& name() const;

    //! See Node::validate()
    virtual bool validate(NodeReporter reporter) const;

    /**
     * If all nodesa are a literal or transformed to finished,
     * this node replaces itself with a constant list of those values.
     *
     * @sa See Node::trasform()
     */
    virtual bool transform(
        MergeGraph&        merge_graph,
        const CallFactory& call_factory,
        Environment        environment,
        NodeReporter       reporter
    );

protected:

    virtual void eval_initialize(
        GraphEvalState& graph_eval_state,
        EvalContext     context
    ) const;

    virtual void eval_calculate(
        GraphEvalState& graph_eval_state,
        EvalContext     context
    ) const;
};

bool FinishAll::transform(
    MergeGraph&        merge_graph,
    const CallFactory& call_factory,
    Environment        environment,
    NodeReporter       reporter
)
{
    node_p me = shared_from_this();

    if (children().size() == 0) {
        node_p replacement(new Literal());
        merge_graph.replace(me, replacement);
        return true;
    }

    {
        boost::shared_ptr<ScopedMemoryPoolLite> mpl(
            new ScopedMemoryPoolLite()
        );
        IronBee::List<Value> my_value = IronBee::List<Value>::create(*mpl);
        bool replace = true;

        BOOST_FOREACH(const node_p& child, children()) {
            if (! child->is_literal()) {
                replace = false;
                break;
            }
            Value v = literal_value(child);
            my_value.push_back(v);
        }

        if (replace) {
            node_p replacement(new Literal(mpl,
                Value::alias_list(*mpl, my_value)
            ));
            merge_graph.replace(me, replacement);
            return true;
        }
    }

    return false;
}

const std::string& FinishAll::name() const
{
    return CALL_FINISH_ALL;
}

bool FinishAll::validate(NodeReporter reporter) const
{
    return true;
}

void FinishAll::eval_initialize(
    GraphEvalState& graph_eval_state,
    EvalContext     context
) const
{
    NodeEvalState& my_state = graph_eval_state[index()];
    node_list_t::const_iterator last_unfinished = children().begin();
    my_state.state() = last_unfinished;
    my_state.setup_local_list(context.memory_manager());
}

void FinishAll::eval_calculate(
    GraphEvalState& graph_eval_state,
    EvalContext     context
) const
{
    NodeEvalState& my_state = graph_eval_state[index()];

    node_list_t::const_iterator last_unfinished = children().end();

    for (
        node_list_t::const_iterator i =
            boost::any_cast<node_list_t::const_iterator>(my_state.state());
        i != children().end();
        ++i
    )
    {
        size_t index = (*i)->index();

        // We may re-check a node that is already done on subsequent evals.
        if (graph_eval_state.is_finished(index)) {
            continue;
        }

        // If the node is not finished, eval it.
        graph_eval_state.eval(*i, context);

        // If the value is finished, record its value.
        if (graph_eval_state.is_finished(index)) {
            Value v = graph_eval_state.value(index);
            my_state.append_to_list(v);
        }
        // If i is not finished and last_unfinished == end, update it.
        else if (last_unfinished == children().end()) {
            last_unfinished = i;
        }
    }

    // If last_unfinished was never updated to an unfinished i, we are done!
    if (last_unfinished == children().end()) {
        my_state.finish();
    }

    // Record where we observed the first unfinished node.
    my_state.state() = last_unfinished;
}

bool FinishAny::transform(
    MergeGraph&        merge_graph,
    const CallFactory& call_factory,
    Environment        environment,
    NodeReporter       reporter
)
{
    node_p me = shared_from_this();

    if (children().size() == 0) {
        node_p replacement(new Literal());
        merge_graph.replace(me, replacement);
        return true;
    }

    BOOST_FOREACH(const node_p& child, children()) {
        if (child->is_literal()) {
            node_p c(child);
            merge_graph.replace(me, c);
            return true;
        }
    }

    return false;
}

const std::string& FinishAny::name() const
{
    return CALL_FINISH_SOME;
}

bool FinishAny::validate(NodeReporter reporter) const
{
    return true;
}

void FinishAny::eval_calculate(
    GraphEvalState& graph_eval_state,
    EvalContext     context
) const
{
    for (
        node_list_t::const_iterator i = children().begin();
        i != children().end();
        ++i
    )
    {
        graph_eval_state.eval(*i, context);

        if (graph_eval_state.is_finished((*i)->index())) {
            Value v = graph_eval_state.value((*i)->index());
            NodeEvalState& my_state = graph_eval_state[index()];
            my_state.finish(v);
            return;
        }
    }
}

} // Anonymous

void load_predicate(CallFactory& to)
{
    to
        .add<IsLiteral>()
        .add<FinishAll>()
        .add<FinishAny>()
        .add("isFinished", Functional::generate<IsFinished>)
        .add("isLonger", Functional::generate<IsLonger>)
        .add("isList", Functional::generate<IsList>)
        ;
}

} // Standard
} // Predicate
} // IronBee
<|endoftext|>


<commit_before>#pragma once

#include <string>

namespace csi{
	// The control sequence introducer string which prefixes every control sequence.
	const std::string prefix = "\033[";

	// Enums for style codes.
	enum class style_code{
		bold = 1,
		italics = 3,
		underlined = 4,
		strikethrough = 9,
		inverse = 7,
		enable_offset = 0, // e.g. bold on is 1 and italics on is 3.
		disable_offset = 20 // e.g. bold off is 21 and italics off is 23.
	};

	// Return a control sequence string which enables a text style.
	std::string enable(style_code style);

	// Return a control sequence string which disables a text style.
	std::string disable(style_code style);

	// Return a control sequence string which enables or disables any text styles.
	std::string style(
		bool bold = false,
		bool italics = false,
		bool underlined = false,
		bool strikethrough = false
	);

	// Enums for color codes.
	enum class color_code{
		none = 9, // The terminal's default colors.
		black = 0,
		red = 1,
		green = 2,
		yellow = 3,
		blue = 4,
		magenta = 5,
		cyan = 6,
		white = 7,
		foreground_offset = 30, // e.g. green foreground is 32.
		background_offset = 40 // e.g. green background is 42.
	};

	// Returns a control sequence string which sets the text color.
	std::string foreground(color_code color = color_code::none);

	// Returns a control sequence string which sets the text background color.
	std::string background(color_code color = color_code::none);

	/* Return a control sequence string which selects foreground and background
	 * text colors.
	 * Additionally, the colors can be inverted to make the text appear
	 * highlighted. */
	std::string color(
		color_code foreground = color_code::none,
		color_code background = color_code::none,
		bool inverse = false
	);

	// Returns a control sequence string which moves the cursor up.
	std::string cursor_up(int rows = 1);

	// Returns a control sequence string which moves the cursor down.
	std::string cursor_down(int rows = 1);

	// Returns a control sequence string which moves the cursor forward.
	std::string cursor_forward(int columns = 1);

	// Returns a control sequence string which moves the cursor back.
	std::string cursor_back(int columns = 1);

	/* Returns a control sequence string which moves the cursor to.
	 * the first column of the next line */
	std::string cursor_next_line(int lines = 1);

	/* Returns a control sequence string which moves the cursor to.
	 * the first column of the previous line */
	std::string cursor_previous_line(int lines = 1);

	// Returns a control sequence string which moves the cursor anywhere.
	std::string cursor_position(int row = 1, int column = 1);

	// Enums for all the erase modes
	enum class erase_mode{
		to_end = 0, // Erase from the cursor to end of the line/display
		to_beginning = 1, // Erase from the cursor to beginning of the line/display
		all = 2 // Erase the entire line/display
	};

	// Returns a control sequence string which erases the display
	std::string erase_display(erase_mode mode = erase_mode::all);

	// Returns a control sequence string which erases the current line
	std::string erase_line(erase_mode mode = erase_mode::all);

	// Returns a control sequence string which scrolls the display up
	std::string scroll_up(int lines = 1);

	// Returns a control sequence string which scrolls the display down
	std::string scroll_down(int lines = 1);

	/* Returns a control sequence string which selects a graphics setting
	 * with a code manually */
	std::string select_graphic_rendition(int code = 0);

	// Control sequence string which saves the cursor position
	const std::string save_cursor_position = prefix + "s";

	// Control sequence string which restores the cursor position
	const std::string restore_cursor_position = prefix + "u";
};
<commit_msg>Improve consistency<commit_after>#pragma once

#include <string>

namespace csi{
	// Control sequence introducer string which prefixes every control sequence.
	const std::string prefix = "\033[";

	// Enum for style codes.
	enum class style_code{
		bold = 1,
		italics = 3,
		underlined = 4,
		strikethrough = 9,
		inverse = 7,
		enable_offset = 0, // e.g. enable bold is 1 and enable italics is 3.
		disable_offset = 20 // e.g. disable bold is 21 and disable italics is 23.
	};

	// Return a control sequence string which enables a text style.
	std::string enable(style_code style);

	// Return a control sequence string which disables a text style.
	std::string disable(style_code style);

	// Return a control sequence string which enables or disables text styles.
	std::string style(
		bool bold = false,
		bool italics = false,
		bool underlined = false,
		bool strikethrough = false
	);

	// Enum for color codes.
	enum class color_code{
		none = 9, // The terminal's default colors.
		black = 0,
		red = 1,
		green = 2,
		yellow = 3,
		blue = 4,
		magenta = 5,
		cyan = 6,
		white = 7,
		foreground_offset = 30, // e.g. green foreground is 32.
		background_offset = 40 // e.g. green background is 42.
	};

	// Return a control sequence string which sets the text color.
	std::string foreground(color_code color = color_code::none);

	// Return a control sequence string which sets the text background color.
	std::string background(color_code color = color_code::none);

	/* Return a control sequence string which selects foreground and background
	 * text colors.
	 * Additionally, the colors can be inverted to make the text appear
	 * highlighted. */
	std::string color(
		color_code foreground = color_code::none,
		color_code background = color_code::none,
		bool inverse = false
	);

	// Return a control sequence string which moves the cursor up.
	std::string cursor_up(int rows = 1);

	// Return a control sequence string which moves the cursor down.
	std::string cursor_down(int rows = 1);

	// Return a control sequence string which moves the cursor forward.
	std::string cursor_forward(int columns = 1);

	// Return a control sequence string which moves the cursor back.
	std::string cursor_back(int columns = 1);

	/* Return a control sequence string which moves the cursor to.
	 * the first column of the next line */
	std::string cursor_next_line(int lines = 1);

	/* Return a control sequence string which moves the cursor to.
	 * the first column of the previous line */
	std::string cursor_previous_line(int lines = 1);

	// Return a control sequence string which moves the cursor anywhere.
	std::string cursor_position(int row = 1, int column = 1);

	// Enum for all the erase modes.
	enum class erase_mode{
		to_end = 0, // Erase from the cursor to end of the line/display.
		to_beginning = 1, // Erase from the cursor to beginning of the line/display.
		all = 2 // Erase the entire line/display.
	};

	// Return a control sequence string which erases the display.
	std::string erase_display(erase_mode mode = erase_mode::all);

	// Return a control sequence string which erases the current line.
	std::string erase_line(erase_mode mode = erase_mode::all);

	// Return a control sequence string which scrolls the display up.
	std::string scroll_up(int lines = 1);

	// Return a control sequence string which scrolls the display down.
	std::string scroll_down(int lines = 1);

	/* Return a control sequence string which selects a graphics setting.
	 * Check online for SGR codes. */
	std::string select_graphic_rendition(int code = 0);

	// Control sequence string which saves the cursor position.
	const std::string save_cursor_position = prefix + "s";

	// Control sequence string which restores the cursor position.
	const std::string restore_cursor_position = prefix + "u";
};
<|endoftext|>


<commit_before>
#include "xlsx_num_format_context.h"
#include "xlsx_complex_number_format.h"

#include <sstream>
#include <map>

#include "..\odf\odfcontext.h"

namespace cpdoccore {
namespace oox {

class num_format_context::Impl2
{
public:
    complex_number_format complex_number_format_;
};

class num_format_context::Impl
{
public:
    Impl(): in_convert_style_(false)
    {}

public:
    std::wstring current_style_name_;
    std::wstringstream stream_;

    void reset_current()
    {
        current_style_name_ = L"";
        stream_.str(std::wstring());
        in_convert_style_ = false;
    }

    std::wstring last_format_;

    bool in_convert_style_;
};

num_format_context::num_format_context(odf_reader::odf_read_context & odfContext): odf_context_(odfContext), impl_(new Impl()), impl2_(new Impl2())
{
}

num_format_context::~num_format_context()
{
}

void num_format_context::start_format(const std::wstring & style_name)
{
    impl_->reset_current();
    impl_->current_style_name_ = style_name;
    impl_->in_convert_style_ = true;
}

std::wostream & num_format_context::output()
{
    return impl_->stream_;
}

void num_format_context::end_format()
{
    impl_->last_format_ = impl_->stream_.str();
    impl_->reset_current();
}

std::wstring num_format_context::get_last_format() const
{
    return impl_->last_format_;
}

void num_format_context::start_complex_format()
{
    impl2_->complex_number_format_.reset();
}

void num_format_context::add_format(std::wstring const & cond, std::wstring const & format)
{
    impl2_->complex_number_format_.add_format(cond, format);
}

void num_format_context::end_complex_format()
{
    impl_->last_format_ = impl2_->complex_number_format_.result_value();
}

}
}
<commit_msg>fix linux build<commit_after>
#include "xlsx_num_format_context.h"
#include "xlsx_complex_number_format.h"

#include <sstream>
#include <map>

#include "../odf/odfcontext.h"

namespace cpdoccore {
namespace oox {

class num_format_context::Impl2
{
public:
    complex_number_format complex_number_format_;
};

class num_format_context::Impl
{
public:
    Impl(): in_convert_style_(false)
    {}

public:
    std::wstring current_style_name_;
    std::wstringstream stream_;

    void reset_current()
    {
        current_style_name_ = L"";
        stream_.str(std::wstring());
        in_convert_style_ = false;
    }

    std::wstring last_format_;

    bool in_convert_style_;
};

num_format_context::num_format_context(odf_reader::odf_read_context & odfContext): odf_context_(odfContext), impl_(new Impl()), impl2_(new Impl2())
{
}

num_format_context::~num_format_context()
{
}

void num_format_context::start_format(const std::wstring & style_name)
{
    impl_->reset_current();
    impl_->current_style_name_ = style_name;
    impl_->in_convert_style_ = true;
}

std::wostream & num_format_context::output()
{
    return impl_->stream_;
}

void num_format_context::end_format()
{
    impl_->last_format_ = impl_->stream_.str();
    impl_->reset_current();
}

std::wstring num_format_context::get_last_format() const
{
    return impl_->last_format_;
}

void num_format_context::start_complex_format()
{
    impl2_->complex_number_format_.reset();
}

void num_format_context::add_format(std::wstring const & cond, std::wstring const & format)
{
    impl2_->complex_number_format_.add_format(cond, format);
}

void num_format_context::end_complex_format()
{
    impl_->last_format_ = impl2_->complex_number_format_.result_value();
}

}
}
<|endoftext|>


<commit_before>#include "SUPPORT/generate2.h"
#include "SUPPORT/window.h"
#include "SUPPORT/geometricObject2.h"
#include "SUPPORT/delone10.h"
#include "SUPPORT/betaSet.h"

#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <list>
#include <mpi.h>
#include <string>
#include <chrono>

#define MASTER 0        /* task ID of master task */

typedef betaSet numberType;
typedef rhombus windowType;

int main (int argc, char* argv[])
{
  // time measuring
  std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();

  int	taskid;
  int numtasks;
  int nodeid;
  int nodes;
  int rc;

  std::string buffer;
  std::string send_buffer;
  int length;

  std::list<std::string> res;
  std::list<std::string> data;
  std::list<std::string>::iterator iterator;

  MPI_Status status;

  // initialize
  numberType winSize(1, 0, 2);
  Cpoint<numberType> origin( numberType::get(0,0), numberType::get(0,0) );

  std::string clipTileStr = "(0+1*beta)/2,(-1+2*beta)/2 (0+0*beta)/2,(0+1*beta)/1 (-1+2*beta)/2,(0+1*beta)/2 (0-1*beta)/2,(-1+2*beta)/2 (0+1*beta)/1,(0+0*beta)/4 (1-2*beta)/2,(0+1*beta)/2 (0+0*beta)/4,(0+0*beta)/4 (-1+2*beta)/2,(0-1*beta)/2 (0-1*beta)/1,(0+0*beta)/4 (0+1*beta)/2,(1-2*beta)/2 (1-2*beta)/2,(0-1*beta)/2 (0+0*beta)/2,(0-1*beta)/1 (0-1*beta)/2,(1-2*beta)/2 ";

  windowType win( winSize );
  win.center( origin );

  // hyperquasicrystal
  //rhombus *circ = dynamic_cast<rhombus*> ( win.circumscribed() );
  rhombus *circ = new rhombus(winSize*betaSet::get(4,0,3));

  // hypoquasicrystal
  //rhombus *insc = dynamic_cast<rhombus*> ( win.inscribed() );
  rhombus *insc = new rhombus(winSize*betaSet::get(2,0,3));

  betaSet S = circ->Xwindow().Small();
  betaSet L = insc->Xwindow().Large();

  betaSet coveringR = numberType::get(161, -43)*L;

  // size of rhumbus circumscribed to covering radius disc
  betaSet lengthToCover = numberType::get(8, 0)*coveringR;

  CvoronoiCell<numberType>::large = numberType::get(2, 0)*coveringR;

  // find out the word length by testing
  int wordLength = 1;
  do
  {
    ++wordLength;
  } while ( minWord(language(circ->Xwindow(), wordLength), circ->Xwindow()) < lengthToCover );

  wordLength = 5;

  /* Obtain number of tasks and task ID */
  MPI_Init(&argc,&argv);
  MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
  MPI_Comm_rank(MPI_COMM_WORLD,&taskid);

  std::cout << std::string(4, ' ') << "MPI task " << taskid << " has started..." << std::endl;

  nodes = numtasks-1;
  nodeid = taskid-1;

  if (taskid != MASTER) // NODE ----------------------------------------
  {
    CvoronoiCell<numberType> clipTile;
    clipTile.load(clipTileStr);
    *clipTile.CarrierSet = *clipTile.CarrierSet*numberType(0,1);

    do
    {
      MPI_Probe(MASTER, MPI_ANY_TAG, MPI_COMM_WORLD, &status);

      MPI_Get_count(&status, MPI_CHAR, &length);
      char *cache = new char[length];

      MPI_Recv(cache, length, MPI_CHAR, MASTER, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
      buffer = std::string(cache, length);
      delete [] cache;

      //std::cout << std::string(4, ' ') << taskid << ": received " << buffer << " status: " << status.MPI_TAG << std::endl;

      //std::cout << "  node " << taskid << " data received" << std::endl;

      if (status.MPI_TAG == 0)
      {

        // process data ------------------------------------------------
        std::string word1 = buffer.substr(0, buffer.length()/2);
        std::string word2 = buffer.substr(buffer.length()/2);
        CdeloneSet10<numberType> delone = quasicrystal2D10(circ->Xwindow(), word1, word2);

        delone << *clipTile.CarrierSet;

        delone.setPackingR();
        delone.setCoveringR(numberType::get(2, 0)*coveringR);
        delone.setDescription(word1+word2);
        delone.sortPotentialByDistance();

        delone.sortByDistance();

        std::list<CdeloneSet10<numberType> > delones;
        std::list<CvoronoiCell<numberType> > cells;
        delones.push_back(delone);

        for (std::list<CdeloneSet10<numberType> >::iterator it = delones.begin(); it != delones.end(); it = delones.begin())
        {
          //std::cout << "SIZE POTENTIAL: " << it->sizePotential() << std::endl;
          //it->filterPotentialByWindow(win);

          CvoronoiCell<numberType> voronoi;

          *(voronoi.CarrierSet) = *it;

          voronoi.CarrierSet->sort();
          voronoi.CarrierSet->unique();

          voronoi.CarrierSet->sortByDistance();
          voronoi.CarrierSet->setPackingR();
          voronoi.CarrierSet->setCoveringR(CvoronoiCell<numberType>::large);
          voronoi.setCenter(origin);
          voronoi.construct();
          voronoi.filterSet();

          std::list<Cpoint<numberType> > potential;
          potential = it->getPotential();
          voronoi.filterSetPotential( &potential );
          it->clearPotential();
          it->addPotential(potential);

          //std::cout << "SIZE POTENTIAL: " << it->sizePotential() << '\t' << "SIZE DELONES: " << delones.size() << std::endl;

          // deal with potential
          while (it->isPotential())
          {
            Cpoint<numberType> cache = it->popPotential();

            delone = *it;
            delone << cache;
            delones.push_back(delone);
          }

          cells.push_back( voronoi );

          delones.erase(it);

          delones.sort();
          delones.unique();

          //std::cout << "  node " << taskid << " delones: " << delones.size() << std::endl;
        }

        cells.sort();
        cells.unique();

        std::list<std::string> list;

        for (std::list<CvoronoiCell<numberType> >::iterator it = cells.begin(); it != cells.end(); ++it)
        {
          list.push_back(it->save());
        }

        list.sort();
        list.unique();
        // end ---------------------------------------------------------

        //std::cout << "  node " << taskid << " sending back: " << list.size() << std::endl;

        for (std::list<std::string>::iterator it = list.begin(); it != --list.end(); ++it)
        {
          send_buffer = *it;
          // return result
          MPI_Send(send_buffer.c_str(), send_buffer.length(), MPI_CHAR, MASTER, 0, MPI_COMM_WORLD);
        }

        send_buffer = *list.rbegin();
        // return result
        MPI_Send(send_buffer.c_str(), send_buffer.length(), MPI_CHAR, MASTER, 1, MPI_COMM_WORLD);
      }
    } while (status.MPI_TAG == 0);
  }
  else // MASTER -------------------------------------------------------
  {
    // create data -----------------------------------------------------
    std::cout << "Load data" << std::endl;

    std::list<std::string> lang = language( insc->Xwindow(), circ->Xwindow(), wordLength );
    for ( std::list<std::string>::iterator it = lang.begin(); it != lang.end(); ++it )
    {
      for ( std::list<std::string>::iterator ot = lang.begin(); ot != lang.end(); ++ot )
      {
        data.push_back(*it+*ot);
      }
    }

    std::cout << "tasks: " << data.size() << std::endl;
    std::cout << "word length: " << wordLength << std::endl;

    iterator = data.begin();

    int count = 0;
    // send initial load of data
    std::cout << "Send initial load of data" << std::endl;
    for (int it = 0; it < nodes; ++it)
    {
      send_buffer = *(iterator++);

      //std::cout << std::string(4, ' ') << "MASTER sending: " << iterator << "/168" << std::endl;

      MPI_Send(send_buffer.c_str(), send_buffer.length(), MPI_CHAR, it+1, 0, MPI_COMM_WORLD);
      count++;
    }

    // gather data while processing
    std::cout << "distribute the rest on demand" << std::endl;
    while (iterator != data.end())
    {
      //std::cout << "waiting" << std::endl;
      MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);

      MPI_Get_count(&status, MPI_CHAR, &length);
      char *cache = new char[length];
      MPI_Recv(cache, length, MPI_CHAR, status.MPI_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
      buffer = std::string(cache, length);
      delete [] cache;

      // save result
      res.push_back(buffer);
      //std::cout << "finished: " << res.size() << std::endl;

      while (status.MPI_TAG == 0)
      {
        MPI_Probe(status.MPI_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);

        MPI_Get_count(&status, MPI_CHAR, &length);
        char *cache = new char[length];
        MPI_Recv(cache, length, MPI_CHAR, status.MPI_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
        buffer = std::string(cache, length);
        delete [] cache;

        // save result
        res.push_back(buffer);
        //std::cout << "finished: " << res.size() << std::endl;
      }

      //std::cout << std::string(4, ' ') << "MASTER received from: " << status.MPI_SOURCE << " sending: " << iterator << std::endl;

      send_buffer = *(iterator++);

      MPI_Send(send_buffer.c_str(), send_buffer.length(), MPI_CHAR, status.MPI_SOURCE, 0, MPI_COMM_WORLD);

      count++;
      if ((20*count)%data.size() == 0)
      {
        std::cout << "processed " << count << "/" << data.size() << " <=> " << 10*count/data.size() << "0%" << std::endl;
      }
    }

    // terminate processes
    std::cout << "termination" << std::endl;
    for (int it = 0; it < nodes; ++it)
    {
      MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);

      MPI_Get_count(&status, MPI_CHAR, &length);
      char *cache = new char[length];
      MPI_Recv(cache, length, MPI_CHAR, status.MPI_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
      buffer = std::string(cache, length);
      delete [] cache;

      // save result
      res.push_back(buffer);
      std::cout << "finished: " << res.size() << std::endl;

      //std::cout << std::string(4, ' ') << "MASTER received from: " << status.MPI_SOURCE << " - " << buffer << std::endl;

      send_buffer = std::to_string(0);

      rc = MPI_Send(send_buffer.c_str(), send_buffer.length(), MPI_CHAR, it+1, 1, MPI_COMM_WORLD);
    }

    // write to file
    std::ostringstream convert;
    convert << argv[1] << "_" << wordLength << "_";
    printFile(convert, winSize);

    std::ofstream output(convert.str().c_str());
    res.sort();
    res.unique();

    print(output, winSize);
    output << std::endl;
    for (std::list<std::string>::iterator it = res.begin(); it != res.end(); ++it)
    {
      output << *it << std::endl;
    }
    output.close();
  }

  std::cout << std::string(4, ' ') << "... MPI task " << taskid << " is closing" << std::endl;
  MPI_Finalize();

  // time measuring
  std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
  auto duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
  std::cout << "microseconds: " << duration << " (" << std::round(duration/100000.0)/10.0 << "s)" << std::endl;

  return 0;
}
<commit_msg>minor adjustment<commit_after>#include "SUPPORT/generate2.h"
#include "SUPPORT/window.h"
#include "SUPPORT/geometricObject2.h"
#include "SUPPORT/delone10.h"
#include "SUPPORT/betaSet.h"

#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <list>
#include <mpi.h>
#include <string>
#include <chrono>

#define MASTER 0        /* task ID of master task */

typedef betaSet numberType;
typedef rhombus windowType;

int main (int argc, char* argv[])
{
  // time measuring
  std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();

  int	taskid;
  int numtasks;
  int nodeid;
  int nodes;
  int rc;

  std::string buffer;
  std::string send_buffer;
  int length;

  std::list<std::string> res;
  std::list<std::string> data;
  std::list<std::string>::iterator iterator;

  MPI_Status status;

  // initialize
  numberType winSize(1, 0, 2);
  Cpoint<numberType> origin( numberType::get(0,0), numberType::get(0,0) );

  std::string clipTileStr = "(0+1*beta)/2,(-1+2*beta)/2 (0+0*beta)/2,(0+1*beta)/1 (-1+2*beta)/2,(0+1*beta)/2 (0-1*beta)/2,(-1+2*beta)/2 (0+1*beta)/1,(0+0*beta)/4 (1-2*beta)/2,(0+1*beta)/2 (0+0*beta)/4,(0+0*beta)/4 (-1+2*beta)/2,(0-1*beta)/2 (0-1*beta)/1,(0+0*beta)/4 (0+1*beta)/2,(1-2*beta)/2 (1-2*beta)/2,(0-1*beta)/2 (0+0*beta)/2,(0-1*beta)/1 (0-1*beta)/2,(1-2*beta)/2 ";

  windowType win( winSize );
  win.center( origin );

  // hyperquasicrystal
  //rhombus *circ = dynamic_cast<rhombus*> ( win.circumscribed() );
  rhombus *circ = new rhombus(winSize*betaSet::get(4,0,3));

  // hypoquasicrystal
  //rhombus *insc = dynamic_cast<rhombus*> ( win.inscribed() );
  rhombus *insc = new rhombus(winSize*betaSet::get(2,0,3));

  betaSet S = circ->Xwindow().Small();
  betaSet L = insc->Xwindow().Large();

  betaSet coveringR = numberType::get(161, -43)*L;

  // size of rhumbus circumscribed to covering radius disc
  betaSet lengthToCover = numberType::get(8, 0)*coveringR;

  CvoronoiCell<numberType>::large = numberType::get(2, 0)*coveringR;

  // find out the word length by testing
  int wordLength = 1;
  do
  {
    ++wordLength;
  } while ( minWord(language(circ->Xwindow(), wordLength), circ->Xwindow()) < lengthToCover );

  //wordLength = 5;

  /* Obtain number of tasks and task ID */
  MPI_Init(&argc,&argv);
  MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
  MPI_Comm_rank(MPI_COMM_WORLD,&taskid);

  std::cout << std::string(4, ' ') << "MPI task " << taskid << " has started..." << std::endl;

  nodes = numtasks-1;
  nodeid = taskid-1;

  if (taskid != MASTER) // NODE ----------------------------------------
  {
    CvoronoiCell<numberType> clipTile;
    clipTile.load(clipTileStr);
    *clipTile.CarrierSet = *clipTile.CarrierSet*numberType(0,1);

    do
    {
      MPI_Probe(MASTER, MPI_ANY_TAG, MPI_COMM_WORLD, &status);

      MPI_Get_count(&status, MPI_CHAR, &length);
      char *cache = new char[length];

      MPI_Recv(cache, length, MPI_CHAR, MASTER, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
      buffer = std::string(cache, length);
      delete [] cache;

      //std::cout << std::string(4, ' ') << taskid << ": received " << buffer << " status: " << status.MPI_TAG << std::endl;

      //std::cout << "  node " << taskid << " data received" << std::endl;

      if (status.MPI_TAG == 0)
      {

        // process data ------------------------------------------------
        std::string word1 = buffer.substr(0, buffer.length()/2);
        std::string word2 = buffer.substr(buffer.length()/2);
        CdeloneSet10<numberType> delone = quasicrystal2D10(circ->Xwindow(), word1, word2);

        delone << *clipTile.CarrierSet;

        delone.setPackingR();
        delone.setCoveringR(numberType::get(2, 0)*coveringR);
        delone.setDescription(word1+word2);
        delone.sortPotentialByDistance();

        delone.sortByDistance();

        std::list<CdeloneSet10<numberType> > delones;
        std::list<CvoronoiCell<numberType> > cells;
        delones.push_back(delone);

        for (std::list<CdeloneSet10<numberType> >::iterator it = delones.begin(); it != delones.end(); it = delones.begin())
        {
          //std::cout << "SIZE POTENTIAL: " << it->sizePotential() << std::endl;
          //it->filterPotentialByWindow(win);

          CvoronoiCell<numberType> voronoi;

          *(voronoi.CarrierSet) = *it;

          voronoi.CarrierSet->sort();
          voronoi.CarrierSet->unique();

          voronoi.CarrierSet->sortByDistance();
          voronoi.CarrierSet->setPackingR();
          voronoi.CarrierSet->setCoveringR(CvoronoiCell<numberType>::large);
          voronoi.setCenter(origin);
          voronoi.construct();
          voronoi.filterSet();

          std::list<Cpoint<numberType> > potential;
          potential = it->getPotential();
          voronoi.filterSetPotential( &potential );
          it->clearPotential();
          it->addPotential(potential);

          //std::cout << "SIZE POTENTIAL: " << it->sizePotential() << '\t' << "SIZE DELONES: " << delones.size() << std::endl;

          // deal with potential
          while (it->isPotential())
          {
            Cpoint<numberType> cache = it->popPotential();

            delone = *it;
            delone << cache;
            delones.push_back(delone);
          }

          cells.push_back( voronoi );

          delones.erase(it);

          delones.sort();
          delones.unique();

          //std::cout << "  node " << taskid << " delones: " << delones.size() << std::endl;
        }

        cells.sort();
        cells.unique();

        std::list<std::string> list;

        for (std::list<CvoronoiCell<numberType> >::iterator it = cells.begin(); it != cells.end(); ++it)
        {
          list.push_back(it->save());
        }

        list.sort();
        list.unique();
        // end ---------------------------------------------------------

        //std::cout << "  node " << taskid << " sending back: " << list.size() << std::endl;

        for (std::list<std::string>::iterator it = list.begin(); it != --list.end(); ++it)
        {
          send_buffer = *it;
          // return result
          MPI_Send(send_buffer.c_str(), send_buffer.length(), MPI_CHAR, MASTER, 0, MPI_COMM_WORLD);
        }

        send_buffer = *list.rbegin();
        // return result
        MPI_Send(send_buffer.c_str(), send_buffer.length(), MPI_CHAR, MASTER, 1, MPI_COMM_WORLD);
      }
    } while (status.MPI_TAG == 0);
  }
  else // MASTER -------------------------------------------------------
  {
    // create data -----------------------------------------------------
    std::cout << "Load data" << std::endl;

    std::list<std::string> lang = language( insc->Xwindow(), circ->Xwindow(), wordLength );
    for ( std::list<std::string>::iterator it = lang.begin(); it != lang.end(); ++it )
    {
      for ( std::list<std::string>::iterator ot = lang.begin(); ot != lang.end(); ++ot )
      {
        data.push_back(*it+*ot);
      }
    }

    std::cout << "tasks: " << data.size() << std::endl;
    std::cout << "word length: " << wordLength << std::endl;

    iterator = data.begin();

    int count = 0;
    // send initial load of data
    std::cout << "Send initial load of data" << std::endl;
    for (int it = 0; it < nodes; ++it)
    {
      send_buffer = *(iterator++);

      //std::cout << std::string(4, ' ') << "MASTER sending: " << iterator << "/168" << std::endl;

      MPI_Send(send_buffer.c_str(), send_buffer.length(), MPI_CHAR, it+1, 0, MPI_COMM_WORLD);
      count++;
    }

    // gather data while processing
    std::cout << "distribute the rest on demand" << std::endl;
    while (iterator != data.end())
    {
      //std::cout << "waiting" << std::endl;
      MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);

      MPI_Get_count(&status, MPI_CHAR, &length);
      char *cache = new char[length];
      MPI_Recv(cache, length, MPI_CHAR, status.MPI_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
      buffer = std::string(cache, length);
      delete [] cache;

      // save result
      res.push_back(buffer);
      //std::cout << "finished: " << res.size() << std::endl;

      while (status.MPI_TAG == 0)
      {
        MPI_Probe(status.MPI_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);

        MPI_Get_count(&status, MPI_CHAR, &length);
        char *cache = new char[length];
        MPI_Recv(cache, length, MPI_CHAR, status.MPI_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
        buffer = std::string(cache, length);
        delete [] cache;

        // save result
        res.push_back(buffer);
        //std::cout << "finished: " << res.size() << std::endl;
      }

      //std::cout << std::string(4, ' ') << "MASTER received from: " << status.MPI_SOURCE << " sending: " << iterator << std::endl;

      send_buffer = *(iterator++);

      MPI_Send(send_buffer.c_str(), send_buffer.length(), MPI_CHAR, status.MPI_SOURCE, 0, MPI_COMM_WORLD);

      count++;
      if ((20*count)%data.size() == 0)
      {
        std::cout << "processed " << count << "/" << data.size() << " <=> " << 10*count/data.size() << "0%" << std::endl;
      }
    }

    // terminate processes
    std::cout << "termination" << std::endl;
    for (int it = 0; it < nodes; ++it)
    {
      MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);

      MPI_Get_count(&status, MPI_CHAR, &length);
      char *cache = new char[length];
      MPI_Recv(cache, length, MPI_CHAR, status.MPI_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
      buffer = std::string(cache, length);
      delete [] cache;

      // save result
      res.push_back(buffer);
      std::cout << "finished: " << res.size() << std::endl;

      //std::cout << std::string(4, ' ') << "MASTER received from: " << status.MPI_SOURCE << " - " << buffer << std::endl;

      send_buffer = std::to_string(0);

      rc = MPI_Send(send_buffer.c_str(), send_buffer.length(), MPI_CHAR, it+1, 1, MPI_COMM_WORLD);
    }

    // write to file
    std::ostringstream convert;
    convert << argv[1] << "_" << wordLength << "_";
    printFile(convert, winSize);

    std::ofstream output(convert.str().c_str());
    res.sort();
    res.unique();

    print(output, winSize);
    output << std::endl;
    for (std::list<std::string>::iterator it = res.begin(); it != res.end(); ++it)
    {
      output << *it << std::endl;
    }
    output.close();
  }

  std::cout << std::string(4, ' ') << "... MPI task " << taskid << " is closing" << std::endl;
  MPI_Finalize();

  // time measuring
  std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
  auto duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
  std::cout << "microseconds: " << duration << " (" << std::round(duration/100000.0)/10.0 << "s)" << std::endl;

  return 0;
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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 <thrift/lib/cpp/concurrency/Mutex-impl.h>

#include <gtest/gtest.h>
#include "common/concurrency/Timeout.h"
#include "common/time/TimeConstants.h"
#include <thrift/lib/cpp/concurrency/Util.h>
#include <thread>
#include <condition_variable>
#include <vector>

using namespace std;
using namespace facebook;
using namespace apache::thrift::concurrency;

const int kTimeoutUsec = 10*kUsecPerMs; // 10ms
const int kTimeoutMs = kTimeoutUsec / kUsecPerMs;
const int kMaxReaders = 10;
const int kMicroSecInMilliSec = 1000;
// user operation time on the lock in milliseconds
const int kOpTimeInMs = 100;

TEST(RWMutexTest, Max_Readers ) {
  ReadWriteMutex l;

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_TRUE(l.timedRead(kTimeoutMs));
  }

  EXPECT_TRUE(l.timedRead(kTimeoutMs));
}

TEST(RWMutexTest, Writer_Wait_Readers ) {
  ReadWriteMutex l;

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_TRUE(l.timedRead(kTimeoutMs));
    EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  }

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_FALSE(l.timedWrite(kTimeoutMs));
    l.release();
  }

  EXPECT_TRUE(l.timedWrite(kTimeoutMs));
  l.release();

  // Testing timeout
  vector<std::thread> threads_;
  for (int i = 0; i < kMaxReaders; ++i) {
    threads_.push_back(std::thread([this, &l] {
      EXPECT_TRUE(l.timedRead(kTimeoutMs));
      usleep(kOpTimeInMs * kMicroSecInMilliSec);
      l.release();
    }));
  }
  // make sure reader lock the lock first
  usleep(1000);

  // wait shorter than the operation time will timeout
  std::thread thread1 = std::thread([this, &l] {
      EXPECT_FALSE(l.timedWrite(0.5 * kOpTimeInMs));
    });

  // wait longer than the operation time will success
  std::thread thread2 = std::thread([this, &l] {
      EXPECT_TRUE(l.timedWrite(1.5 * kOpTimeInMs));
      l.release();
    });

  for (auto& t : threads_) {
    t.join();
  }
  thread1.join();
  thread2.join();
}

TEST(RWMutexTest, Readers_Wait_Writer) {
  ReadWriteMutex l;

  EXPECT_TRUE(l.timedWrite(kTimeoutMs));

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_FALSE(l.timedRead(kTimeoutMs));
  }

  l.release();

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_TRUE(l.timedRead(kTimeoutMs));
  }

  for (int i = 0; i < kMaxReaders; ++i) {
    l.release();
  }

  // Testing Timeout
  std::thread wrThread = std::thread([&l] {
      EXPECT_TRUE(l.timedWrite(kTimeoutMs));
      usleep(kOpTimeInMs * kMicroSecInMilliSec);
      l.release();
    });

  // make sure wrThread lock the lock first
  usleep(1000);

  vector<std::thread> threads_;
  for (int i = 0; i < kMaxReaders; ++i) {
    // wait shorter than the operation time will timeout
    threads_.push_back(std::thread([&l] {
      EXPECT_FALSE(l.timedRead(0.5 * kOpTimeInMs));
    }));

    // wait longer than the operation time will success
    threads_.push_back(std::thread([&l] {
      EXPECT_TRUE(l.timedRead(1.5 * kOpTimeInMs));
      l.release();
    }));
  }

  for (auto& t : threads_) {
    t.join();
  }
  wrThread.join();
}

TEST(RWMutexTest, Writer_Wait_Writer) {
  ReadWriteMutex l;

  EXPECT_TRUE(l.timedWrite(kTimeoutMs));
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  l.release();
  EXPECT_TRUE(l.timedWrite(kTimeoutMs));
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  l.release();

  // Testing Timeout
  std::thread wrThread1 = std::thread([this, &l] {
      EXPECT_TRUE(l.timedWrite(kTimeoutMs));
      usleep(kOpTimeInMs * kMicroSecInMilliSec);
      l.release();
    });

  // make sure wrThread lock the lock first
  usleep(1000);

  // wait shorter than the operation time will timeout
  std::thread wrThread2 = std::thread([this, &l] {
      EXPECT_FALSE(l.timedWrite(0.5 * kOpTimeInMs));
    });

  // wait longer than the operation time will success
  std::thread wrThread3 = std::thread([this, &l] {
      EXPECT_TRUE(l.timedWrite(1.5 * kOpTimeInMs));
      l.release();
    });

  wrThread1.join();
  wrThread2.join();
  wrThread3.join();
}

TEST(RWMutexTest, Read_Holders) {
  ReadWriteMutex l;

  RWGuard guard(l, false);
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  EXPECT_TRUE(l.timedRead(kTimeoutMs));
  l.release();
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
}

TEST(RWMutexTest, Write_Holders) {
  ReadWriteMutex l;

  RWGuard guard(l, true);
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  EXPECT_FALSE(l.timedRead(kTimeoutMs));
}

TEST(MutexTest, Recursive_Holders) {
  Mutex mutex(Mutex::RECURSIVE_INITIALIZER);
  Guard g1(mutex);
  {
    Guard g2(mutex);
  }
  Guard g2(mutex);
}

TEST(NoStarveRWMutexTest, Max_Readers ) {
  NoStarveReadWriteMutex l;

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_TRUE(l.timedRead(kTimeoutMs));
  }

  EXPECT_TRUE(l.timedRead(kTimeoutMs));
}

TEST(NoStarveRWMutexTest, Writer_Wait_Readers ) {
  NoStarveReadWriteMutex l;

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_TRUE(l.timedRead(kTimeoutMs));
    EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  }

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_FALSE(l.timedWrite(kTimeoutMs));
    l.release();
  }

  EXPECT_TRUE(l.timedWrite(kTimeoutMs));
  l.release();

  std::condition_variable cv;
  std::mutex cv_m;
  int readers = 0;

  // Testing timeout
  vector<std::thread> threads_;
  for (int i = 0; i < kMaxReaders; ++i) {
    threads_.push_back(std::thread([&, this] {
      EXPECT_TRUE(l.timedRead(kTimeoutMs));
      {
        std::lock_guard<std::mutex> lk(cv_m);
        readers++;
        cv.notify_one();
      }
      usleep(kOpTimeInMs * kMicroSecInMilliSec);
      l.release();
    }));
  }

  {
    std::unique_lock<std::mutex> lk(cv_m);
    cv.wait(lk, [&] {return readers == kMaxReaders;});
  }

  // wait shorter than the operation time will timeout
  std::thread thread1 = std::thread([this, &l] {
      EXPECT_FALSE(l.timedWrite(0.5 * kOpTimeInMs));
    });

  // wait longer than the operation time will success
  std::thread thread2 = std::thread([this, &l] {
      EXPECT_TRUE(l.timedWrite(1.5 * kOpTimeInMs));
      l.release();
    });

  for (auto& t : threads_) {
    t.join();
  }
  thread1.join();
  thread2.join();
}

TEST(NoStarveRWMutexTest, Readers_Wait_Writer) {
  NoStarveReadWriteMutex l;

  EXPECT_TRUE(l.timedWrite(kTimeoutMs));

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_FALSE(l.timedRead(kTimeoutMs));
  }

  l.release();

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_TRUE(l.timedRead(kTimeoutMs));
  }

  for (int i = 0; i < kMaxReaders; ++i) {
    l.release();
  }

  // Testing Timeout
  std::thread wrThread = std::thread([&l] {
      EXPECT_TRUE(l.timedWrite(kTimeoutMs));
      usleep(kOpTimeInMs * kMicroSecInMilliSec);
      l.release();
    });

  // make sure wrThread lock the lock first
  usleep(1000);

  vector<std::thread> threads_;
  for (int i = 0; i < kMaxReaders; ++i) {
    // wait shorter than the operation time will timeout
    threads_.push_back(std::thread([&l] {
      EXPECT_FALSE(l.timedRead(0.5 * kOpTimeInMs));
    }));

    // wait longer than the operation time will success
    threads_.push_back(std::thread([&l] {
      EXPECT_TRUE(l.timedRead(1.5 * kOpTimeInMs));
      l.release();
    }));
  }

  for (auto& t : threads_) {
    t.join();
  }
  wrThread.join();
}

TEST(NoStarveRWMutexTest, Writer_Wait_Writer) {
  NoStarveReadWriteMutex l;

  EXPECT_TRUE(l.timedWrite(kTimeoutMs));
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  l.release();
  EXPECT_TRUE(l.timedWrite(kTimeoutMs));
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  l.release();

  // Testing Timeout
  std::thread wrThread1 = std::thread([this, &l] {
      EXPECT_TRUE(l.timedWrite(kTimeoutMs));
      usleep(kOpTimeInMs * kMicroSecInMilliSec);
      l.release();
    });

  // make sure wrThread lock the lock first
  usleep(1000);

  // wait shorter than the operation time will timeout
  std::thread wrThread2 = std::thread([this, &l] {
      EXPECT_FALSE(l.timedWrite(0.5 * kOpTimeInMs));
    });

  // wait longer than the operation time will success
  std::thread wrThread3 = std::thread([this, &l] {
      EXPECT_TRUE(l.timedWrite(1.5 * kOpTimeInMs));
      l.release();
    });

  wrThread1.join();
  wrThread2.join();
  wrThread3.join();
}

TEST(NoStarveRWMutexTest, Read_Holders) {
  NoStarveReadWriteMutex l;

  RWGuard guard(l, false);
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  EXPECT_TRUE(l.timedRead(kTimeoutMs));
  l.release();
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
}

TEST(NoStarveRWMutexTest, Write_Holders) {
  NoStarveReadWriteMutex l;

  RWGuard guard(l, true);
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  EXPECT_FALSE(l.timedRead(kTimeoutMs));
}
<commit_msg>Fix RWMutexTest-NoStarveRWMutexTest.Readers_Wait_Writer<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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 <thrift/lib/cpp/concurrency/Mutex-impl.h>

#include <gtest/gtest.h>
#include "common/concurrency/Timeout.h"
#include "common/time/TimeConstants.h"
#include <thrift/lib/cpp/concurrency/Util.h>
#include <thread>
#include <condition_variable>
#include <vector>

using namespace std;
using namespace facebook;
using namespace apache::thrift::concurrency;

const int kTimeoutUsec = 10*kUsecPerMs; // 10ms
const int kTimeoutMs = kTimeoutUsec / kUsecPerMs;
const int kMaxReaders = 10;
const int kMicroSecInMilliSec = 1000;
// user operation time on the lock in milliseconds
const int kOpTimeInMs = 200;

TEST(RWMutexTest, Max_Readers ) {
  ReadWriteMutex l;

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_TRUE(l.timedRead(kTimeoutMs));
  }

  EXPECT_TRUE(l.timedRead(kTimeoutMs));
}

TEST(RWMutexTest, Writer_Wait_Readers ) {
  ReadWriteMutex l;

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_TRUE(l.timedRead(kTimeoutMs));
    EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  }

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_FALSE(l.timedWrite(kTimeoutMs));
    l.release();
  }

  EXPECT_TRUE(l.timedWrite(kTimeoutMs));
  l.release();

  // Testing timeout
  vector<std::thread> threads_;
  for (int i = 0; i < kMaxReaders; ++i) {
    threads_.push_back(std::thread([this, &l] {
      EXPECT_TRUE(l.timedRead(kTimeoutMs));
      usleep(kOpTimeInMs * kMicroSecInMilliSec);
      l.release();
    }));
  }
  // make sure reader lock the lock first
  usleep(1000);

  // wait shorter than the operation time will timeout
  std::thread thread1 = std::thread([this, &l] {
      EXPECT_FALSE(l.timedWrite(0.5 * kOpTimeInMs));
    });

  // wait longer than the operation time will success
  std::thread thread2 = std::thread([this, &l] {
      EXPECT_TRUE(l.timedWrite(1.5 * kOpTimeInMs));
      l.release();
    });

  for (auto& t : threads_) {
    t.join();
  }
  thread1.join();
  thread2.join();
}

TEST(RWMutexTest, Readers_Wait_Writer) {
  ReadWriteMutex l;

  EXPECT_TRUE(l.timedWrite(kTimeoutMs));

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_FALSE(l.timedRead(kTimeoutMs));
  }

  l.release();

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_TRUE(l.timedRead(kTimeoutMs));
  }

  for (int i = 0; i < kMaxReaders; ++i) {
    l.release();
  }

  // Testing Timeout
  std::thread wrThread = std::thread([&l] {
      EXPECT_TRUE(l.timedWrite(kTimeoutMs));
      usleep(kOpTimeInMs * kMicroSecInMilliSec);
      l.release();
    });

  // make sure wrThread lock the lock first
  usleep(1000);

  vector<std::thread> threads_;
  for (int i = 0; i < kMaxReaders; ++i) {
    // wait shorter than the operation time will timeout
    threads_.push_back(std::thread([&l] {
      EXPECT_FALSE(l.timedRead(0.5 * kOpTimeInMs));
    }));

    // wait longer than the operation time will success
    threads_.push_back(std::thread([&l] {
      EXPECT_TRUE(l.timedRead(1.5 * kOpTimeInMs));
      l.release();
    }));
  }

  for (auto& t : threads_) {
    t.join();
  }
  wrThread.join();
}

TEST(RWMutexTest, Writer_Wait_Writer) {
  ReadWriteMutex l;

  EXPECT_TRUE(l.timedWrite(kTimeoutMs));
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  l.release();
  EXPECT_TRUE(l.timedWrite(kTimeoutMs));
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  l.release();

  // Testing Timeout
  std::thread wrThread1 = std::thread([this, &l] {
      EXPECT_TRUE(l.timedWrite(kTimeoutMs));
      usleep(kOpTimeInMs * kMicroSecInMilliSec);
      l.release();
    });

  // make sure wrThread lock the lock first
  usleep(1000);

  // wait shorter than the operation time will timeout
  std::thread wrThread2 = std::thread([this, &l] {
      EXPECT_FALSE(l.timedWrite(0.5 * kOpTimeInMs));
    });

  // wait longer than the operation time will success
  std::thread wrThread3 = std::thread([this, &l] {
      EXPECT_TRUE(l.timedWrite(1.5 * kOpTimeInMs));
      l.release();
    });

  wrThread1.join();
  wrThread2.join();
  wrThread3.join();
}

TEST(RWMutexTest, Read_Holders) {
  ReadWriteMutex l;

  RWGuard guard(l, false);
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  EXPECT_TRUE(l.timedRead(kTimeoutMs));
  l.release();
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
}

TEST(RWMutexTest, Write_Holders) {
  ReadWriteMutex l;

  RWGuard guard(l, true);
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  EXPECT_FALSE(l.timedRead(kTimeoutMs));
}

TEST(MutexTest, Recursive_Holders) {
  Mutex mutex(Mutex::RECURSIVE_INITIALIZER);
  Guard g1(mutex);
  {
    Guard g2(mutex);
  }
  Guard g2(mutex);
}

TEST(NoStarveRWMutexTest, Max_Readers ) {
  NoStarveReadWriteMutex l;

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_TRUE(l.timedRead(kTimeoutMs));
  }

  EXPECT_TRUE(l.timedRead(kTimeoutMs));
}

TEST(NoStarveRWMutexTest, Writer_Wait_Readers ) {
  NoStarveReadWriteMutex l;

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_TRUE(l.timedRead(kTimeoutMs));
    EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  }

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_FALSE(l.timedWrite(kTimeoutMs));
    l.release();
  }

  EXPECT_TRUE(l.timedWrite(kTimeoutMs));
  l.release();

  std::condition_variable cv;
  std::mutex cv_m;
  int readers = 0;

  // Testing timeout
  vector<std::thread> threads_;
  for (int i = 0; i < kMaxReaders; ++i) {
    threads_.push_back(std::thread([&, this] {
      EXPECT_TRUE(l.timedRead(kTimeoutMs));
      {
        std::lock_guard<std::mutex> lk(cv_m);
        readers++;
        cv.notify_one();
      }
      usleep(kOpTimeInMs * kMicroSecInMilliSec);
      l.release();
    }));
  }

  {
    std::unique_lock<std::mutex> lk(cv_m);
    cv.wait(lk, [&] {return readers == kMaxReaders;});
  }

  // wait shorter than the operation time will timeout
  std::thread thread1 = std::thread([this, &l] {
      EXPECT_FALSE(l.timedWrite(0.5 * kOpTimeInMs));
    });

  // wait longer than the operation time will success
  std::thread thread2 = std::thread([this, &l] {
      EXPECT_TRUE(l.timedWrite(1.5 * kOpTimeInMs));
      l.release();
    });

  for (auto& t : threads_) {
    t.join();
  }
  thread1.join();
  thread2.join();
}

TEST(NoStarveRWMutexTest, Readers_Wait_Writer) {
  NoStarveReadWriteMutex l;

  EXPECT_TRUE(l.timedWrite(kTimeoutMs));

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_FALSE(l.timedRead(kTimeoutMs));
  }

  l.release();

  for (int i = 0; i < kMaxReaders; ++i) {
    EXPECT_TRUE(l.timedRead(kTimeoutMs));
  }

  for (int i = 0; i < kMaxReaders; ++i) {
    l.release();
  }

  std::condition_variable cv;
  std::mutex cv_m;
  bool writer = false;

  // Testing Timeout
  std::thread wrThread = std::thread([&] {
      EXPECT_TRUE(l.timedWrite(kTimeoutMs));
      {
        std::lock_guard<std::mutex> lk(cv_m);
        writer = true;
        cv.notify_all();
      }
      usleep(kOpTimeInMs * kMicroSecInMilliSec);
      l.release();
    });

  vector<std::thread> threads_;
  for (int i = 0; i < kMaxReaders; ++i) {
    // wait shorter than the operation time will timeout
    threads_.push_back(std::thread([&] {
      {
        std::unique_lock<std::mutex> lk(cv_m);
        cv.wait(lk, [&] { return writer; });
      }
      EXPECT_FALSE(l.timedRead(0.5 * kOpTimeInMs));
    }));

    // wait longer than the operation time will success
    threads_.push_back(std::thread([&l] {
      EXPECT_TRUE(l.timedRead(1.5 * kOpTimeInMs));
      l.release();
    }));
  }

  for (auto& t : threads_) {
    t.join();
  }
  wrThread.join();
}

TEST(NoStarveRWMutexTest, Writer_Wait_Writer) {
  NoStarveReadWriteMutex l;

  EXPECT_TRUE(l.timedWrite(kTimeoutMs));
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  l.release();
  EXPECT_TRUE(l.timedWrite(kTimeoutMs));
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  l.release();

  // Testing Timeout
  std::thread wrThread1 = std::thread([this, &l] {
      EXPECT_TRUE(l.timedWrite(kTimeoutMs));
      usleep(kOpTimeInMs * kMicroSecInMilliSec);
      l.release();
    });

  // make sure wrThread lock the lock first
  usleep(1000);

  // wait shorter than the operation time will timeout
  std::thread wrThread2 = std::thread([this, &l] {
      EXPECT_FALSE(l.timedWrite(0.5 * kOpTimeInMs));
    });

  // wait longer than the operation time will success
  std::thread wrThread3 = std::thread([this, &l] {
      EXPECT_TRUE(l.timedWrite(1.5 * kOpTimeInMs));
      l.release();
    });

  wrThread1.join();
  wrThread2.join();
  wrThread3.join();
}

TEST(NoStarveRWMutexTest, Read_Holders) {
  NoStarveReadWriteMutex l;

  RWGuard guard(l, false);
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  EXPECT_TRUE(l.timedRead(kTimeoutMs));
  l.release();
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
}

TEST(NoStarveRWMutexTest, Write_Holders) {
  NoStarveReadWriteMutex l;

  RWGuard guard(l, true);
  EXPECT_FALSE(l.timedWrite(kTimeoutMs));
  EXPECT_FALSE(l.timedRead(kTimeoutMs));
}
<|endoftext|>