Add state machine module.

This commit is contained in:
xiaojiazhu 2023-09-10 06:11:12 -07:00
parent 9fc61803f1
commit 08d451c882
23 changed files with 2956 additions and 8 deletions

View File

@ -42,14 +42,6 @@ endif()
#Add macro definition #Add macro definition
# add_definitions(-DCONFIG_FILE_PATH=\"${CONFIG_FILE_PATH}\") # add_definitions(-DCONFIG_FILE_PATH=\"${CONFIG_FILE_PATH}\")
# Config message of libs on board
# unset(MAIN_INCLUDE_PATH CACHE)
# set(MAIN_INCLUDE_PATH "" CACHE STRING INTERNAL)
# unset(MAIN_SRC_FILE CACHE)
# set(MAIN_SRC_FILE "" CACHE STRING INTERNAL)
# unset(MAIN_LINK_LIB CACHE)
# set(MAIN_LINK_LIB "" CACHE STRING INTERNAL)
# Config message of main thread # Config message of main thread
unset(MAIN_INCLUDE_PATH CACHE) unset(MAIN_INCLUDE_PATH CACHE)
set(MAIN_INCLUDE_PATH "" CACHE STRING INTERNAL) set(MAIN_INCLUDE_PATH "" CACHE STRING INTERNAL)
@ -85,6 +77,7 @@ endif()
# #
# add_subdirectory(application) # add_subdirectory(application)
add_subdirectory(middleware)
add_subdirectory(utils) add_subdirectory(utils)
add_subdirectory(hal) add_subdirectory(hal)
# add_subdirectory(customization) # add_subdirectory(customization)

View File

@ -7,6 +7,7 @@ set(TEST_OUTPUT_PATH "${PLATFORM_PATH}/out/test")
set(PROJECT_ROOT_PATH "${PLATFORM_PATH}") set(PROJECT_ROOT_PATH "${PLATFORM_PATH}")
set(APPLICATION_SOURCE_PATH "${CMAKE_SOURCE_DIR_IPCSDK}/application") set(APPLICATION_SOURCE_PATH "${CMAKE_SOURCE_DIR_IPCSDK}/application")
set(MIDDLEWARE_SOURCE_PATH "${CMAKE_SOURCE_DIR_IPCSDK}/middleware")
set(UTILS_SOURCE_PATH "${CMAKE_SOURCE_DIR_IPCSDK}/utils") set(UTILS_SOURCE_PATH "${CMAKE_SOURCE_DIR_IPCSDK}/utils")
set(HAL_SOURCE_PATH "${CMAKE_SOURCE_DIR_IPCSDK}/hal") set(HAL_SOURCE_PATH "${CMAKE_SOURCE_DIR_IPCSDK}/hal")
set(TEST_SOURCE_PATH "${CMAKE_SOURCE_DIR_IPCSDK}/test") set(TEST_SOURCE_PATH "${CMAKE_SOURCE_DIR_IPCSDK}/test")

View File

@ -0,0 +1,2 @@
add_subdirectory(StateMachine)

View File

@ -0,0 +1,47 @@
include(${CMAKE_SOURCE_DIR}/build/global_config.cmake)
set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH})
set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH})
include_directories(
./src
./include
./src/OpenHarmony
${UTILS_SOURCE_PATH}/StatusCode/include
${UTILS_SOURCE_PATH}/Log/include
${HAL_SOURCE_PATH}/include
)
#do not rely on any other library
#link_directories(
#)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
aux_source_directory(./src SRC_FILES)
aux_source_directory(./src/OpenHarmony SRC_FILES_OPENHARMONY)
set(TARGET_NAME StateMachine)
add_library(${TARGET_NAME} STATIC ${SRC_FILES} ${SRC_FILES_OPENHARMONY})
target_link_libraries(${TARGET_NAME} ReturnCode Log)
if ("${CLANG_TIDY_SUPPORT}" MATCHES "true")
add_custom_target(
StateMahince_code_check
COMMAND ${CLANG_TIDY_EXE}
-checks='${CLANG_TIDY_CHECKS}'
--header-filter=.*
--system-headers=false
${SRC_FILES}
${CLANG_TIDY_CONFIG}
-p ${CMAKE_SOURCE_DIR_IPCSDK}/cmake-shell-linux
WORKING_DIRECTORY ${MIDDLEWARE_SOURCE_PATH}/StateMachine
)
add_custom_command(
TARGET ${TARGET_NAME}
PRE_BUILD
COMMAND make StateMahince_code_check
WORKING_DIRECTORY ${PROJECT_ROOT_PATH}/cmake-shell-linux/
)
endif()

View File

@ -0,0 +1,26 @@
# 1. 层次状态机
   层次状态机在事件队列的基础上进行状态管理,使得业务逻辑耦合度非常低。
## 1.1. 开源代码
   移植了鸿蒙开源项目当中的层次状态机代码进行二次封装改造而成。
源码目录:
```
middleware/
├── CMakeLists.txt
└── StateMachine // 状态机中间件
├── CMakeLists.txt
├── include
│   └── IStateMachine.h
├── README.md
└── src
├── IStateMachine.cpp
├── OpenHarmony // 鸿蒙开源的状态机源码目录
├── StateMachineImpl.cpp
├── StateMachineImpl.h
├── StateMachineMakePtr.cpp
└── StateMachineMakePtr.h
```

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2023 JIUYILIAN Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef I_STATE_MACHINE_H
#define I_STATE_MACHINE_H
#include "StatusCode.h"
#include <memory>
class VStateMessage
{
public:
VStateMessage() = default;
virtual ~VStateMessage() = default;
};
class VStateMachineParam
{
public:
VStateMachineParam() = default;
virtual ~VStateMachineParam() = default;
virtual int GetMessageName() const = 0;
virtual const std::shared_ptr<VStateMessage> &GetMessageObj(void) const = 0;
};
class State
{
public:
explicit State(const std::string &name) : mStateName(name) {}
virtual ~State() = default;
public:
virtual void GoInState() = 0;
virtual void GoOutState() = 0;
virtual bool ExecuteStateMsg(VStateMachineParam *msg) = 0;
std::string GetStateName() { return mStateName; }
private:
std::string mStateName;
};
class VStateMachine
{
public:
VStateMachine() = default;
virtual ~VStateMachine() = default;
virtual bool InitialStateMachine() { return false; }
virtual void StatePlus(State *state, State *upper) {}
virtual void SetFirstState(State *firstState) {}
virtual void StartStateMachine() {}
virtual void SendMessage(int msgName) {}
virtual void StopHandlerThread() {}
virtual void SendMessage(int msgName, const std::shared_ptr<VStateMessage> &messageObj) {}
virtual void MessageExecutedLater(int msgName, const std::shared_ptr<VStateMessage> &messageObj, int64_t delayTimeMs) {}
virtual void SwitchState(State *targetState) {}
virtual void StopTimer(int timerName) {}
virtual void DelayMessage(VStateMachineParam *msg) {}
};
class IStateMachine
{
public:
IStateMachine() = default;
virtual ~IStateMachine() = default;
static std::shared_ptr<IStateMachine> &GetInstance(std::shared_ptr<IStateMachine> *impl = nullptr);
virtual const StatusCode CreateStateMachine(std::shared_ptr<VStateMachine> &stateMachine)
{
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
}
};
bool CreateStateMachine(void);
#endif

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2023 JIUYILIAN Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "IStateMachine.h"
#include "ILog.h"
#include <thread>
std::shared_ptr<IStateMachine> &IStateMachine::GetInstance(std::shared_ptr<IStateMachine> *impl)
{
static std::shared_ptr<IStateMachine> instance = std::make_shared<IStateMachine>();
static bool instanceChanging = false;
if (impl && false == instanceChanging)
{
instanceChanging = true;
if (instance.use_count() == 1)
{
LogInfo("Instance change succeed.\n");
instance = *impl;
}
else
{
LogError("Instance change failed, using by some one.\n");
}
instanceChanging = false;
}
if (instanceChanging)
{
static std::shared_ptr<IStateMachine> tmporaryInstance = std::make_shared<IStateMachine>();
return tmporaryInstance;
}
return instance;
}

View File

