diff options
Diffstat (limited to 'include/rba/RBAArbitrator.hpp')
-rw-r--r-- | include/rba/RBAArbitrator.hpp | 600 |
1 files changed, 600 insertions, 0 deletions
diff --git a/include/rba/RBAArbitrator.hpp b/include/rba/RBAArbitrator.hpp new file mode 100644 index 0000000..c7c2761 --- /dev/null +++ b/include/rba/RBAArbitrator.hpp @@ -0,0 +1,600 @@ +// Copyright (c) 2018 DENSO CORPORATION. All rights reserved. +/** + * Arbitrator Logic class + */ + +#ifndef RBAARBITORATOR_HPP +#define RBAARBITORATOR_HPP + +#ifdef _MSC_VER +#ifdef _WINDLL +#define DLL_EXPORT __declspec(dllexport) +#else +#define DLL_EXPORT __declspec(dllimport) +#endif +#else +#define DLL_EXPORT +#endif + +#include <string> +#include <list> +#include <memory> +#include <mutex> +#include <deque> +#include "RBAModel.hpp" +#include "RBAResult.hpp" +#include "RBARequestQueMember.hpp" +#include "RBAResultSet.hpp" +#include "RBAResultImpl.hpp" + +/** + * @namespace rba + * @brief The namespace defined by Rule Based Arbitration Framework. + */ +namespace rba +{ + +// internal { +#ifdef RBA_USE_LOG +class RBALogManager; +#endif + +class RBARuleObject; +class RBAExpression; +class RBAModelImpl; +class RBAAffectInfo; +class RBARollbacker; +class RBAWindowRouter; +class RBAConstraintImpl; +// } + +/** + * @class RBAArbitrator + * An object that performs arbitration processing based on rules + * generated from a model.<br> + * Set the model generated using rba::RBAJsonParser in the constructor. + */ +class DLL_EXPORT RBAArbitrator +{ +public: + /** + * @brief Arbitrator logic constractor. + * @param newModel Processing model. + * The model is generated by rba::RBAJsonParser. + */ + RBAArbitrator()=default; + RBAArbitrator(RBAModel* newModel); + + /** + * @brief Arbitrator logic destractor. + */ + RBAArbitrator(const RBAArbitrator&)=delete; + RBAArbitrator(const RBAArbitrator&&)=delete; + RBAArbitrator& operator=(const RBAArbitrator&)=delete; + RBAArbitrator& operator=(const RBAArbitrator&&)=delete; + virtual ~RBAArbitrator() noexcept; + +public: + + /** + * @brief Sets the model for arbitration + * The model is generated by rba::RBAJsonParser. + * @param newModel The model for arbitration + * @details Replace the model with newModel. An arbitrator has only one model at all times. + * Model can be generated by using rba::RBAJsonParser. + * nullptr can not be set. + */ + void setModel(RBAModel* newModel); + + /** + * @brief Returns the model for arbitration + * @return model The model for arbitration + * @details Because the arbitrator always has a model, this API never returns nullptr. + */ + const RBAModel* getModel() const; + + /** + * @brief Set initial requirements of contents and scenes + * @param contexts Context list of contents and scenes requests. + * + * Following is the structure of context name.\n + * *<CONTENT_NAME>* / *<STATE_NAME>* \n\n + * Example of context name: \n + * TEL/Calling\n + * TPMS/NORMAL\n + * AutoDriveScene\n\n + * You can omit "/ <STATE_NAME>" if content has only one state. + * @details After arbitrator creation or calling clearArbitration(), + * you can set initial state of contents and scenes for first arbitration. + * This API does not execute arbitration. + * The information of arbitration result will be empty. + * Don't call this API after starting arbitration until calling clearArbitration(). + * @details + * **Example** + * + * ``` + * RBAJsonParser parser; + * rba::RBAModel* model = parser.parse(JSONFILE_PATH); + * rba::RBAArbitrator* arb = new rba::RBAArbitrator(model); + * + * std::list<std::string> defaultContents = { + * "CONTENT_A/NORMAL", + * "CONTENT_B/NORMAL", + * "CONTENT_C/NORMAL", + * "CONTENT_D/NORMAL", + * }; + * arb->initialize(defaultContents); + * std::unique_ptr<RBAResult> result = arb->execute(); + * ``` + */ + void initialize(std::list<std::string>& contexts); + + /** + * @brief Executes arbitration with one requirement\n + * @param contextName + * Context string of arbitration request.\n + * Display request or sound request : "<CONTENT_NAME>/<STATE_NAME>"\n + * If the content has only one state, the <STATE> can be omitted.\n + * \n + * Scene request : ”<SCENE_NAME>” + * @param require + * true : request displaying / outputting content or scene on (default)\n + * false : withdraw a request or scene off. + * + * @return The result of arbitration. + * @details + * Execute Arbitration with one requirement of a content or scene without properties. \n + * The arbitration result as the return value will be generated at every arbitration and + * will not be changed by another arbitration. + * \n + * Context indicates a content state or a scene. + * If the content or scene is not defined in the model, the arbitration will not executed + * and the state of the arbitration result will be UNKNWON_CONTENT_STATE. + * In this case, other property values are undefined.\n + * If the context is empty, this API just execute arbitration. + * \n + * **Exapmle** + * + * ``` + * RBAJsonParser parser; + * rba::RBAModel* model = parser.parse(JSONFILE_PATH); + * rba::RBAArbitrator* arb = new rba::RBAArbitrator(model); + * std::unique_ptr<RBAResult> result = arb->execute("CONTENT_A/NORMAL", true); + * + * if(result->getStatusType() != rba::RBAResultStatusType::SUCCESS) { + * std::cout << "ERROR: Unknown context" << std::endl; + * } + * ``` + * + */ + std::unique_ptr<RBAResult> execute(const std::string& contextName="", + bool require=true); + + /** + * @brief Executes arbitration with multiple requirements\n + * @param contexts List of contexts. + * @param require + * true : request displaying / outputting content or scene on (default)\n + * false : withdraw a request or scene off. + * @return The result of arbitration. + * @details + * \n + * Execute Arbitration with multiple requirements of contents or scenes. \n + * Contents and Scenes can be mixed in the list. + * Display / Outputting request and withdraw request, scene on and scene off request can not be mixed. + * The arbitration result as the return value will be generated at every arbitration and + * will not be changed by another arbitration. + * \n + * Context indicates a content state or a scene. + * If the content or scene is not defined in the model, the arbitration will not executed + * and the state of the arbitration result will be UNKNWON_CONTENT_STATE.\n + * In this case, other property values are undefined.\n + * If the context is empty, this API just execute arbitration. + * \n + * Request order is the with the list. Beginning of the list will be treated as the first coming request. + * \n + * **Exapmle** + * + * ``` + * RBAJsonParser parser; + * rba::RBAModel* model = parser.parse(JSONFILE_PATH); + * rba::RBAArbitrator* arb = new rba::RBAArbitrator(model); + * std::list<std::string> contents = { + * "CONTENT_A/NORMAL", + * "CONTENT_B/NORMAL", + * "CONTENT_C/NORMAL", + * "CONTENT_D/NORMAL", + * }; + * std::unique_ptr<RBAResult> result = arb->execute(contents, true); + * + * if(result->getStatusType() != rba::RBAResultStatusType::SUCCESS) { + * std::cout << "ERROR: Unknown context" << std::endl; + * } + * ``` + * + */ + std::unique_ptr<RBAResult> execute(std::list<std::string>& contexts, + bool require=true); + + /** + * @brief Executes arbitration with a requirement of scene and scene properties. + * @param sceneName The Scene name of arbitration reauest.\n + * @param properties The list of pairs of property name and value. + * @return The result of arbitration. + * @details + * \n + * Sets the scene indicated by sceneName to the property specified + * by properties, and execute arbitration processing.\n + * If sceneName is empty, this API just execute arbitration. + * If the required scene is not defined in the model, the arbitration will not executed + * and the state of the arbitration result will be UNKNWON_CONTENT_STATE.\n + * Even If there is a property not defined in the model, the arbitration will be executed. + * \n + * @note + * You cannot set scene off and property at the same time, by this API.\n + * Use setScene() to set scene off and properties, + * and then call execute(const std::string&,bool) without specifying arguments.\n + * Or Use setScene() to set properties, + * and then call execute(scene name,false).\n + * \n + * @details + * **Example** + * + * ``` + * RBAJsonParser parser; + * rba::RBAModel* model = parser.parse(JSONFILE_PATH); + * rba::RBAArbitrator* arb = new rba::RBAArbitrator(model); + * std::list<std::pair<std::string, std::int32_t>> properties; + * properties.push_back(std::make_pair("Prop1", 10)); + * properties.push_back(std::make_pair("Prop2", 20)); + * std::unique_ptr<RBAResult> result = arb->execute("Scene1", properties); + * + * if(result->getStatusType() != rba::RBAResultStatusType::SUCCESS) { + * std::cout << "ERROR: Unknown context" << std::endl; + * } + * ``` + */ + std::unique_ptr<RBAResult> execute(const std::string& sceneName, + std::list<std::pair<std::string,std::int32_t>>& properties); + + /** + * @brief Replaces the result of arbitration + * @param allocatableName area or zone name + * @param contextName Context string of arbitration request. + * @return The result of arbitration. + * @details + * \n + * Replace allocated a content state to area or zone of the last arbitration result.\n + * If the allocatableName or contextName is undefined, return the errror + * code from the method getStatusType() of result.\n + * If the contextName is non-active, activate the content request. + * This API execute the "Request handling on lost" process and the + * "Execution expression" process, and doesn't execute the check of + * constraint expression process. + * Therefore, this API can lead the result that does not satisfy the constraints\n + * If the specified area or zone by allocatableName is hidden, mute or + * attenuated, these statuses will be kept. + * @deprecated Because there is a possibility that the result does not satisfy + * the constraints, please use execute() + * instead of this API.\n + * \n + * @details + * **Example** + * + * ``` + * RBAJsonParser parser; + * rba::RBAModel* model = parser.parse(JSONFILE_PATH); + * rba::RBAArbitrator* arb = new rba::RBAArbitrator(model); + * std::unique_ptr<RBAResult> result = arb->execute("CONTENT_A/NORMAL", true); + * std::unique_ptr<RBAResult> result_replaced = arb->setResultContentState("AREA_A", "CONTENT_B/NORMAL"); + * + * if(result_replaced->getStatusType() != rba::RBAResultStatusType::SUCCESS) { + * std::cout << "ERROR" << std::endl; + * } + * ``` + */ + std::unique_ptr<RBAResult> + setResultContentState(const std::string& allocatableName, + const std::string& contextName); + + /** + * @brief Cancel last arbitration + * @return The result of arbitration. + * @details + * \n + * Cancel last arbitration and restore internal state immediately.\n + * This API returns the restored result but the ViewActions will be empty.\n + * Do not execute this function more than once continuously. In that case, + * an error occurs.\n + * Even when executed without performing arbitration processing, + * an error occurs.\n + * In case of error, the status of the arbitration result is set to + * CANCEL_ERROR.\n + * \n + * @details + * **Example** + * + * ``` + * RBAJsonParser parser; + * rba::RBAModel* model = parser.parse(JSONFILE_PATH); + * rba::RBAArbitrator* arb = new rba::RBAArbitrator(model); + * std::unique_ptr<RBAResult> result = arb->execute("CONTENT_A/NORMAL", true); + * std::unique_ptr<RBAResult> result_back = arb->cancelArbitration() + * + * if(result_replaced->getStatusType() != rba::RBAResultStatusType::SUCCESS) { + * std::cout << "ERROR" << std::endl; + * } + * ``` + */ + std::unique_ptr<RBAResult> cancelArbitration(); + + /** + * @brief Clear internal states of arbitration. + * @details + * \n + * Initialize internal states of arbitration (ex. Previous arbitration + * result, request of content states, etc...) and set to the initial state.\n + * \n + * @note + * This API is intended for setting up initial state of unit tests.\n + * \n + * @details + * **Example** + * + * ``` + * std::unique_ptr<RBAResult> result1 = arb->execute("CONTENT_A/NORMAL", true); + * std::unique_ptr<RBAResult> result2 = arb->execute("CONTENT_B/NORMAL", true); + * // reset display requests + * arb->clearArbitration(); + * std::unique_ptr<RBAResult> result2 = arb->execute("CONTENT_C/NORMAL", true); + * std::unique_ptr<RBAResult> result3 = arb->execute("CONTENT_D/NORMAL", true); + + * + * ``` + */ + void clearArbitration(); + + /** + * @brief Sets scene ON/OFF requests and properties. + * @param sceneName The Scene name of arbitration reauest.\n + * @param require true : Valid request.\n + * false : Invalid request. + * @param properties The pair of property name and value.\n + * @return true: Success\n + * @return false: Unknown scene\n + * @details + * \n + * Sets the scene indicated by sceneName to the property specified + * by properties, and without execute arbitration processing.\n + * Returns true if the scene set succeeded. If an unknown scene name is + * specified, false is returned.\n + * \n + * @note + * This API is intended for setting up initial state of unit tests\n + * or setting global scene and scene properties.\n + * \n + * @details + * **Example** + * + * ``` + * std::list<std::pair<std::string, std::int32_t>> props; + * props.push_back(std::make_pair("PropertyA", 10); + * props.push_back(std::make_pair("PropertyB", -3); + * res = arb->setScene("SCENE_A", true, props); + * if(res == false) { + * // Unknwon scene + * } + * ``` + */ + bool setScene(const std::string& sceneName, bool require, + std::list<std::pair<std::string, std::int32_t>>& properties); + + /** + * @brief Sets content requests or scene ON/OFF request. + * @param contextName Context string of arbitration request.\n + * @param require + * true : request displaying / outputting content or scene on (default)\n + * false : withdraw a request or scene off. + * @return true: Success\n + * @return false: Unknown context\n + * @details + * \n + * Sets a display request for the context without arbitration.\n + * Returns true if the request setting is succeeded. If an unknown context + * name is specified, false is returned.\n + * \n + * @note + * This API is intended for setting up initial state of unit tests.\n + * While initialize() has only the function to turn on the request, + * this API can turn off the request. It is used for switch of each + * requests when initialization setting of unit test.\n + * \n + * @details + * **Example** + * + * ``` + * res = arb->setContentState("ContentA/NORMAL", true); + * if(res == false) { + * // Unknwon context + * } + * ``` + */ + bool setContentState(const std::string& contextName, bool require); + + /** + * @brief Allocates content state to area or zone. + * @param allocatableName Name of area or zone + * @param contextName Context string of content state.\n + * contextName : "<CONTENT_NAME>/<STATE_NAME>"\n + * If the content has only one state, the <STATE> can be omitted.\n + * \n + * @return true: Success\n + * @return false: Unknown area, zone or context\n + * @details + * \n + * Allocates the content state to the area or zone. Arbitration and + * post arbitration will not be executed.\n + * The display / outputting request of the specified content state will be active. + * The statuses of hidden, mute and attenuated will not be changed.\n + * Returns true if the request setting is succeeded. If an unknown context + * name is specified, false is returned.\n + * + * @note + * This API is intended for setting up initial state of unit tests.\n + * In setResultContentState(), in addition to content state assignment, + * evaluation of the action determination process at the time of arbitration + * losing and control execution expression is performed, whereas in this + * API only content state assignment is performed.\n + * \n + * @deprecated + * Since there is a possibility of contradiction with the + * constraint, it is recommended not to use it except unit test. + * \n + * @details + * **Example** + * + * ``` + * res = arb->setAllocatableResult("AreaA", "ContentA/NORMAL"); + * if(res == false) { + * // Unknwon area, zone or context + * } + * ``` + */ + bool setAllocatableResult(const std::string& allocatableName, + const std::string& contextName); + // internal { +#ifdef RBA_USE_LOG + RBAArbitrator(RBAModel* newModel, RBALogManager* logManager); +#endif + bool evaluate(RBAExpression* expression); + const RBARuleObject* evaluateObject(RBAExpression* expression); + int32_t evaluateValue(RBAExpression* expression); + + // } + +private: +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4251) +#endif +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +private: + bool isValidContext(const std::string& context); + bool isValidContext(std::list<std::string>& contexts); + bool setRequestData( + const std::string& context, bool require, + std::list<std::pair<std::string, std::int32_t>>* const properties = nullptr, + std::uint32_t syncIndex = 0xFFFFU); + void setRequestData(const RBAContentState* state, bool require); + void setRequestData(const RBAContent* const content, bool require); + void setActive(const RBASceneImpl* const scene, const bool require); + void setSceneProperty(const RBAAbstractProperty* const prop, const std::int32_t value); + void setRequestData(std::list<std::string>& contexts, const bool require); + +#ifdef RBA_USE_LOG + void checkAllConstraints(); +#endif + void updateResult(); + void checkCancelContent() const; + void createResultData(); + +public: + bool satisfiesConstraints() const; + +private: + std::unique_ptr<RBAResult> arbitrateMain(); + void arbitrate(std::list<RBAAllocatable*>& allocatables); + void arbitrateAllocatable(RBAAllocatable* allocatable, + std::set<const RBAAllocatable*>& revisited, + const std::int32_t nest, RBAAffectInfo* const affectInfo, + RBARollbacker* const parentRollbacker); + + bool sortContentStates(const RBAAllocatable* const allocatable, + std::list<const RBAContentState*>& states) const; + void postArbitrate(); + void changeContentStateCancelWithPolicy(const RBAContentState* const state); + void collectRevisitAllocatable( + std::list<const RBAAllocatable*>* const totalRevisitAllocatables, + RBAAllocatable*& allocatable, + std::list<RBAConstraintImpl*>& falseConstraints, + std::set<const RBAAllocatable*>& revisited); + + static std::int32_t getViewActionPriority(const RBAViewActionType viewActionType); + static bool compareViewAction(const std::unique_ptr<RBAViewAction>& lhs, + const std::unique_ptr<RBAViewAction>& rhs); + +public: + RBAResultImpl* getResult() const; /// Used by rba_tool + bool isCancel(const RBAContentState* const state) const; + +private: + void differenceArbitrate(); + bool checkConstraints(std::list<RBAConstraintImpl*>& constraints, + std::list<RBAConstraintImpl*>& falseConstraints, + const RBAAllocatable* const allocatable); + bool checkConstraintAndReArbitrate(RBAAllocatable* allocatable, + std::set<const RBAAllocatable*>& revisited, + const std::int32_t nest, + RBAAffectInfo* const affectInfo, + RBARollbacker* const parentRollbacker, + std::list<RBAConstraintImpl*>& constraints, + bool * const isSkipped, const bool isFinal); + void setCancel(const RBAContentState* const state, const bool checked); + void getSortedContentStates( + const RBAAllocatable* const allocatable, + std::list<const RBAContentState*>& contentStates) const; + +#ifdef RBA_USE_LOG + void logRequestArbitration(); + void logPreResultArbitration(); + void logRequestForCoverage(); + void logResultArbitration(); + void logResultForCoverage(); + void setLogToResult(); +#endif + +public: + std::set<const RBAContentState*>& getCancelChecked(); + std::unique_ptr<RBAResultImpl>& getResultRef() const; + void setResult(std::unique_ptr<RBAResultImpl> result); + std::unique_ptr<RBAResultSet>& getNextResultSet(); + void setNextResultSet(std::unique_ptr<RBAResultSet> nextResultSet); + std::unique_ptr<RBAResultSet>& getBackupResultSet(); + void setBackupResultSet(std::unique_ptr<RBAResultSet> backupResultSet); + std::unique_ptr<RBAResultSet>& getReservedResultSet(); + void setReservedResultSet(std::unique_ptr<RBAResultSet> reservedResultSet); + std::recursive_mutex& getMutex() const; +#ifdef RBA_USE_LOG + void setSimulationMode(bool simulationMode); +#endif + std::deque<std::unique_ptr<RBARequestQueMember>>& getRequestQue(); + +private: + RBAModelImpl* model_ {nullptr}; + std::set<const RBAContentState*> cancelChecked_; + + mutable std::unique_ptr<RBAResultImpl> result_; + // ResultSet to use as CurrentResultSet in next arbitration + std::unique_ptr<RBAResultSet> nextResultSet_; + // ResultSet to use as PreviousResultSet in next arbitration + std::unique_ptr<RBAResultSet> backupResultSet_; + // ResultSet to be used as CurrentResultSet in cancelArbitration() + std::unique_ptr<RBAResultSet> reservedResultSet_; + // ResultSet to use as CurrentResultSet in satisfiesConstraints() + std::unique_ptr<RBAResultSet> resultSetForSatisfiesConstraints_; + mutable std::recursive_mutex mutex_; +#ifdef RBA_USE_LOG + bool simulationMode_ = false; +#endif + std::deque<std::unique_ptr<RBARequestQueMember>> requestQue_; + +public: + void setModel(RBAModelImpl* const newModel); +}; + +} + +#endif |