[RK1108][Linux3.1]应用笔记 - 状态机(一)

平台 内核版本
RK1108 Linux3.1

结构体相关定义

typedef struct _StMachinePriv {
	Queue *queue;
    pthread_mutex_t mutex;
	StateTable *funcentry;
	StateTableDebug *st_debug;
	void *arg;
	int cur_state;
	int status_run;	
	int table_num;			
}StMachinePriv;

重点看下状态标志:

	typedef struct _StateTable {
		int msg;			// 事件消息
		int cur_state;		// 当前状态
		int next_state;		// 下一状态
		int run;			// 执行处理
	}StateTable;

状态机类定义

	typedef struct _StMachine {
		struct _StMachinePriv *priv;
		int	id;		

		void  *(*initPara)(struct _StMachine *,int size);
		int  (*getCurrentstate)(struct _StMachine *);
		int  (*getCurRun)(struct _StMachine *);
        /* ---------------------------------------------------------------------------*/
        /**
         * @brief 发送异步消息
         *
         * @param 
         * @param msg 消息值
         * @param data 附加数据,需要用initPara初始化
         */
        /* ---------------------------------------------------------------------------*/
		void  (*msgPost)(struct _StMachine *,int msg,void *data);
        /* ---------------------------------------------------------------------------*/
        /**
         * @brief  发送同步消息
         *
         * @param 
         * @param msg 消息值
         * @param data 附加数据,直接传入参数,无需初始化
         *
         * @returns -1为未找到当前消息对应执行动作,其他为执行动作返回值
         */
        /* ---------------------------------------------------------------------------*/
		int  (*msgPostSync)(struct _StMachine *,int msg,void *data);
		int  (*handle)(struct _StMachine *,int result,void *data,void *arg);
		void  (*destroy)(struct _StMachine **);
	}StMachine;

创建状态机

/* ---------------------------------------------------------------------------*/
/**
 * @brief stateMachineCreate 创建状态机
 *
 * @param init_state 初始状态
 * @param state_table 状态机表
 * @param num 状态机表的数量
 * @param id 状态机的ID,区别多个状态机同时运行
 * @param handle 状态机处理,
 *
 * @returns 
 */
/* ---------------------------------------------------------------------------*/
StMachine* stateMachineCreate(int init_state, 
		StateTable *state_table, 
		int num,
		int id,
		int (*handle)(StMachine *This,int result,void *data,void *arg),
		void *arg,
		StateTableDebug *st_debug)
{

	StMachine *This = (StMachine *)calloc(1,sizeof(StMachine));
	This->priv = (StMachinePriv *)calloc(1,sizeof(StMachinePriv));
	This->priv->arg = arg;
	This->priv->funcentry = (StateTable *)state_table;
	This->priv->table_num = num;
	This->priv->cur_state = init_state;
	This->priv->queue = queueCreate("stm",QUEUE_BLOCK,sizeof(MsgData));
	This->priv->st_debug = st_debug;

	pthread_mutexattr_t mutexattr;
	pthread_mutexattr_init(&mutexattr);
    pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE_NP);
    pthread_mutex_init(&This->priv->mutex, &mutexattr);
	pthread_mutexattr_destroy(&mutexattr);

	This->id = id;

	This->msgPost = stmMsgPost;
	This->msgPostSync = stmMsgPostSync;
	This->handle = handle;
	This->initPara = stmInitPara;
	This->getCurrentstate = stmGetCurrentState;
	This->getCurRun = stmGetCurRun;
	This->destroy = stmDestroy;
	createThread(stmThread,This);
	return This;
}

可以看出做了状态机参数的赋值,状态机回调函数的赋值,最后创建状态机处理线程:

static void *stmThread(void *arg)
{
	prctl(PR_SET_NAME, __func__, 0, 0, 0);
    StMachine *stm= (StMachine *)arg;
	MsgData   msg_data;
    while(1) {
		memset(&msg_data,0,sizeof(MsgData));
		stm->priv->queue->get(stm->priv->queue,&msg_data);
        pthread_mutex_lock(&stm->priv->mutex);
		if (stmExecEntry(stm,msg_data.msg))
			stm->handle(stm,1,msg_data.data,stm->priv->arg);
		else
			stm->handle(stm,0,&msg_data.msg,stm->priv->arg);
		if (msg_data.data)
			free(msg_data.data);
        pthread_mutex_unlock(&stm->priv->mutex);
    }
    pthread_exit(NULL);
    return NULL;
}

从上可以看出首先从队列中取出消息,然后状态机执行状态判断和转换:

static int stmExecEntry(StMachine *This,int msg)
{
	int num = This->priv->table_num;
	StateTable *funcentry = This->priv->funcentry;

    for (; num > 0; num--,funcentry++) {
		if (		(msg == funcentry->msg) 
				&& 	(This->priv->cur_state == funcentry->cur_state)) {
			if (This->priv->st_debug) {
				DBG_P("[ST->msg:%s,cur:%s,next:%s,do:%s]\n",
						This->priv->st_debug->ev[msg],
						This->priv->st_debug->st[funcentry->cur_state],
						This->priv->st_debug->st[funcentry->next_state],
						This->priv->st_debug->todo[funcentry->run]);
			}
			This->priv->status_run = funcentry->run ;
			This->priv->cur_state = funcentry->next_state;
			return 1;
		}
	}
    return 0;
}