@ -0,0 +1,215 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "handler.h"
#include <iostream>
#include <sys/time.h>
#include "ILog.h"
#undef LOG_TAG
#define LOG_TAG "OHWIFI_HANDLER"
// namespace OHOS {
// namespace Wifi {
Handler::Handler() : pMyQueue(nullptr), handleThread(0), isRunning(true)
{}
Handler::~Handler()
{
LogInfo("Handler::~Handler\n");
StopHandlerThread();
return;
}
bool Handler::InitialHandler()
{
if (handleThread != 0) {
return true;
}
if (pMyQueue == nullptr) {
pMyQueue = std::make_unique<MessageQueue>();
if (pMyQueue == nullptr) {
LogError("pMyQueue alloc failed.\n");
return false;
}
}
int ret = pthread_create(&handleThread, nullptr, RunHandleThreadFunc, this);
if (ret < 0) {
LogError("pthread_create failed.\n");
return false;
}
return true;
}
void Handler::StopHandlerThread()
{
LogInfo("Handler::StopHandlerThread\n");
if (isRunning) {
isRunning = false;
if (pMyQueue != nullptr) {
pMyQueue->StopQueueLoop();
}
if (handleThread != 0) {
pthread_join(handleThread, nullptr);
}
}
return;
}
void *Handler::RunHandleThreadFunc(void *pInstance)
{
if (pInstance == nullptr) {
LogError("pInstance is null.\n");
return nullptr;
}
Handler *pHandler = (Handler *)pInstance;
pHandler->GetAndDistributeMessage();
return nullptr;
}
void Handler::GetAndDistributeMessage()
{
if (pMyQueue == nullptr) {
LogError("pMyQueue is null.\n");
return;
}
while (isRunning) {
InternalMessage *msg = pMyQueue->GetNextMessage();
if (msg == nullptr) {
LogError("GetNextMessage failed.\n");
continue;
}
DistributeMessage(msg);
MessageManage::GetInstance().ReclaimMsg(msg);
}
return;
}
void Handler::SendMessage(InternalMessage *msg)
{
if (msg == nullptr) {
LogError("Handler::SendMessage: msg is null.\n");
return;
}
// LogInfo("Handler::SendMessage msg:%d\n", msg->GetMessageName());
MessageExecutedLater(msg, 0);
return;
}
void Handler::MessageExecutedLater(InternalMessage *msg, int64_t delayTimeMs)
{
if (msg == nullptr) {
LogError("Handler::MessageExecutedLater: msg is null.\n");
return;
}
// LogInfo("Handler::MessageExecutedLater msg:%d\n", msg->GetMessageName());
int64_t delayTime = delayTimeMs;
if (delayTime < 0) {
delayTime = 0;
}
/* Obtains the current time, accurate to milliseconds. */
struct timeval curTime = {0, 0};
if (gettimeofday(&curTime, nullptr) != 0) {
LogError("gettimeofday failed.\n");
MessageManage::GetInstance().ReclaimMsg(msg);
return;
}
int64_t nowTime = static_cast<int64_t>(curTime.tv_sec) * USEC_1000 + curTime.tv_usec / USEC_1000;
MessageExecutedAtTime(msg, nowTime + delayTime);
return;
}
void Handler::MessageExecutedAtTime(InternalMessage *msg, int64_t execTime)
{
if (msg == nullptr) {
LogError("Handler::MessageExecutedAtTime: msg is null.\n");
return;
}
// LogInfo("Handler::MessageExecutedAtTime msg: %d\n", msg->GetMessageName());
if (pMyQueue == nullptr) {
LogError("pMyQueue is null.\n");
MessageManage::GetInstance().ReclaimMsg(msg);
return;
}
if (pMyQueue->AddMessageToQueue(msg, execTime) != true) {
LogError("AddMessageToQueue failed.\n");
return;
}
return;
}
void Handler::PlaceMessageTopOfQueue(InternalMessage *msg)
{
if (msg == nullptr) {
LogError("Handler::PlaceMessageTopOfQueue: msg is null.\n");
return;
}
// LogInfo("Handler::PlaceMessageTopOfQueue msg: %d\n", msg->GetMessageName());
if (pMyQueue == nullptr) {
LogError("pMyQueue is null.\n");
MessageManage::GetInstance().ReclaimMsg(msg);
return;
}
if (!pMyQueue->AddMessageToQueue(msg, 0)) {
LogError("AddMessageToQueue failed.\n");
return;
}
return;
}
void Handler::DeleteMessageFromQueue(int messageName)
{
// LogInfo("Handler::DeleteMessageFromQueue msg is: %d\n", messageName);
if (pMyQueue == nullptr) {
LogError("pMyQueue is null.\n");
return;
}
if (!pMyQueue->DeleteMessageFromQueue(messageName)) {
LogError("DeleteMessageFromQueue failed.\n");
return;
}
return;
}
void Handler::DistributeMessage(InternalMessage *msg)
{
if (msg == nullptr) {
return;
}
ExecuteMessage(msg);
return;
}
// } // namespace Wifi
// } // namespace OHOS

View File

@ -0,0 +1,135 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_HANDLER_H
#define OHOS_HANDLER_H
#include <pthread.h>
#include "internal_message.h"
#include "message_queue.h"
// namespace OHOS {
// namespace Wifi {
const int USEC_1000 = 1000;
class Handler {
public:
/**
* @Description : Construct a new Handler:: Handler object.
*
*/
Handler();
/**
* @Description : Destroy the Handler:: Handler object.
*
*/
virtual ~Handler();
/**
* @Description : Initialize Handler
*
* @return true : Initialize Handler success, false: Initialize Handler failed.
*/
bool InitialHandler();
/**
* @Description : Thread processing function
*
* @param pInstance - Handler Instance pointer.[in]
*/
static void *RunHandleThreadFunc(void *pInstance);
/**
* @Description :Stop the thread for obtaining messages.
*
*/
void StopHandlerThread();
/**
* @Description : Send a message and place the message in the message queue.
*
* @param msg - Message to be sent.[in]
*/
void SendMessage(InternalMessage *msg);
/**
* @Description : Send a message, place the message in the message queue, and
process the message after delayTimeMs is delayed.
*
* @param msg - Message to be sent.[in]
* @param delayTimeMs - Delay Time.[in]
*/
void MessageExecutedLater(InternalMessage *msg, int64_t delayTimeMs);
/**
* @Description : Send a message, place the message in the message queue, and
process the message at the execTime time point.
*
* @param msg - Message to be sent.[in]
* @param execTime - Time when a message is processed.[in]
*/
void MessageExecutedAtTime(InternalMessage *msg, int64_t execTime);
/**
* @Description : Send a message and place the message at the top of the message queue.
*
* @param msg - Message to be sent.[in]
*/
void PlaceMessageTopOfQueue(InternalMessage *msg);
/**
* @Description : Delete messages from the queue.
*
* @param messageName - Name of the message to be deleted.[in]
*/
void DeleteMessageFromQueue(int messageName);
/**
* @Description : Distributing Messages.
*
* @param msg - Messages to be processed.[in]
*/
void DistributeMessage(InternalMessage *msg);
/**
* @Description : Invoke the ExecuteStateMsg interface of the current state
to process messages sent to the state machine. The entry/exit
of the state machine is also called, and the delayed message
is put back into queue when transitioning to a new state.
*
* @param msg - Messages.[in]
*/
virtual void ExecuteMessage(InternalMessage *msg) = 0;
/**
* @Description : Obtains messages from the message queue, distributes the
messages, and recycles the messages.
*
*/
void GetAndDistributeMessage();
private:
/* message queue. */
std::unique_ptr<MessageQueue> pMyQueue;
/* Thread handle. */
pthread_t handleThread;
/* Running flag. */
bool isRunning;
};
// } // namespace Wifi
// } // namespace OHOS
#endif

View File

