事件驱动?逻辑控制?信号槽?

基于回调的事件驱动或者逻辑控制

本文提供了一种单线程编程思路,并简单实现了该思路。

受PLC编程线圈和触点概念的启发。
将程序抽象理解成一条条因果逻辑,即条件和动作。
当条件满足时执行动作。
实现业务逻辑时只需要将条件和动作对应实现。
回过头来一想这不就是QT的信号槽吗?
更一般的概念,程序就是处理输入输出。线圈是输入,触点是输出。信号是输入,槽是输出。条件是输入,动作是输出。概念都是相通的。

本实现特点

1.将条件和动作关联起来管理,区别于一般的事件驱动。
2.使用void指针,条件函数和动作函数都可以有参数。
3.例子里使用数组实现命令表,适合MCU,也可以使用链表。

代码

接口

/*cmd.h*/
#ifndef FILE_CMD_H
# define FILE_CMD_H

# define MAX_CMD_NUM 100

# define CMD_FALSE 0
# define CMD_TRUE (!CMD_FALSE)

typedef unsigned int(*fp_condition_t)(void *);
typedef void (*fp_action_t)(void *);

typedef struct
{
  fp_condition_t cond_cb;//condition
  fp_action_t act_cb;//action
  void* cond_para;
  void* act_para;
}cmd_t;

int cmd_init();
int cmd_add(cmd_t* p_cmd);
int cmd_del(int cmd_id);
int cmd_process();

#endif // FILE_CMD_H

实现

/*cmd.c*/
#include "cmd.h"

# ifndef NULL
#  define NULL ((void*)0)
# endif

cmd_t* cmd_table[MAX_CMD_NUM]={0};

/*初始化清空命令表*/
int cmd_init()
{
  int i = 0;
  for(i = 0;i < MAX_CMD_NUM;i++)
  {
    cmd_table[i] = NULL;
  }
}

/*向命令表中添加命令,成功返回在表中的位置*/
int cmd_add(cmd_t* p_cmd)
{
  int i = 0;
  for(i = 0;i < MAX_CMD_NUM;i++)
  {
    if(NULL == cmd_table[i])
    {
      cmd_table[i]=p_cmd;
      return i;
    }
  }
  return -1;//out of memory
}

/*删除命令*/
int cmd_del(int cmd_id)
{
  cmd_table[cmd_id]=NULL;
}

/*命令处理,遍历命令表,执行满足条件的命令的动作*/
int cmd_process()
{
  int i = 0;

  for(i = 0;i < MAX_CMD_NUM;i++)
  {
    cmd_t* cmd = cmd_table[i];
    if(cmd!= NULL)
    {
      if(cmd->cond_cb != NULL)
      {
        if(CMD_FALSE != cmd->cond_cb(cmd->cond_para))
        {
          if(cmd->act_cb != NULL)
          {
            cmd->act_cb(cmd->act_para);
          }
        }
      }
    }
  }
}

用法

/*main.c*/
#include <stdio.h>
#include "cmd.h"

unsigned int cond_hello(void * p_time)
{
  int time=*(int*)p_time;

  if(time  == 1 )
  {
    return CMD_TRUE;
  }
  return CMD_FALSE;
}

unsigned int cond_bye(void * p_time)
{
  int time=*(int*)p_time;

  if(time == 5 )
  {
    return CMD_TRUE;
  }
  return CMD_FALSE;
}

void act_hello(void * name)
{
  printf("hello %s \n",(char *)name);
}

void act_bye(void * name)
{
  printf("bye %s \n",(char *)name);
}



void main(void)
{
  unsigned int time = 0;
  char* name_ryan = "ryan";
  char* name_Mr_White = "Mr White";


  cmd_t hello_ryan = {.cond_cb = cond_hello,
                      .act_cb = act_hello,
                      .cond_para = &time,
                      .act_para = name_ryan  };

  cmd_t bye_ryan = {.cond_cb=cond_bye,
                    .act_cb=act_bye,
                    .cond_para = &time,
                    .act_para = name_ryan  };

  cmd_t hello_white = {.cond_cb = cond_hello,
                      .act_cb = act_hello,
                      .cond_para = &time,
                      .act_para = name_Mr_White  };

  cmd_t bye_white = {.cond_cb=cond_bye,
                    .act_cb=act_bye,
                    .cond_para = &time,
                    .act_para = name_Mr_White  };


  cmd_init();
  cmd_add(&hello_ryan);
  cmd_add(&bye_ryan);
  cmd_add(&hello_white);
  cmd_add(&bye_white);
  while(1)
  {
    sleep(1);
    time++;
    cmd_process();
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值