看下状态机的功能函数

  • 发送异步消息msgPost
  • 发送同步消息msgPostSync
  • 处理函数handle
  • 初始化发送状态机消息时带的参数initPara
  • 获取状态机当前状态getCurrentstate
  • 获取状态机运行getCurRun
  • 摧毁状态机destroy
/**
 * @brief stmMsgPost 状态机发送事件消息
 *
 * @param This
 * @param msg 消息
 * @param data 附加参数
 */
/* ---------------------------------------------------------------------------*/
static void stmMsgPost(StMachine* This,int msg,void *data)
{
	MsgData   msg_data;
	msg_data.msg = msg;
	msg_data.data = data;
	This->priv->queue->post(This->priv->queue,&msg_data);
}
static int stmMsgPostSync(StMachine* This,int msg,void *data)
{
    int ret = -1;
	pthread_mutex_lock(&This->priv->mutex);
    if (stmExecEntry(This,msg)) {
		printf("%s\n",__func__ );
        ret = This->handle(This,1,data,This->priv->arg);
    }
	pthread_mutex_unlock(&This->priv->mutex);
    return ret;
}
/* ---------------------------------------------------------------------------*/
/**
 * @brief stmInitPara 初始化发送状态机消息时带的参数
 *
 * @param This
 * @param size 参数大小
 *
 * @returns 
 */
/* ---------------------------------------------------------------------------*/
static void *stmInitPara(StMachine *This,int size)
{
	void *para = NULL;
	if (size) {
		para = (void *) calloc (1,size);
	}
	return para;
}
/* ---------------------------------------------------------------------------*/
/**
 * @brief stmGetCurrentState 获取状态机当前状态
 *
 * @param This
 *
 * @returns 
 */
/* ---------------------------------------------------------------------------*/
static int stmGetCurrentState(StMachine *This)
{
	return This->priv->cur_state;	
}

static int stmGetCurRun(StMachine *This)
{
	return This->priv->status_run;
}

/* ---------------------------------------------------------------------------*/
/**
 * @brief stmDestroy 销毁状态机
 *
 * @param This
 */
/* ---------------------------------------------------------------------------*/
static void stmDestroy(StMachine **This)
{
	if ((*This)->priv)
		free((*This)->priv);
	if (*This)
		free(*This);
	*This = NULL;	
}

处理函数

我们再看一下我们状态机的处理函数,这里的思想跟中断服务程序有着异曲同工的意义:

static int stmHandle(StMachine *This,int result,void *data,void *arg)
{
	if (result) {
		return stm_do[This->getCurRun(This)].proc(data,(MyVideo *)arg);
	} else {
		return stm_do[DO_FAIL].proc(data,(MyVideo *)arg);
	}
}

首先看下处理函数对应的结构体

typedef struct _StmDo {
	int action;
	int (*proc)(void *data,MyVideo *arg);
}StmDo;
static StmDo stm_do[] =
{
	{DO_FAIL,			stmDoFail},
	{DO_NOTHING,		stmDoNothing},
	{DO_FACE_ON,    	stmDoFaceOn},
	{DO_FACE_OFF,   	stmDoFaceOff},
	{DO_FACE_REGIST,	stmDoFaceRegist},
	{DO_FACE_RECOGNIZER,stmDoFaceRecognizer},
	{DO_TALK_CALLOUT,	stmDoTalkCallout},
	{DO_TALK_CALLOUTALL,stmDoTalkCalloutAll},
	{DO_TALK_CALLIN,	stmDoTalkCallin},
	{DO_TALK_ANSWER,	stmDoTalkAnswer},
	{DO_TALK_HANGUP,	stmDoTalkHangup},
	{DO_TALK_HANGUPALL,	stmDoTalkHangupAll},
	{DO_CAPTURE,		stmDoCapture},
	{DO_CAPTURE_NO_UI,	stmDoCaptureNoUi},
	{DO_RECORD_START,	stmDoRecordStart},
	{DO_RECORD_STOP,	stmDoRecordStop},
	{DO_DELAY_SLEEP,	stmDoDelaySleepTime},

};

应用

stm = stateMachineCreate(ST_IDLE,
			state_table,
			sizeof (state_table) / sizeof ((state_table) [0]),
			0,
			stmHandle,
			my_video,
			&st_debug);
static StateTable state_table[] =
{
	{EV_FACE_ON,		ST_IDLE,	ST_FACE,	DO_FACE_ON},
	{EV_FACE_REGIST,	ST_FACE,	ST_FACE,	DO_FACE_REGIST},
	{EV_FACE_RECOGNIZER,ST_FACE,	ST_FACE,	DO_FACE_RECOGNIZER},
}

状态机引擎

static void* threadVideoTimer(void *arg)
{
	prctl(PR_SET_NAME, __func__, 0, 0, 0);
	while (1) {
		if (talk_peer_dev.call_time) {
			printf("call time:%d\n", talk_peer_dev.call_time);
			if (--talk_peer_dev.call_time == 0) {
				stm->msgPost(stm,EV_TALK_HANGUP,NULL);
			}
		}
		sleep(1);
	}
	return NULL;
}
发布了295 篇原创文章 · 获赞 99 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/qq_33487044/article/details/104691214