@ -0,0 +1,332 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "internal_message.h"
// #include "securec.h"
#include "ILog.h"
#undef LOG_TAG
#define LOG_TAG "OHWIFI_INTERNAL_MESSAGE"
// namespace OHOS {
// namespace Wifi {
void MessageBody::SaveIntData(int data)
{
intArray_.push_back(data);
return;
}
void MessageBody::SaveStringData(std::string data)
{
stringArray_.push_back(data);
return;
}
int MessageBody::GetIntData()
{
if (intArray_.empty()) {
LogError("intArray is null.\n");
return 0;
}
int tmp = intArray_.front();
intArray_.pop_front();
return tmp;
}
std::string MessageBody::GetStringData()
{
std::string tmp;
if (stringArray_.empty()) {
LogError("stringArray is null.\n");
return tmp;
}
tmp = stringArray_.front();
stringArray_.pop_front();
return tmp;
}
void MessageBody::ClearAllData()
{
intArray_.clear();
stringArray_.clear();
return;
}
void MessageBody::CopyMessageBody(const MessageBody &origBody)
{
intArray_.assign(origBody.intArray_.begin(), origBody.intArray_.end());
stringArray_.assign(origBody.stringArray_.begin(), origBody.stringArray_.end());
return;
}
InternalMessage::InternalMessage()
: mMsgName(0),
mParam1(0),
mParam2(0),
pNextMsg(nullptr),
mHandleTime(0)
{}
InternalMessage::~InternalMessage()
{
}
int InternalMessage::GetMessageName() const
{
return mMsgName;
}
int InternalMessage::GetParam1() const
{
return mParam1;
}
int InternalMessage::GetParam2() const
{
return mParam2;
}
int InternalMessage::GetIntFromMessage()
{
return mMessageBody.GetIntData();
}
std::string InternalMessage::GetStringFromMessage()
{
return mMessageBody.GetStringData();
}
const MessageBody &InternalMessage::GetMessageBody() const
{
return mMessageBody;
}
void InternalMessage::CopyMessageBody(const MessageBody &origBody)
{
mMessageBody.CopyMessageBody(origBody);
return;
}
InternalMessage *InternalMessage::GetNextMsg() const
{
return pNextMsg;
}
int64_t InternalMessage::GetHandleTime() const
{
return mHandleTime;
}
void InternalMessage::SetMessageName(int msgName)
{
mMsgName = msgName;
return;
}
void InternalMessage::SetParam1(int param1)
{
mParam1 = param1;
return;
}
void InternalMessage::SetParam2(int param2)
{
mParam2 = param2;
return;
}
void InternalMessage::ReleaseMessageObj()
{
mMessageObj.reset();
return;
}
void InternalMessage::AddIntMessageBody(int data)
{
mMessageBody.SaveIntData(data);
return;
}
void InternalMessage::AddStringMessageBody(std::string data)
{
mMessageBody.SaveStringData(data);
return;
}
void InternalMessage::ClearMessageBody()
{
mMessageBody.ClearAllData();
return;
}
void InternalMessage::SetNextMsg(InternalMessage *nextMsg)
{
pNextMsg = nextMsg;
return;
}
void InternalMessage::SetHandleTime(int64_t time)
{
mHandleTime = time;
return;
}
std::unique_ptr<MessageManage> MessageManage::msgManage;
MessageManage &MessageManage::GetInstance()
{
if (msgManage.get() == nullptr) {
msgManage = std::make_unique<MessageManage>();
}
return *msgManage;
}
MessageManage::MessageManage() : pMsgPool(nullptr), mMsgPoolSize(0)
{}
MessageManage::~MessageManage()
{
ReleasePool();
return;
}
InternalMessage *MessageManage::CreateMessage()
{
{
std::unique_lock<std::mutex> lock(mPoolMutex);
if (pMsgPool != nullptr) {
InternalMessage *m = pMsgPool;
pMsgPool = m->GetNextMsg();
m->SetNextMsg(nullptr);
mMsgPoolSize--;
return m;
}
}
auto pMessage = new (std::nothrow) InternalMessage();
return pMessage;
}
InternalMessage *MessageManage::CreateMessage(const InternalMessage *orig)
{
InternalMessage *m = CreateMessage();
if (m == nullptr) {
return nullptr;
}
m->SetMessageName(orig->GetMessageName());
m->SetParam1(orig->GetParam1());
m->SetParam2(orig->GetParam2());
m->SetMessageObj(orig->GetMessageObj());
m->CopyMessageBody(orig->GetMessageBody());
return m;
}
InternalMessage *MessageManage::CreateMessage(int messageName)
{
InternalMessage *m = CreateMessage();
if (m == nullptr) {
return nullptr;
}
m->SetMessageName(messageName);
return m;
}
InternalMessage *MessageManage::CreateMessage(int messageName, const std::shared_ptr<VStateMessage> &messageObj)
{
InternalMessage *m = CreateMessage();
if (m == nullptr) {
return nullptr;
}
m->SetMessageName(messageName);
m->SetMessageObj(messageObj);
return m;
}
InternalMessage *MessageManage::CreateMessage(int messageName, int param1, int param2)
{
InternalMessage *m = CreateMessage();
if (m == nullptr) {
return nullptr;
}
m->SetMessageName(messageName);
m->SetParam1(param1);
m->SetParam2(param2);
return m;
}
InternalMessage *MessageManage::CreateMessage(int messageName, int param1, int param2, const std::shared_ptr<VStateMessage> &messageObj)
{
InternalMessage *m = CreateMessage();
if (m == nullptr) {
return nullptr;
}
m->SetMessageName(messageName);
m->SetParam1(param1);
m->SetParam2(param2);
m->SetMessageObj(messageObj);
return m;
}
void MessageManage::ReclaimMsg(InternalMessage *m)
{
if (m == nullptr) {
return;
}
m->SetMessageName(0);
m->SetParam1(0);
m->SetParam2(0);
m->ReleaseMessageObj();
m->ClearMessageBody();
{
std::unique_lock<std::mutex> lock(mPoolMutex);
if (mMsgPoolSize < MAX_MSG_NUM_IN_POOL) {
m->SetNextMsg(pMsgPool);
pMsgPool = m;
mMsgPoolSize++;
return;
}
}
delete m;
m = nullptr;
return;
}
void MessageManage::ReleasePool()
{
std::unique_lock<std::mutex> lock(mPoolMutex);
InternalMessage *current = pMsgPool;
InternalMessage *next = nullptr;
while (current != nullptr) {
next = current->GetNextMsg();
delete current;
current = next;
}
return;
}
// } // namespace Wifi
// } // namespace OHOS

View File

@ -0,0 +1,390 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_INTERNAL_MESSAGE_H
#define OHOS_INTERNAL_MESSAGE_H
#include "IStateMachine.h"
#include <cstring>
#include <list>
#include <memory>
#include <mutex>
#include <string>
// #include <any>
// namespace OHOS {
// namespace Wifi {
const int MAX_POOL_SIZE_INIT = 50;
class MessageBody {
public:
/**
* @Description : Save an Integer Data.
*
* @param data - Integer Data.[in]
*/
void SaveIntData(int data);
/**
* @Description : Save a String Data.
*
* @param data - String Data.[in]
*/
void SaveStringData(std::string data);
/**
* @Description : Get an Integer Data.
*
* @return int
*/
int GetIntData();
/**
* @Description : Get a String Data.
*
* @return std::string
*/
std::string GetStringData();
/**
* @Description : Clear all Data.
*
*/
void ClearAllData();
/**
* @Description : Copy a message body.
*
* @param origBody - Source Message Body.[in]
*/
void CopyMessageBody(const MessageBody &origBody);
private:
/* Integer data. */
std::list<int> intArray_;
/* String data. */
std::list<std::string> stringArray_;
};
class InternalMessage : public VStateMachineParam {
public:
/**
* @Description : Construct a new Internal Message object.
*
*/
InternalMessage();
/**
* @Description Destroy the Internal Message object.
*
*/
~InternalMessage();
/**
* @Description : Get message name.
*
* @return int
*/
int GetMessageName() const override;
/**
* @Description : Obtains the first parameter in the message body.
*
* @return int
*/
int GetParam1() const;
/**
* @Description : Obtains the second parameter in the message body.
*
* @return int
*/
int GetParam2() const;
/**
* @Description : Obtains Integer data from message.
*
* @return int
*/
int GetIntFromMessage();
/**
* @Description : Obtains Sting data from message.
*
* @return std::string
*/
std::string GetStringFromMessage();
/**
* @Description : Obtains message body.
*
* @return MessageBody&
*/
const MessageBody &GetMessageBody() const;
/**
* @Description : Copy message body.
*
* @param origBody - Source Message Body.[in]
*/
void CopyMessageBody(const MessageBody &origBody);
/**
* @Description : Get next message.
*
* @return InternalMessage*
*/
InternalMessage *GetNextMsg() const;
/**
* @Description : Obtains time.
*
* @return int64_t
*/
int64_t GetHandleTime() const;
/**
* @Description : Set message name.
*
* @param msgName - Message name.[in]
*/
void SetMessageName(int msgName);
/**
* @Description : Set the first parameter in the message body.
*
* @param param1 - The first parameter.[in]
*/
void SetParam1(int param1);
/**
* @Description : Set the second parameter in the message body.
*
* @param param2 - The second parameter.[in]
*/
void SetParam2(int param2);
/**
* @DescriptionSet the Message Obj object - brief
* @tparam - T Custom type to be set
* @param messageObj - User-defined data to be set
*/
// template<typename T>
// void SetMessageObj(const T &messageObj)
// {
// mMessageObj = messageObj;
// }
/**
* @DescriptionSet the Message Obj object - brief
* @tparam - T Custom type to be set
* @param messageObj - User-defined data to be set
*/
// template<typename T>
// void SetMessageObj(T &&messageObj)
// {
// mMessageObj = T(messageObj);
// }
void SetMessageObj(const std::shared_ptr<VStateMessage> &messageObj)
{
mMessageObj = messageObj;
}
/**
* @DescriptionGet the Message Obj object
* @tparam - T Custom type to be set
* @param messageObj - Gets data of an actual specific object.
* @return - bool true:success   false:failed  
*/
// template<typename T>
// bool GetMessageObj(T &messageObj) const
// {
// messageObj = std::any_cast<const T &>(mMessageObj);
// return true;
// }
bool GetMessageObj(std::shared_ptr<VStateMessage> &messageObj) const
{
// TODO:
// messageObj = std::any_cast<const T &>(mMessageObj);
return true;
}
// const std::any &GetMessageObj(void) const
// {
// return mMessageObj;
// }
const std::shared_ptr<VStateMessage> &GetMessageObj(void) const override
{
return mMessageObj;
}
/**
* @Description : Release Message Object.
*
*/
void ReleaseMessageObj();
/**
* @Description : Add integer message body.
*
* @param data - Integer data.[in]
*/
void AddIntMessageBody(int data);
/**
* @Description : Add string message body.
*
* @param data - String data.[in]
*/
void AddStringMessageBody(std::string data);
/**
* @Description : Clear message body.
*
*/
void ClearMessageBody();
/**
* @Description : Sets next message.
*
* @param next - The next message.[in]
*/
void SetNextMsg(InternalMessage *nextMsg);
/**
* @Description : Set the time.
*
* @param time - Time.[in]
*/
void SetHandleTime(int64_t time);
private:
/* Message Name */
int mMsgName;
/* Parameter 1 */
int mParam1;
/* Parameter 2 */
int mParam2;
/* any message obj. */
// std::any mMessageObj;
std::shared_ptr<VStateMessage> mMessageObj;
/* Message bodies that cannot be directly copied */
MessageBody mMessageBody;
/* Next message in the resource pool or message queue */
InternalMessage *pNextMsg;
/* Message execution time */
int64_t mHandleTime;
};
class MessageManage {
public:
/**
* @Description : Obtains a single instance.
*
* @return MessageManage&
*/
static MessageManage &GetInstance();
/**
* @Description : Message obtaining function.
*
* @return InternalMessage*
*/
InternalMessage *CreateMessage();
/**
* @Description : Obtain original messages.
*
* @param orig - Original messages.[in]
* @return InternalMessage*
*/
InternalMessage *CreateMessage(const InternalMessage *orig);
/**
* @Description : Obtains the message name.
*
* @param messageName - Message name.[in]
* @return InternalMessage*
*/
InternalMessage *CreateMessage(int messageName);
/**
* @Description :Obtaining Message Information.
*
* @param messageName - Message name.[in]
* @param messageObj - Message pointer.[in]
* @return InternalMessage*
*/
InternalMessage *CreateMessage(int messageName, const std::shared_ptr<VStateMessage> &messageObj);
/**
* @Description : Obtaining Message Information.
*
* @param messageName - Message name.[in]
* @param param1 - param1.[in]
* @param param2 - param2.[in]
* @return InternalMessage*
*/
InternalMessage *CreateMessage(int messageName, int param1, int param2);
/**
* @Description : Obtaining Message Information.
*
* @param messageName - Message name.[in]
* @param param1 - param1.[in]
* @param param2 - param2.[in]
* @param messageObj - Message pointer.[in]
* @return InternalMessage*
*/
InternalMessage *CreateMessage(int messageName, int param1, int param2, const std::shared_ptr<VStateMessage> &messageObj);
/**
* @Description :Recycle message.
*
* @param m - message.[in]
*/
void ReclaimMsg(InternalMessage *m);
/**
* @Description : Release pool.
*
*/
void ReleasePool();
/**
* @Description : Construct a new Message Manage object.
*
*/
MessageManage();
/**
* @Description : Destroy the Message Manage object.
*
*/
~MessageManage();
private:
/* Maximum number of messages in the message resource pool */
const int MAX_MSG_NUM_IN_POOL = 50;
/* Message resource pool */
InternalMessage *pMsgPool;
/* Number of messages in the message resource pool */
int mMsgPoolSize;
/* Mutex for operating the message resource pool */
std::mutex mPoolMutex;
static std::unique_ptr<MessageManage> msgManage;
};
// } // namespace Wifi
// } // namespace OHOS
#endif

