aboutsummaryrefslogtreecommitdiffstats
path: root/include/rba/RBAArbitrator.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/rba/RBAArbitrator.hpp')
-rw-r--r--include/rba/RBAArbitrator.hpp600
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