View File

@ -0,0 +1,190 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "message_queue.h"
#include <sys/time.h>
#include "ILog.h"
// #include "wifi_errcode.h"
#undef LOG_TAG
#define LOG_TAG "OHWIFI_MESSAGE_QUEUE"
// namespace OHOS {
// namespace Wifi {
MessageQueue::MessageQueue() : pMessageQueue(nullptr), mIsBlocked(false), mNeedQuit(false)
{}
MessageQueue::~MessageQueue()
{
LogInfo("MessageQueue::~MessageQueue\n");
/* Releasing Messages in a Queue */
std::unique_lock<std::mutex> lock(mMtxQueue);
InternalMessage *current = pMessageQueue;
InternalMessage *next = nullptr;
while (current != nullptr) {
next = current->GetNextMsg();
delete current;
current = next;
}
return;
}
bool MessageQueue::AddMessageToQueue(InternalMessage *message, int64_t handleTime)
{
if (message == nullptr) {
LogError("message is null.\n");
return false;
}
if (mNeedQuit) {
MessageManage::GetInstance().ReclaimMsg(message);
LogError("Already quit the message queue.\n");
return false;
}
message->SetHandleTime(handleTime);
bool needWake = false;
/*
* If the queue is empty, the current message needs to be executed
* immediately, or the execution time is earlier than the queue header, the
* message is placed in the queue header and is woken up when the queue is
* blocked.
*/
{
std::unique_lock<std::mutex> lck(mMtxQueue);
InternalMessage *pTop = pMessageQueue;
if (pTop == nullptr || handleTime == 0 || handleTime < pTop->GetHandleTime()) {
message->SetNextMsg(pTop);
pMessageQueue = message;
needWake = mIsBlocked;
/* Inserts messages in the middle of the queue based on the execution time. */
} else {
InternalMessage *pPrev = nullptr;
InternalMessage *pCurrent = pTop;
while (pCurrent != nullptr) {
pPrev = pCurrent;
pCurrent = pCurrent->GetNextMsg();
if (pCurrent == nullptr || handleTime < pCurrent->GetHandleTime()) {
message->SetNextMsg(pCurrent);
pPrev->SetNextMsg(message);
break;
}
}
}
}
/* Wake up the process. */
if (needWake) {
std::unique_lock<std::mutex> lck(mMtxBlock);
mCvQueue.notify_all();
mIsBlocked = false;
}
return true;
}
bool MessageQueue::DeleteMessageFromQueue(int messageName)
{
std::unique_lock<std::mutex> lck(mMtxQueue);
InternalMessage *pTop = pMessageQueue;
if (pTop == nullptr) {
return true;
}
InternalMessage *pCurrent = pTop;
while (pCurrent != nullptr) {
InternalMessage *pPrev = pCurrent;
pCurrent = pCurrent->GetNextMsg();
if ((pCurrent != nullptr) && (pCurrent->GetMessageName() == messageName)) {
InternalMessage *pNextMsg = pCurrent->GetNextMsg();
pPrev->SetNextMsg(pNextMsg);
MessageManage::GetInstance().ReclaimMsg(pCurrent);
pCurrent = pNextMsg;
}
}
if (pTop->GetMessageName() == messageName) {
pMessageQueue = pTop->GetNextMsg();
MessageManage::GetInstance().ReclaimMsg(pTop);
}
return true;
}
InternalMessage *MessageQueue::GetNextMessage()
{
// LogInfo("MessageQueue::GetNextMessage\n");
int nextBlockTime = 0;
while (!mNeedQuit) {
/* Obtains the current time, accurate to milliseconds. */
struct timeval curTime = {0, 0};
if (gettimeofday(&curTime, nullptr) != 0) {
LogError("gettimeofday failed.\n");
return nullptr;
}
int64_t nowTime = static_cast<int64_t>(curTime.tv_sec) * TIME_USEC_1000 + curTime.tv_usec / TIME_USEC_1000;
{
std::unique_lock<std::mutex> lck(mMtxQueue);
InternalMessage *curMsg = pMessageQueue;
mIsBlocked = true;
if (curMsg != nullptr) {
if (nowTime < curMsg->GetHandleTime()) {
/* The execution time of the first message is not reached.
The remaining time is blocked here. */
nextBlockTime = curMsg->GetHandleTime() - nowTime;
} else {
/* Return the first message. */
mIsBlocked = false;
pMessageQueue = curMsg->GetNextMsg();
curMsg->SetNextMsg(nullptr);
return curMsg;
}
} else {
/* If there's no message, check it every 30 seconds. */
nextBlockTime = TIME_INTERVAL;
}
}
std::unique_lock<std::mutex> lck(mMtxBlock);
if (mIsBlocked && (!mNeedQuit)) {
if (mCvQueue.wait_for(lck, std::chrono::milliseconds(nextBlockTime)) == std::cv_status::timeout) {
// LogInfo("mCvQueue timeout.\n");
} else {
// LogInfo("Wake up.\n");
}
}
mIsBlocked = false;
}
LogError("Already quit the message queue.\n");
return nullptr;
}
void MessageQueue::StopQueueLoop()
{
mNeedQuit = true;
if (mIsBlocked) {
std::unique_lock<std::mutex> lck(mMtxBlock);
mCvQueue.notify_all();
mIsBlocked = false;
}
return;
}
// } // namespace Wifi
// } // namespace OHOS

View File

@ -0,0 +1,88 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_MESSAGE_QUEUE_H
#define OHOS_MESSAGE_QUEUE_H
#include <chrono>
#include <condition_variable>
#include <mutex>
#include "internal_message.h"
// namespace OHOS {
// namespace Wifi {
#define TIME_USEC_1000 1000
#define TIME_INTERVAL 30000
class MessageQueue {
public:
/**
* @Description : Construct a new Message Queue object.
*
*/
MessageQueue();
/**
* @Description : Destroy the Message Queue object.
*
*/
~MessageQueue();
/**
* @Description : Inserting Messages into Queues.
*
* @param message - Message to be inserted.[in]
* @param handleTime - Message execution time.[in]
* @return true : success, false : failed.
*/
bool AddMessageToQueue(InternalMessage *message, int64_t handleTime);
/**
* @Description : Delete messages from the queue.
*
* @param messageName - Name of the message to be deleted.[in]
* @return true : success, false : failed.
*/
bool DeleteMessageFromQueue(int messageName);
/**
* @Description : Obtain messages from the queue for processing.
* If no message is found, the system blocks the messages.
*
*/
InternalMessage *GetNextMessage();
/**
* @Description : Obtain messages from the queue for processing.
* If no message is found, the system blocks the messages.
*/
void StopQueueLoop();
private:
/* Message Queuing */
InternalMessage *pMessageQueue;
/* No messages to be executed, blocking */
bool mIsBlocked;
/* Exit Loop */
bool mNeedQuit;
/* Thread lock of operation queue */
std::mutex mMtxQueue;
/* Blocked thread lock */
std::mutex mMtxBlock;
/* blocking condition variable */
std::condition_variable mCvQueue;
};
// } // namespace Wifi
// } // namespace OHOS
#endif

View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "IStateMachine.h"
#undef LOG_TAG
#define LOG_TAG "OHWIFI_STATE"
// namespace OHOS {
// namespace Wifi {
// State::State(const std::string &name) : mStateName(name)
// {}
// State::~State()
// {}
// std::string State::GetStateName()
// {
// return mStateName;
// }
// } // namespace Wifi
// } // namespace OHOS

View File

@ -0,0 +1,26 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_STATE_H
#define OHOS_STATE_H
#include <iostream>
#include "message_queue.h"
// namespace OHOS {
// namespace Wifi {
// } // namespace Wifi
// } // namespace OHOS
#endif

View File

@ -0,0 +1,686 @@
/*
* Copyright (C) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <inttypes.h>
#include "state_machine.h"
#include "ILog.h"
#undef LOG_TAG
#define LOG_TAG "OHWIFI_STATE_MACHINE"
// namespace OHOS {
// namespace Wifi {
static const int SM_INIT_CMD = -2;
StateMachine::StateMachine(const std::string &name) : pStateMachineHandler(nullptr), mStateName(name)
{}
StateMachine::~StateMachine()
{
LogInfo("StateMachine::~StateMachine\n");
if (pStateMachineHandler != nullptr) {
delete pStateMachineHandler;
pStateMachineHandler = nullptr;
}
}
bool StateMachine::InitialStateMachine()
{
pStateMachineHandler = new (std::nothrow) StateMachineHandler(this);
if (pStateMachineHandler == nullptr) {
LogError("pStateMachineHandler alloc failed.\n");
return false;
}
if (!pStateMachineHandler->InitialSmHandler()) {
LogError("InitialStateMachineHandler failed.\n");
return false;
}
return true;
}
void StateMachine::StartStateMachine()
{
if (pStateMachineHandler == nullptr) {
LogError("Start StateMachine failed, pStateMachineHandler is nullptr!\n");
return;
}
pStateMachineHandler->BuildTreeComplete();
return;
}
void StateMachine::SetHandler(StateMachineHandler *handler)
{
pStateMachineHandler = handler;
}
void StateMachine::NotExecutedMessage(const InternalMessage *msg)
{
if (msg == nullptr) {
return;
}
LogWarning("msg not handled msg:%d\n", msg->GetMessageName());
}
void StateMachine::StatePlus(State *state, State *upper)
{
if (pStateMachineHandler == nullptr) {
LogError("Start StateMachine failed, pStateMachineHandler is nullptr!\n");
return;
}
pStateMachineHandler->StatePlus(state, upper);
}
void StateMachine::StateDelete(State *state)
{
if (pStateMachineHandler == nullptr) {
LogError("Start StateMachine failed, pStateMachineHandler is nullptr!\n");
return;
}
pStateMachineHandler->StateDelete(state);
}
void StateMachine::SetFirstState(State *firstState)
{
if (pStateMachineHandler == nullptr) {
LogError("Start StateMachine failed, pStateMachineHandler is nullptr!\n");
return;
}
pStateMachineHandler->SetFirstState(firstState);
}
void StateMachine::SwitchState(State *targetState)
{
if (pStateMachineHandler == nullptr) {
LogError("Start StateMachine failed, pStateMachineHandler is nullptr!\n");
return;
}
pStateMachineHandler->SwitchState(targetState);
}
void StateMachine::DelayMessage(const InternalMessage *msg)
{
if (pStateMachineHandler == nullptr) {
LogError("Start StateMachine failed, pStateMachineHandler is nullptr!\n");
return;
}
pStateMachineHandler->DelayMessage(msg);
}
void StateMachine::DelayMessage(VStateMachineParam *msg)
{
if (pStateMachineHandler == nullptr) {
LogError("Start StateMachine failed, pStateMachineHandler is nullptr!\n");
return;
}
pStateMachineHandler->DelayMessage((InternalMessage *)msg);
}
void StateMachine::StopHandlerThread()
{
if (pStateMachineHandler == nullptr) {
LogError("Start StateMachine failed, pStateMachineHandler is nullptr!\n");
return;
}
pStateMachineHandler->StopHandlerThread();
}
InternalMessage *StateMachine::CreateMessage()
{
return MessageManage::GetInstance().CreateMessage();
}
InternalMessage *StateMachine::CreateMessage(const InternalMessage *orig)
{
if (orig == nullptr) {
return nullptr;
}
return MessageManage::GetInstance().CreateMessage(orig);
}
InternalMessage *StateMachine::CreateMessage(int msgName)
{
return MessageManage::GetInstance().CreateMessage(msgName);
}
InternalMessage *StateMachine::CreateMessage(int msgName, int param1)
{
return MessageManage::GetInstance().CreateMessage(msgName, param1, 0);
}
InternalMessage *StateMachine::CreateMessage(int msgName, int param1, int param2)
{
return MessageManage::GetInstance().CreateMessage(msgName, param1, param2);
}
InternalMessage *StateMachine::CreateMessage(int msgName, const std::shared_ptr<VStateMessage> &messageObj)
{
return MessageManage::GetInstance().CreateMessage(msgName, messageObj);
}
InternalMessage *StateMachine::CreateMessage(int msgName, int param1, int param2, const std::shared_ptr<VStateMessage> &messageObj)
{
return MessageManage::GetInstance().CreateMessage(msgName, param1, param2, messageObj);
}
void StateMachine::SendMessage(int msgName)
{
pStateMachineHandler->SendMessage(CreateMessage(msgName));
return;
}
void StateMachine::SendMessage(int msgName, int param1)
{
pStateMachineHandler->SendMessage(CreateMessage(msgName, param1));
return;
}
void StateMachine::SendMessage(int msgName, int param1, int param2)
{
pStateMachineHandler->SendMessage(CreateMessage(msgName, param1, param2));
return;
}
void StateMachine::SendMessage(InternalMessage *msg)
{
if (msg == nullptr) {
return;
}
pStateMachineHandler->SendMessage(msg);
return;
}
void StateMachine::SendMessage(int msgName, const std::shared_ptr<VStateMessage> &messageObj)
{
pStateMachineHandler->SendMessage(CreateMessage(msgName, messageObj));
return;
}
void StateMachine::SendMessage(int msgName, int param1, int param2, const std::shared_ptr<VStateMessage> &messageObj)
{
pStateMachineHandler->SendMessage(CreateMessage(msgName, param1, param2, messageObj));
return;
}
void StateMachine::MessageExecutedLater(int msgName, int64_t delayTimeMs)
{
pStateMachineHandler->MessageExecutedLater(CreateMessage(msgName), delayTimeMs);
return;
}
void StateMachine::MessageExecutedLater(int msgName, int param1, int64_t delayTimeMs)
{
pStateMachineHandler->MessageExecutedLater(CreateMessage(msgName, param1), delayTimeMs);
return;
}
void StateMachine::MessageExecutedLater(int msgName, int param1, int param2, int64_t delayTimeMs)
{
pStateMachineHandler->MessageExecutedLater(CreateMessage(msgName, param1, param2), delayTimeMs);
return;
}
void StateMachine::MessageExecutedLater(InternalMessage *msg, int64_t delayTimeMs)
{
pStateMachineHandler->MessageExecutedLater(msg, delayTimeMs);
return;
}
void StateMachine::MessageExecutedLater(int msgName, const std::shared_ptr<VStateMessage> &messageObj, int64_t delayTimeMs)
{
pStateMachineHandler->MessageExecutedLater(CreateMessage(msgName, messageObj), delayTimeMs);
return;
}
void StateMachine::MessageExecutedLater(
int msgName, int param1, int param2, const std::shared_ptr<VStateMessage> &messageObj, int64_t delayTimeMs)
{
pStateMachineHandler->MessageExecutedLater(CreateMessage(msgName, param1, param2, messageObj), delayTimeMs);
return;
}
void StateMachine::StartTimer(int timerName, int64_t interval)
{
// LogInfo("Enter StateMachine::StartTimer, timerName is %d, interval is %d\n", timerName, interval);
MessageExecutedLater(timerName, interval);
return;
}
void StateMachine::StopTimer(int timerName)
{
// LogInfo("Enter StateMachine::StopTimer, timerName is %d.\n", timerName);
pStateMachineHandler->DeleteMessageFromQueue(timerName);
return;
}
StateMachineHandler::StateMachineHandler(StateMachine *pStateMgr)
{
mStateInfoMap.clear();
mStateVector.clear();
mStateVectorTopIndex = -1;
mSequenceStateVector.clear();
mSequenceStateVectorCount = 0;
mDelayedMessages.clear();
pStateMachine = pStateMgr;
pFirstState = nullptr;
pTargetState = nullptr;
mQuitFlag = false;
mBuildCompleteFlag = false;
mSwitchingStateFlag = false;
pCurrentMsg = nullptr;
}
StateMachineHandler::~StateMachineHandler()
{
LogInfo("StateMachineHandler::~StateMachineHandler\n");
StopHandlerThread();
ReleaseDelayedMessages();
ClearWhenQuit();
return;
}
bool StateMachineHandler::InitialSmHandler()
{
if (!InitialHandler()) {
return false;
}
return true;
}
StateInfo *StateMachineHandler::StatePlus(State *state, State *upper)
{
LogInfo("Enter StateMachineHandler::StatePlus function.\n");
StateInfo *upperStateInfo = nullptr;
StateInfoMap::iterator it = mStateInfoMap.begin();
if (upper != nullptr) {
it = mStateInfoMap.find(upper->GetStateName());
if (it != mStateInfoMap.end()) {
upperStateInfo = it->second;
}
if (upperStateInfo == nullptr) {
LogInfo("upperStateInfo is null, add upper first. upper->GetStateName():%s\n",
upper->GetStateName().c_str());
/* Recursively add our upper as it's not been added yet. */
StatePlus(upper, nullptr);
} else {
LogInfo("upperStateInfo is not null, go on.\n");
}
}
StateInfo *stateInfo = nullptr;
it = mStateInfoMap.find(state->GetStateName());
if (it != mStateInfoMap.end()) {
stateInfo = it->second;
}
if (stateInfo == nullptr) {
stateInfo = new (std::nothrow) StateInfo();
if (stateInfo == nullptr) {
LogError("failed to new StateInfo!\n");
return nullptr;
}
mStateInfoMap.insert(StateInfoMap::value_type(state->GetStateName(), stateInfo));
}
/* Validate that we aren't adding the same state in two different hierarchies. */
if (stateInfo->upperStateInfo != nullptr && stateInfo->upperStateInfo != upperStateInfo) {
LogError("The same state cannot be added to two different hierarchies!\n");
}
stateInfo->state = state;
stateInfo->upperStateInfo = upperStateInfo;
stateInfo->active = false;
LogInfo("successfully added a new state!\n");
return stateInfo;
}
void StateMachineHandler::StateDelete(State *state)
{
StateInfoMap::iterator it = mStateInfoMap.find(state->GetStateName());
StateInfo *stateInfo = nullptr;
if (it != mStateInfoMap.end()) {
stateInfo = it->second;
}
if (stateInfo == nullptr || stateInfo->active) {
return;
}
it = mStateInfoMap.begin();
while (it != mStateInfoMap.end()) {
if (it->second->upperStateInfo == stateInfo) {
return;
}
++it;
}
it = mStateInfoMap.find(state->GetStateName());
if (it != mStateInfoMap.end()) {
delete it->second;
it->second = nullptr;
mStateInfoMap.erase(it);
}
}
void StateMachineHandler::SetFirstState(State *firstState)
{
pFirstState = firstState;
}
void StateMachineHandler::BuildTreeComplete()
{
/* Determines the maximum depth of the state hierarchy. */
int maxDepth = 0;
StateInfoMap::iterator it = mStateInfoMap.begin();
while (it != mStateInfoMap.end()) {
int depth = 0;
StateInfo *tempStateInfo = it->second;
while (tempStateInfo != nullptr) {
depth++;
tempStateInfo = tempStateInfo->upperStateInfo;
}
if (maxDepth < depth) {
maxDepth = depth;
}
++it;
}
LogInfo("StateMachineHandler::BuildTreeComplete, maxDepth:%d\n", maxDepth);
mStateVector.resize(maxDepth);
mSequenceStateVector.resize(maxDepth);
BuildStateInitVector();
MessageExecutedAtTime(pStateMachine->CreateMessage(SM_INIT_CMD), 0);
return;
}
void StateMachineHandler::BuildStateInitVector()
{
LogInfo("StateMachineHandler::BuildStateInitVector\n");
if (pFirstState == nullptr) {
LogError("StateMachineHandler::BuildStateInitVector please set initial state first!\n");
return;
}
StateInfoMap::iterator it = mStateInfoMap.find(pFirstState->GetStateName());
StateInfo *startStateInfo = nullptr;
if (it != mStateInfoMap.end()) {
startStateInfo = it->second;
}
for (mSequenceStateVectorCount = 0; startStateInfo != nullptr; mSequenceStateVectorCount++) {
mSequenceStateVector[mSequenceStateVectorCount] = startStateInfo;
startStateInfo = startStateInfo->upperStateInfo;
}
/* Clearing the StateVector. */
mStateVectorTopIndex = -1;
MoveSequenceToStateVector();
}
StateInfo *StateMachineHandler::BuildSequenceStateVector(State *targetState)
{
mSequenceStateVectorCount = 0;
StateInfoMap::iterator it = mStateInfoMap.find(targetState->GetStateName());
StateInfo *curStateInfo = nullptr;
if (it != mStateInfoMap.end()) {
curStateInfo = it->second;
}
if (curStateInfo == nullptr) {
return nullptr;
}
do {
mSequenceStateVector[mSequenceStateVectorCount++] = curStateInfo;
curStateInfo = curStateInfo->upperStateInfo;
} while ((curStateInfo != nullptr) && (!curStateInfo->active));
return curStateInfo;
}
void StateMachineHandler::PlaceDelayedMsgQueueTop()
{
// LogInfo("Enter StateMachineHandler::PlaceDelayedMsgQueueTop.\n");
for (int i = mDelayedMessages.size() - 1; i >= 0; i--) {
InternalMessage *curMsg = mDelayedMessages[i];
if (curMsg == nullptr) {
LogError("StateMachineHandler::PlaceDelayedMsgQueueTop: curMsg is null.\n");
continue;
}
PlaceMessageTopOfQueue(curMsg);
}
mDelayedMessages.clear();
return;
}
void StateMachineHandler::ReleaseDelayedMessages()
{
for (int i = mDelayedMessages.size() - 1; i >= 0; i--) {
InternalMessage *curMsg = mDelayedMessages[i];
if (curMsg != nullptr) {
delete curMsg;
curMsg = nullptr;
}
}
mDelayedMessages.clear();
return;
}
int StateMachineHandler::MoveSequenceToStateVector()
{
// LogInfo("StateMachineHandler::MoveSequenceToStateVector mSequenceStateVectorCount:%d\n",
// mSequenceStateVectorCount);
int newIndex = mStateVectorTopIndex + 1;
int i = mSequenceStateVectorCount - 1;
int j = newIndex;
while (i >= 0) {
mStateVector[j] = mSequenceStateVector[i];
j += 1;
i -= 1;
}
mStateVectorTopIndex = j - 1;
return newIndex;
}
void StateMachineHandler::SwitchState(State *targetState)
{
pTargetState = static_cast<State *>(targetState);
}
void StateMachineHandler::ClearWhenQuit()
{
pStateMachine->SetHandler(nullptr);
pStateMachine = nullptr;
pCurrentMsg = nullptr;
mStateVector.clear();
mSequenceStateVector.clear();
mDelayedMessages.clear();
pFirstState = nullptr;
pTargetState = nullptr;
mQuitFlag = true;
StateInfoMap::iterator it = mStateInfoMap.begin();
while (it != mStateInfoMap.end()) {
delete it->second;
it->second = nullptr;
it = mStateInfoMap.erase(it);
}
mStateInfoMap.clear();
}
void StateMachineHandler::PerformSwitchState(State *msgProcessedState, InternalMessage *msg)
{
if (msgProcessedState == nullptr || msg == nullptr) {
// LogError("poniter is null.\n");
}
State *targetState = pTargetState;
if (targetState != nullptr) {
// LogInfo("StateMachineHandler::PerformSwitchState targetState name is: %s\n",
// targetState->GetStateName().c_str());
while (true) {
StateInfo *commonStateInfo = BuildSequenceStateVector(targetState);
mSwitchingStateFlag = true;
CallTreeStateExits(commonStateInfo);
int stateListEnteringIndex = MoveSequenceToStateVector();
CallTreeStateEnters(stateListEnteringIndex);
PlaceDelayedMsgQueueTop();
if (targetState != pTargetState) {
targetState = pTargetState;
} else {
break;
}
}
pTargetState = nullptr;
}
return;
}
void StateMachineHandler::ExecuteMessage(InternalMessage *msg)
{
if (msg == nullptr) {
return;
}
if (!mQuitFlag) {
if (pStateMachine != nullptr && msg->GetMessageName() != SM_INIT_CMD) {
}
pCurrentMsg = msg;
State *msgProcessedState = nullptr;
if (mBuildCompleteFlag) {
// LogInfo("StateMachineHandler::ExecuteMessage ExecuteTreeStateMsg!\n");
msgProcessedState = ExecuteTreeStateMsg(msg);
} else if (!mBuildCompleteFlag && msg->GetMessageName() == SM_INIT_CMD) {
// LogInfo("StateMachineHandler::ExecuteMessage msg: SM_INIT_CMD\n");
mBuildCompleteFlag = true;
CallTreeStateEnters(0);
} else {
LogError("The start method not called!\n");
}
if (pStateMachine != nullptr) {
PerformSwitchState(msgProcessedState, msg);
} else {
LogError("poniter is null.\n");
}
if (pStateMachine != nullptr && msg->GetMessageName() != SM_INIT_CMD) {
}
}
return;
}
void StateMachineHandler::DelayMessage(const InternalMessage *msg)
{
// LogInfo("Enter StateMachineHandler::DelayMessage.\n");
if (msg == nullptr) {
return;
}
InternalMessage *newMsg = pStateMachine->CreateMessage(msg);
if (newMsg == nullptr) {
LogError("StateMachineHandler::DelayMessage: newMsg is null.\n");
return;
}
mDelayedMessages.push_back(newMsg);
return;
}
State *StateMachineHandler::ExecuteTreeStateMsg(InternalMessage *msg)
{
// LogInfo("StateMachineHandler::ExecuteTreeStateMsg mStateVectorTopIndex:%d\n", mStateVectorTopIndex);
if (msg == nullptr) {
return nullptr;
}
StateInfo *curStateInfo = mStateVector[mStateVectorTopIndex];
if (curStateInfo == nullptr) {
LogError("StateInfo is null.\n");
return nullptr;
}
if (curStateInfo->state) {
LOGI("State machine: %s execute Cmd:%d\n",
curStateInfo->state->GetStateName().c_str(), msg->GetMessageName());
}
// TODO:
while (curStateInfo->state && (!curStateInfo->state->ExecuteStateMsg((VStateMachineParam *)(msg)))) {
curStateInfo = curStateInfo->upperStateInfo;
if (curStateInfo == nullptr) {
pStateMachine->NotExecutedMessage(msg);
break;
}
}
return (curStateInfo != nullptr) ? curStateInfo->state : nullptr;
}
void StateMachineHandler::CallTreeStateExits(StateInfo *commonStateInfo)
{
while ((mStateVectorTopIndex >= 0) && (mStateVector[mStateVectorTopIndex] != commonStateInfo)) {
if (mStateVector[mStateVectorTopIndex] != nullptr) {
State *curState = mStateVector[mStateVectorTopIndex]->state;
if (curState != nullptr) {
curState->GoOutState();
}
mStateVector[mStateVectorTopIndex]->active = false;
}
mStateVectorTopIndex -= 1;
}
}
void StateMachineHandler::CallTreeStateEnters(int index)
{
for (int i = index; i <= mStateVectorTopIndex; i++) {
if (index == mStateVectorTopIndex) {
/* Last enter state for transition. */
mSwitchingStateFlag = false;
}
// LogInfo("StateMachineHandler::CallTreeStateEnters mStateVectorTopIndex:%d, i: %d\n",
// mStateVectorTopIndex,
// i);
if (mStateVector[i] != nullptr && mStateVector[i]->state != nullptr) {
mStateVector[i]->state->GoInState();
mStateVector[i]->active = true;
}
}
/* ensure flag set to false if no methods called. */
mSwitchingStateFlag = false;
}
// } // namespace Wifi
// } // namespace OHOS

View File

@ -0,0 +1,518 @@
/*
* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_STA_MACHINE_H
#define OHOS_STA_MACHINE_H
#include <map>
#include <string>
#include <vector>
#include "handler.h"
#include "message_queue.h"
#include "IStateMachine.h"
// namespace OHOS {
// namespace Wifi {
#define CMD_SET_OPERATIONAL_MODE 1
class StateMachineHandler;
class StateMachine : public VStateMachine
{
public:
/**
* @Description : StateMachine Initialization Function
*
* @return true :success, false : failed.
*/
bool InitialStateMachine() override;
/**
* @Description : Start StateMachine.
*
*/
void StartStateMachine() override;
/**
* @Description : Set Handler.
*
* @param handler - StateMachineHandler instance.[in]
*/
void SetHandler(StateMachineHandler *handler);
/**
* @Description : The Message is not handled.
*
* @param msg - Message object.[in]
*/
void NotExecutedMessage(const InternalMessage *msg);
/**
* @Description Stop Handler Thread.
*
*/
void StopHandlerThread() override;
/**
* @Description : Start the timer.
*
* @param timerName - Timer Name.[in]
* @param interval - Timer duration, in milliseconds.[in]
*/
virtual void StartTimer(int timerName, int64_t interval);
/**
* @Description : Stop the timer.
*
* @param timerName - Timer Name.[in]
*/
virtual void StopTimer(int timerName) override;
/**
* @Description : Construct internal messages.
*
* @return InternalMessage* : Pointer to the constructed internal message.
*/
InternalMessage *CreateMessage();
/**
* @Description : Construct an information message based on
* the original message.
*
* @param orig - Original message.[in]
* @return InternalMessage* : Pointer to the constructed internal message.
*/
InternalMessage *CreateMessage(const InternalMessage *orig);
/**
* @Description : Construct internal messages.
*
* @param msgName - Message Name.[in]
* @return InternalMessage* : Pointer to the constructed internal message.
*/
InternalMessage *CreateMessage(int msgName);
/**
* @Description : Construct internal messages.
*
* @param msgName - Message Name.[in]
* @param param1 - Message parameters.[in]
* @return InternalMessage* : Pointer to the constructed internal message.
*/
InternalMessage *CreateMessage(int msgName, int param1);
/**
* @Description : Construct internal messages.
*
* @param msgName - Message Name.[in]
* @param param1 - Message parameters.[in]
* @param param2 - Message parameters.[in]
* @return InternalMessage* : Pointer to the constructed internal message.
*/
InternalMessage *CreateMessage(int msgName, int param1, int param2);
/**
* @Description : Construct internal messages.
*
* @param msgName - Message Name.[in]
* @param messageObj - User-defined data
* @return InternalMessage* : Pointer to the constructed internal message.
*/
InternalMessage *CreateMessage(int msgName, const std::shared_ptr<VStateMessage> &messageObj);
/**
* @Description : Constructs internal messages.
*
* @param msgName - Message name.[in]
* @param param1 - First Message parameter.[in]
* @param param2 - Second Message parameter.[in]
* @param messageObj - User-defined data
* @return InternalMessage* : Pointer to the constructed internal message.
*/
InternalMessage *CreateMessage(int msgName, int param1, int param2, const std::shared_ptr<VStateMessage> &messageObj);
/**
* @Description : Constructs internal messages and places the
* messages in the message queue of the state machine.
*
* @param msgName - Message name.[in]
*/
virtual void SendMessage(int msgName) override;
/**
* @Description : Constructs internal messages and places the messages
* in the message queue of the state machine.
*
* @param msgName - Message name.[in]
* @param param1 - Message parameter.[in]
*/
virtual void SendMessage(int msgName, int param1);
/**
* @Description : Constructs internal messages and places the messages
* in the message queue of the state machine.
*
* @param msgName - Message name.[in]
* @param param1 - Message parameter.[in]
* @param param2 - Message parameter.[in]
*/
virtual void SendMessage(int msgName, int param1, int param2);
/**
* @Description : Puts messages into the message queue of the state machine.
*
* @param msg - Message to be sent.[in]
*/
virtual void SendMessage(InternalMessage *msg);
/**
* @Description : Puts messages into the message queue of the state machine.
*
* @param msgName - Message Name.[in]
* @param messageObj - User-defined data
*/
virtual void SendMessage(int msgName, const std::shared_ptr<VStateMessage> &messageObj) override;
/**
* @Description : Puts messages into the message queue of the state machine.
*
* @param msgName - Message Name.[in]
* @param param1 - Message parameters.[in]
* @param param2 - Message parameters.[in]
* @param messageObj - User-defined data
*/
virtual void SendMessage(int msgName, int param1, int param2, const std::shared_ptr<VStateMessage> &messageObj);
/**
* @Description Constructs internal messages and places them in the
* message queue of the state machine. The messages are processed
* after the specified delay time.
*
* @param msgName - Message Name.[in]
* @param delayTimeMs - Delay time, in milliseconds.[in]
*/
void MessageExecutedLater(int msgName, int64_t delayTimeMs);
/**
* @Description : Constructs internal messages and places them in the
* message queue of the state machine. The messages are processed
* after the specified delay time.
*
* @param msgName - Message Name.[in]
* @param param1 - Message parameters.[in]
* @param delayTimeMs - Delay time, in milliseconds.[in]
*/
void MessageExecutedLater(int msgName, int param1, int64_t delayTimeMs);
/**
* @Description : Constructs internal messages and places them in the
* message queue of the state machine. The messages are processed
* after the specified delay time.
*
* @param msgName - Message Name.[in]
* @param param1 - Message parameters.[in]
* @param param2 - Message parameters.[in]
* @param delayTimeMs - Delay time, in milliseconds.[in]
*/
void MessageExecutedLater(int msgName, int param1, int param2, int64_t delayTimeMs);
/**
* @Description : Constructs internal messages and places them in the
* message queue of the state machine. The messages are processed
* after the specified delay time.
*
* @param msg - Message to be sent.[in]
* @param delayTimeMs - Delay time, in milliseconds.[in]
*/
void MessageExecutedLater(InternalMessage *msg, int64_t delayTimeMs);
/**
* @Description : Constructs internal messages and places them in the
* message queue of the state machine. The messages are processed
* after the specified delay time.
*
* @param msgName - Message Name.[in]
* @param messageObj -User-defined data
* @param delayTimeMs - Delay time, in milliseconds.[in]
*/
void MessageExecutedLater(int msgName, const std::shared_ptr<VStateMessage> &messageObj, int64_t delayTimeMs) override;
/**
* @Description : Constructs internal messages and places them in the
* message queue of the state machine. The messages are processed
* after the specified delay time.
*
* @param msgName - Message Name.[in]
* @param param1 - Message parameters.[in]
* @param param2 - Message parameters.[in]
* @param messageObj - User-defined data
* @param delayTimeMs - Delay time, in milliseconds.[in]
*/
void MessageExecutedLater(int msgName, int param1, int param2, const std::shared_ptr<VStateMessage> &messageObj, int64_t delayTimeMs);
/**
* @Description : Construct a new State Machine:: State Machine object.
*
* @param name - State name.[in]
*/
explicit StateMachine(const std::string &name);
/**
* @Description : Destroy the State Machine:: State Machine object.
*
*/
virtual ~StateMachine();
protected:
/**
* @Description : Add state.
*
* @param state - state.[in]
* @param upper - upper state.[in]
*/
void StatePlus(State *state, State *upper) override;
/**
* @Description : Remove state.
*
* @param state - state.[in]
*/
void StateDelete(State *state);
/**
* @Description : Set first state.
*
* @param firstState - First state.[in]
*/
void SetFirstState(State *firstState) override;
/**
* @Description : Transition to orther state.
*
* @param targetState - state.[in]
*/
void SwitchState(State *targetState) override;
/**
* @Description : Delay Message.
*
* @param msg - Message object.[in]
*/
void DelayMessage(const InternalMessage *msg);
void DelayMessage(VStateMachineParam *msg) override;
private:
StateMachineHandler *pStateMachineHandler;
std::string mStateName;
};
typedef struct StateInfo
{
State *state;
StateInfo *upperStateInfo;
bool active;
} StateInfo;
class StateMachineHandler : public Handler
{
public:
using StateInfoMap = std::map<std::string, StateInfo *>;
using StateVector = std::vector<StateInfo *>;
using DelayedMessage = std::vector<InternalMessage *>;
/**
* @Description : Construct a new state machine Handler:: StateMachine Handler object.
*
* @param pStateMgr - Handler pointer.[in]
*/
explicit StateMachineHandler(StateMachine *pStateMgr);
/**
* @Description : Destroy the StateMachine Handler:: StateMachine Handler object.
*
*/
~StateMachineHandler();
/**
* @Description : StateMachineHandler Initialization Function.
*
* @return true : success, false : failed.
*/
bool InitialSmHandler();
/**
* @Description : Add a new state.
*
* @param state - State to be added.[in]
* @param upper - upper of state.[in]
* @return StateInfo*
*/
StateInfo *StatePlus(State *state, State *upper);
/**
* @Description : Delete a state.
*
* @param state - State to be deleted.[in]
*/
void StateDelete(State *state);
/**
* @Description : Sets the Initialization State.
*
* @param firstState - Initialization State.[in]
*/
void SetFirstState(State *firstState);
/**
* @Description : State transition function.
*
* @param targetState - Destination State.[in]
*/
void SwitchState(State *targetState);
/**
* @Description : Delay Message Processing Function.
*
* @param msg - Message body pointer.[in]
*/
void DelayMessage(const InternalMessage *msg);
// void DelayMessage(const std::shared_ptr<VStateMessage> &messageObj);
/**
* @Description : The state machine is constructed.
*
*/
void BuildTreeComplete();
private:
/**
* @Description : Sets the initial state sequence.
*
*/
void BuildStateInitVector();
/**
* @Description : Writes the inactive upper states of targetState
* and targetState to the sequenceStateVector list.
*
* @param targetState - Target State Machine.[in]
* @return StateInfo*
*/
StateInfo *BuildSequenceStateVector(State *targetState);
/**
* @Description : Move Delayed Message At Front Of Queue.
*
*/
void PlaceDelayedMsgQueueTop();
/**
* @Description : Release all messages in delayed Messages.
*
*/
void ReleaseDelayedMessages();
/**
* @Description : Fill the status in the sequential status
* list in reverse order.
*
* @return int
*/
int MoveSequenceToStateVector();
/**
* @Description : Invoke the ExecuteStateMsg interface of the current state
* to process messages sent to the state machine. The entry/exit of the
* state machine is also called, and the delayed messagei s put back
* into queue when transitioning to a new state.
*
* @param msg - Messages.[in]
*/
void ExecuteMessage(InternalMessage *msg) override;
/**
* @Description : Clean up After Quitting.
*
*/
void ClearWhenQuit();
/**
* @Description : Performing Status Transitions.
*
* @param msgProcessedState - Message processing status.[in]
* @param msg - Messages.[in]
*/
void PerformSwitchState(State *msgProcessedState, InternalMessage *msg);
/**
* @Description : Process messages. If the current state doesnot process it,
* the upper state processing is called, and so on. If all upper states
* are not processed, invoke the NotExecutedMessage method of the state machine.
*
* @param msg - Message body pointer.[in]
* @return State*
*/
State *ExecuteTreeStateMsg(InternalMessage *msg);
/**
* @Description : Invoke GoOutState() for each state from the first
* state in the list to the public upper state.
*
* @param commonStateInfo - common upper state machine.[in]
*/
void CallTreeStateExits(StateInfo *commonStateInfo);
/**
* @Description : Call the GoInState method from the start state
* index to the top of the state stack.
*
* @param index - Start state index of the
* state machine list.
*/
void CallTreeStateEnters(int index);
private:
/* All state mappings of the state machine */
StateInfoMap mStateInfoMap;
/* From child state to upper state list */
StateVector mStateVector;
/* Top index of mStateVector */
int mStateVectorTopIndex;
/* From upper state to child state list */
StateVector mSequenceStateVector;
/* Top of mSequenceStateVector */
int mSequenceStateVectorCount;
/* Delayed Message Queue */
DelayedMessage mDelayedMessages;
/* State machine instance */
StateMachine *pStateMachine;
/* Initial state */
State *pFirstState;
/* Target Status */
State *pTargetState;
/* StateMachine exit or not */
bool mQuitFlag;
/* Whether the state machine has been built */
bool mBuildCompleteFlag;
/*
* All State exit/enter calls are true before the
* last enter call in the target state.
*/
bool mSwitchingStateFlag;
/* Current Message */
InternalMessage *pCurrentMsg;
};
// } // namespace Wifi
// } // namespace OHOS
#endif

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2023 JIUYILIAN Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "StateMachineImpl.h"
#include "StateMachineMakePtr.h"
const StatusCode StateMachineImpl::CreateStateMachine(std::shared_ptr<VStateMachine> &stateMachine)
{
return StateMachineMakePtr::GetInstance()->CreateStateMachine(stateMachine);
}

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2023 JIUYILIAN Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef STATE_MACHINE_IMPL_H
#define STATE_MACHINE_IMPL_H
#include "IStateMachine.h"
class StateMachineImpl : public IStateMachine
{
public:
StateMachineImpl() = default;
~StateMachineImpl() = default;
const StatusCode CreateStateMachine(std::shared_ptr<VStateMachine> &stateMachine) override;
};
#endif

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2023 JIUYILIAN Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "StateMachineMakePtr.h"
#include "ILog.h"
#include "state_machine.h"
#include "IStateMachine.h"
#include "StateMachineImpl.h"
#include <thread>
bool CreateStateMachine(void)
{
auto instance = std::make_shared<IStateMachine>();
StatusCode code = StateMachineMakePtr::GetInstance()->CreateStateMachine(instance);
if (IsCodeOK(code))
{
LogInfo("State machine instance is ok.\n");
IStateMachine::GetInstance(&instance);
return true;
}
return false;
}
std::shared_ptr<StateMachineMakePtr> &StateMachineMakePtr::GetInstance(std::shared_ptr<StateMachineMakePtr> *impl)
{
static auto instance = std::make_shared<StateMachineMakePtr>();
if (impl)
{
instance = *impl;
}
return instance;
}
StatusCode StateMachineMakePtr::CreateStateMachine(std::shared_ptr<VStateMachine> &stateMachine)
{
// TODO: need a name ?
auto tmp = std::make_shared<StateMachine>("TODO");
if (tmp)
{
stateMachine = std::move(tmp);
return CreateStatusCode(STATUS_CODE_OK);
}
LogError("Create state machine module failed.\n");
return CreateStatusCode(STATUS_CODE_MAKE_SHARED_PTR_FAILED);
}
StatusCode StateMachineMakePtr::CreateStateMachine(std::shared_ptr<IStateMachine> &instance)
{
auto tmp = std::make_shared<StateMachineImpl>();
if (tmp)
{
instance = std::move(tmp);
return CreateStatusCode(STATUS_CODE_OK);
}
LogError("Create state machine module failed.\n");
return CreateStatusCode(STATUS_CODE_MAKE_SHARED_PTR_FAILED);
}

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2023 JIUYILIAN Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef STATE_MACHINE_MAKE_PTR_H
#define STATE_MACHINE_MAKE_PTR_H
#include "StatusCode.h"
#include "IStateMachine.h"
#include <memory>
class StateMachineMakePtr
{
public:
StateMachineMakePtr() = default;
virtual ~StateMachineMakePtr() = default;
static std::shared_ptr<StateMachineMakePtr> &GetInstance(std::shared_ptr<StateMachineMakePtr> *impl = nullptr);
virtual StatusCode CreateStateMachine(std::shared_ptr<VStateMachine> &stateMachine);
virtual StatusCode CreateStateMachine(std::shared_ptr<IStateMachine> &instance);
};
#endif

View File

@ -32,6 +32,13 @@ extern "C"
#define LogWarning(...) GetLogIntance()->printf(GetLogIntance(), __FUNCTION__, __LINE__, LOG_TYPE_WARNING, __VA_ARGS__) #define LogWarning(...) GetLogIntance()->printf(GetLogIntance(), __FUNCTION__, __LINE__, LOG_TYPE_WARNING, __VA_ARGS__)
#define LogError(...) GetLogIntance()->printf(GetLogIntance(), __FUNCTION__, __LINE__, LOG_TYPE_ERROR, __VA_ARGS__) #define LogError(...) GetLogIntance()->printf(GetLogIntance(), __FUNCTION__, __LINE__, LOG_TYPE_ERROR, __VA_ARGS__)
#define LogTrace(...) GetLogIntance()->printf(GetLogIntance(), __FUNCTION__, __LINE__, LOG_TYPE_TRACE, __VA_ARGS__) #define LogTrace(...) GetLogIntance()->printf(GetLogIntance(), __FUNCTION__, __LINE__, LOG_TYPE_TRACE, __VA_ARGS__)
#if 1 // For OpenHarmony log, should delete finally.// TODO:
#define LOGD(...)
#define LOGI(...)
#define LOGW(...)
#define LOGE(...)
#define LOGF(...)
#endif
typedef struct i_log ILog; typedef struct i_log ILog;
typedef struct i_log typedef struct i_log
{ {

View File

@ -11,6 +11,7 @@ extern "C"
STATUS_CODE_NOT_OK, STATUS_CODE_NOT_OK,
STATUS_CODE_VIRTUAL_FUNCTION, STATUS_CODE_VIRTUAL_FUNCTION,
STATUS_CODE_INVALID_PARAMENTER, STATUS_CODE_INVALID_PARAMENTER,
STATUS_CODE_MAKE_SHARED_PTR_FAILED,
STATUS_CODE_END STATUS_CODE_END
}; };
typedef struct status_code StatusCode; typedef struct status_code StatusCode;