// C语言之 面向对象+虚事务的抽象

/*********** 进阶练习: (对虚的事物的抽象) 完善部门职责 ***********************/

#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include <string.h> typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned char mybool; /*** 时间同步正常:每五分钟(300秒)同步一次
时间同步失败 :增补同步(在临近的60秒内wakeup无线模块增补一次同步)/节能处理(由300秒一次改为1小时一次) 机制
要求:如果曾经只要收到过一次同步信号,那么要保证之后每次唤醒的时间点都是预设的时间点。这个时间点需要是固定的。
***/ typedef enum{
ID1 = 1,
ID2,
ID3,
ID4,
ID5,
ID6
}ID_Enum; typedef enum{
SyncProcessDepartment = 1, // 时间同步处理 部
MarketDepartment, // 市场 部 : 这里可根据需求、自行扩展
HumanResourcesDepartment // 人力资源 部
}Department_Enum; typedef struct ClassInfo_{
ID_Enum ID;
Department_Enum Department;
}ClassInfo; typedef enum SYNC_State__{
SYNC_NewOnceStart = 0,
SYNC_LastOnceOK = 0xff
}SYNC_State_; enum SYNC_State__;
typedef struct Class_SYNC_Department_{
enum SYNC_State__ SYNC_State; // 当前的同步状态
u16 SYNC_NormalPeriod; // 正常同步一次的周期
u8 SYNC_SomeTime; // 给点余量.本机提前5秒唤醒,(而不是刚好是在同步信号来的时刻才唤醒)以便去接收这个同步信号
u16 SYNC_ErrPeriod; void (*pSYNC_Department_GetPara)(struct ClassAdmin_ *pthis, void* pSYNC_NormalPeriod, void* pSYNC_SomeReadyTime, void* pSYNC_ErrPeriod);
mybool(*pSYNC_Department_NormalProcess_CyeleCheck)(struct ClassAdmin_ *pthis);
void (*pSYNC_ERRProcess_CyeleCheck)(struct ClassAdmin_ *pthis, void* pFailTimes);
void (*pSYNCProcess_CyeleCheck) (struct ClassAdmin_ *pthis, SYNC_State_ SYNC_State); // 阅读了RT Thread的IO设备驱动框架后,rt_err_t rt_device_control(rt_device_t dev, rt_uint8_t cmd, void *arg);
// 感悟:我这里也可以使用命令 命令就是下面说的服务号
void (*pControl)(struct ClassAdmin_ *pthis, u8 CMD, void *pRara, SYNC_State_ SYNC_State);
// 最后一个参数是获取参数 。 有一个命令需要对应, pSYNC_Department_GetPara }Class_SYNC_Department; struct ClassAdmin_;
typedef struct ClassAdmin_
{
ClassInfo Internal_AdminInfo; //父类1
void(*pAdminInit)(struct ClassAdmin_ *pthis, ID_Enum Admin_ID, Department_Enum Admin_Department); void* pInternal_AdminDepartment;
// 部门本职工作
void (*pAdminMustMainJob_GetPara)(struct ClassAdmin_ *pthis, void* Para1, void* Para2, void* Para3); // 每个管理员自己的私活 : XX部门的YY,下班后送外卖挣了100元。
void (*pAdmin_PrivateJob1) (struct ClassAdmin_ *pthis, void* Para1);
}ClassAdmin; // 下面写 时间同步失败节能处理机制 的功能实现 // 具体的职能需要亲自操刀。我现在,需要一个时间同步的管理员。
// 那么我就来描述一下这个时间同步管理员的职责 // 首先是获取用户参数
void JobSYNC_Department_GetPara(struct ClassAdmin_ *pthis, void* pSYNC_NormalPeriod, void* pSYNC_SomeReadyTime, void* pSYNC_ErrPeriod)
{
u16 SYNC_NormalPeriod = *((u16*)pSYNC_NormalPeriod);
u8 SYNC_SomeReadyTime = *((u8*)pSYNC_SomeReadyTime);
u16 SYNC_ErrPeriod = *((u16*)pSYNC_ErrPeriod); ((Class_SYNC_Department*)(pthis->pInternal_AdminDepartment))->SYNC_NormalPeriod = SYNC_NormalPeriod;
((Class_SYNC_Department*)(pthis->pInternal_AdminDepartment))->SYNC_SomeTime = SYNC_SomeReadyTime;
((Class_SYNC_Department*)(pthis->pInternal_AdminDepartment))->SYNC_ErrPeriod = SYNC_ErrPeriod;
} // 轮询方式: 每次同步后会传递过来SYNC_OK标志。
mybool JobSYNC_NormalProcess_CyeleCheck(struct ClassAdmin_ *pthis)
{
// 正常模式: 每次收到SYNC_State = SYNC_OK的时候,开始计时。计时到,300-13的时候,无线模块WAKEUP,等待同步信号。
static u8 SYNC_State = (u8)SYNC_NewOnceStart;
static u16 TimeCountdownforNextSYNCSingal = 0; static u32 ErrCnt = 0; // 异常计数器。
mybool Cur_retVal = 0; // 只关注最近的一次同步状态 0:正常 1:异常 ErrCnt++; SYNC_State = ((Class_SYNC_Department*)(pthis->pInternal_AdminDepartment))->SYNC_State; if(SYNC_State == (u8)SYNC_LastOnceOK) // 收到信号的时候,相当于打开一个秒表开始倒计时
{ // 对比生活里跑步比赛,枪声一响,教练会按下秒表。这个按下动作,就是打开秒表这一动作。
  SYNC_State = SYNC_NewOnceStart; // 小结:要想利用生活的思维来指导编程,就不要遗漏生活里事物的细节, // 要严谨细致地观察,并一一映射到编程思维。
  TimeCountdownforNextSYNCSingal = ((Class_SYNC_Department*)(pthis->pInternal_AdminDepartment))->SYNC_NormalPeriod;   ErrCnt = 0;
}
if(SYNC_State == (u8)SYNC_NewOnceStart)
{
  if(TimeCountdownforNextSYNCSingal>0) // 这个是倒计时秒表的开关
  {
  if(--TimeCountdownforNextSYNCSingal == ((Class_SYNC_Department*)(pthis->pInternal_AdminDepartment))->SYNC_SomeTime)
    {
    // WirelessWakeUp(62);
    printf(" Wireless Wakeup, Ready to SYNC\n");
    TimeCountdownforNextSYNCSingal = 0;
    }
  }
} // 上面是正常周期性同步逻辑(周期性同步也会消除异常) 下面是发送异常消息 if(ErrCnt > ((Class_SYNC_Department*)(pthis->pInternal_AdminDepartment))->SYNC_NormalPeriod)
{
  Cur_retVal = 1; // 只关注最近的一次同步状态 0:正常 1:异常
} return Cur_retVal;
} void JobSYNC_ERRProcess_CyeleCheck(struct ClassAdmin_ *pthis, void* pFailTimes)
{
//异常分为:同步失败次数小于3 和 大于3的场景
u16 SYNC_NormalPeriod = ((Class_SYNC_Department*)pthis->pInternal_AdminDepartment)->SYNC_NormalPeriod;
u8 SYNC_SomeReadyTime = ((Class_SYNC_Department*)pthis->pInternal_AdminDepartment)->SYNC_SomeTime;
u8 FailTimes = *((u8*)pFailTimes); if(FailTimes == 0)
  return ; // 大于0才继续向下 if(FailTimes <= 3)
{
static u16 CntDown = 60;   if(CntDown-- == SYNC_SomeReadyTime)
  {
  // WakeUp(62); //可以事先约定同步部门的管理员1负责无线模块1的同步工作、管理员2负责无线模块2的同步工作 // 那么这里可以根据pthis来加以区分。 if(pthis->Internal_AdminInfo.ID == ID1) plora1->WirelessWakeup(plora1, 62);   printf("Wakeup in %d S later \n", CntDown);   CntDown = SYNC_SomeReadyTime + 60; // 这个SYNC_SomeReadyTime,让本周期的时间走完。
  }
}
else if(FailTimes <= 15)
{
static u16 CntDown = 3600;   if(CntDown-- == SYNC_SomeReadyTime)
  {
  // WakeUp(62);
  printf("Wakeup in %d S later \n", CntDown);   CntDown = SYNC_SomeReadyTime + 3600;
  }
}
if(FailTimes > 15)
  FailTimes = 0;
} // 这里内部统一处理正常模式和异常模式
// 给外界提供友好的简单接口,而不需要外界来操作同步逻辑
void JobSYNCProcess_CyeleCheck(struct ClassAdmin_ *pthis, SYNC_State_ SYNC_State)
{
static u32 Failtimes = 0;
u16 SYNC_NormalPeriod = ((Class_SYNC_Department*)pthis->pInternal_AdminDepartment)->SYNC_NormalPeriod;   if( 1 == (((Class_SYNC_Department*)(pthis->pInternal_AdminDepartment))->pSYNC_Department_NormalProcess_CyeleCheck)(pthis))
  {
  Failtimes++;
  Failtimes = (Failtimes + SYNC_NormalPeriod)/ SYNC_NormalPeriod;
  // 如果这里超时会怎样?那就是超时的那会多唤醒了(SYNC_NormalPeriod-SYNC_SomeReadyTime)秒咯。
  //调用异常处理
  ((Class_SYNC_Department*)(pthis->pInternal_AdminDepartment))->pSYNC_ERRProcess_CyeleCheck(pthis, (void*)&Failtimes);
  }
  else
  {
  Failtimes = 0;
  }
} // --------------------------------对外的接口 面向该程序的使用者----------------------------------------- void Obj_AdminInit(struct ClassAdmin_ *pthis, ID_Enum Admin_ID, Department_Enum Admin_Department)
{
pthis->Internal_AdminInfo.ID = Admin_ID;
pthis->Internal_AdminInfo.Department = Admin_Department; // 把部门的初始化也加在这里
if(pthis->Internal_AdminInfo.Department == SyncProcessDepartment)
((Class_SYNC_Department*)(pthis->pInternal_AdminDepartment))->pSYNC_Department_GetPara = JobSYNC_Department_GetPara; } // 例如: 创建一个同步部门的管理员Jason
ClassAdmin* pNewObj_ClassAdmin(ID_Enum Admin_ID, Department_Enum Admin_Department)
{
ClassAdmin* pNewObj_ClassAdmin = (ClassAdmin*)malloc(sizeof(ClassAdmin));   if((ClassAdmin*)0 == pNewObj_ClassAdmin)
  pNewObj_ClassAdmin = (ClassAdmin*)malloc(sizeof(ClassAdmin));   memset(pNewObj_ClassAdmin, 0, sizeof(ClassAdmin));   pNewObj_ClassAdmin->pAdminInit = Obj_AdminInit;
  pNewObj_ClassAdmin->pAdminInit(pNewObj_ClassAdmin, Admin_ID, Admin_Department);   return pNewObj_ClassAdmin;
} // 如果初始化的是时间同步管理员,那么后三个参数输入,从左到右依次是:SYNC_NormalPeriod、SYNC_SomeReadyTime、SYNC_ErrPeriod
void InitNewObj_ClassAdmin(ClassAdmin* pAdmin, void* Para1, void* Para2, void* Para3)
{
// 初始化部门职责:传入参数
  if(pAdmin->Internal_AdminInfo.Department == SyncProcessDepartment) // 根据Department信息访问相应的父类
  {
  pAdmin->pAdminMustMainJob_GetPara = ((Class_SYNC_Department*)(pAdmin->pInternal_AdminDepartment))->pSYNC_Department_GetPara;
  ((Class_SYNC_Department*)(pAdmin->pInternal_AdminDepartment))->pSYNC_Department_NormalProcess_CyeleCheck =           JobSYNC_NormalProcess_CyeleCheck;
  ((Class_SYNC_Department*)(pAdmin->pInternal_AdminDepartment))->pSYNC_ERRProcess_CyeleCheck = JobSYNC_ERRProcess_CyeleCheck;
  ((Class_SYNC_Department*)(pAdmin->pInternal_AdminDepartment))->pSYNCProcess_CyeleCheck = JobSYNCProcess_CyeleCheck;
  }   pAdmin->pAdminMustMainJob_GetPara(pAdmin, Para1, Para2, Para3);
} // 日后扩展 //为了给用户更好的接口。 //考虑每个管理员可以有许多的job,那么采取办法:每个管理员的每个job唯一对应一个ServiceID。 void GetService(部门, ID, ServiceID) { // 这块逻辑自行扩展,要把ServiceID这个逻辑加进去 } //还有:如果用户要扩展管理员及其职责,那么需要在我的关键类处添加代码 // 一切都是为了使用这套程序的人。 《== 即,我这套程序框架对外提供的界面要简单易用。 // 作为这套程序框架的创建者,我应该提供一个类似函数指针数组啥的接口,让他们在那里去填充即可。 int main(void)
{
  printf(" Hello \n"); // 使用方法 我没写,这套代码还没在实际的板子上跑过,是我重构的。
}
所有的东西可以分为部门 和 下属的管理员 。

到时候我写一个嵌入式产品 只需要两三个部门 哪怕下属搞七八个管理员都没事。

包括同步相关的那些逻辑,现在也用另一种思想修改过了。

思路清晰:  正常模式(包含异常检测), 发送异常通知,  异常处理。   这个思路是万能的。可复用的。

C面向对象: 升级版本实现:同步逻辑、少量连续失败则增补、多次连续失败则拉长同步周期的更多相关文章

  1. H5+ 重写在线升级版本比较代码

    重写h5+在线升级版本比较代码 hello h5+版本在线升级提供了如下的版本比较方法,逻辑比较繁琐,相关判断多余,非常不宜读. 先判断新旧版本有无, 接着分割为数组比较数组项大小,而且还只取了前四项 ...

  2. IDEA升级版本后界面出现变小,字体变细的问题解决

    笔者在今天升级了最新版本的IDEA 2019后发现,该版本的IDEA出现了非常诡异的事情如下图: 升级版本后字体居然发生了变化(通过官方导入的我自己的settings文件)还是出现了问题. 问题解决方 ...

  3. SQLSERVER 升级版本的方法

    1. 以SQLSERVER2014为例说明 SQLSERVER升级版本的方法, 也适用于evaluation 版本超过180天之后的处理. 2. 打开所有的应用 看到有一个 sqlserver2008 ...

  4. R 升级版本

    从3.4.1 升级到最新 懒得去官网下载 在R studio 执行一下代码 install.packages("installr") library(installr) updat ...

  5. Git的升级版本

    关于升级版本,例如我们要升级service版本,我们可以这样子操作 1.在master里面pull完了之后,到自己的分支,然后merge master里面的代码,然后把pom文件 里面的版本升一级,然 ...

  6. 所有的 Unix Like 系统都会内建 vi 文书编辑器。vim 是vi的升级版本,它不仅兼容vi的所有指令 ,而且还有一些新的特性在里面。

    所有的 Unix Like 系统都会内建 vi 文书编辑器.vim 是vi的升级版本,它不仅兼容vi的所有指令 ,而且还有一些新的特性在里面. https://blog.csdn.net/carolz ...

  7. Maven-内部多个项目依赖自动升级版本的部署

    需要自动升级版本的AAA项目发布 (有内部依赖时) 步骤比较复杂, 有一些需要根据实际情况调整. 考虑了以下几种可能性: 依赖模块的版本有更新 依赖模块版本没更新 依赖模块的版本号: 直接定义, 用属 ...

  8. 第10章 同步设备I/O和异步设备I/O(2)_同步IO和异步IO基础

    10.3 执行同步设备I/O (1)对设备读写操作的函数 ①ReadFile/WriteFile函数 参数 描述 hFile 文件句柄 pvBuffer 指向要接收文件数据的缓冲区或把缓冲区数据写入设 ...

  9. 使用Red Gate Sql Compare 数据库同步工具进行SQL Server的两个数据库的结构比较、同步

    将测试版的项目同步(部署)到正式版的时候,两个数据库的结构比较与同步时,如果修改数据库的时候没有记录好修改了那些表,很难将两个数据库进行同步 RedGate Sql Compare使用简介说明: 1. ...

随机推荐

  1. 焦大:seo思维光年(中)seo体系化

    http://www.wocaoseo.com/thread-56-1-1.html 光年的seo培训一直被业界公认为高端的培训,其主导的seo数据化一直对现在很多人的影响至深,比如我自己.但是也有人 ...

  2. Qt QString转char[]数组

    Qt QString转char[]数组 QString s1="1234456";char str[20]={0};strcpy(str,s1.toStdString().c_st ...

  3. asp .net core 静态文件资源

    前言 对静态资源的简单的一个概况,在<重新整理.net core 计1400篇>系列后面会深入. 正文 我们在加入中间件是这样写的: app.UseStaticFiles(); 默认是给w ...

  4. 以Winsows Service方式运行JupyterLab

    有数据分析,数据挖掘,以及机器学习和深度学习实践经验的读者应该会对Jupyter Notebook这一工具十分熟悉,而JupyterLab是它的升级版本,其提供了更具扩展性,更加可定制化的功能选项. ...

  5. 用python导入20个G的json数据到Mysql数据库

    整体思路参考资料:https://blog.csdn.net/layman2016/article/details/79252499 作业:有一个16个G的跟疫情相关的json新闻大数据(articl ...

  6. UI自动化测试、接口测试等自动化测试策略

    今天跟大家介绍UI测试.接口测试.单元测试主要内容,以及每种测试花费时间讨论.UI测试[Selenium]UI测试是最接近软件真实用户使用行为的测试类型.通常是模拟真实用户使用软件的行为,即模拟用户在 ...

  7. Labview学习之路(七)for和while的理论要点

    for循环 循环次数可以为0(N的接线端为) 终止条件:1. 完成N次循环.      2. 添加条件接线端,就像while循环的红点一样,(方法,右键点击边框,添加条件接线端) 数组通过自动索引接入 ...

  8. 用rspec执行自动化测试用例

    rspec是一款行为驱动开发(BDD)的工具,不过在这里用于测试,准确来说应该是测试驱动开发(TDD)吧.事实上我也没搞清楚.作为初学者不清楚就不清楚吧,以后会知道的.写博客无非就是写写学习笔记,不纠 ...

  9. 【基础知识】Unity查漏补缺

    最近发现了一些平时不太注重的知识点,特此建立个专题,把零散的东西.疏忽的东西临时记录下来. Mecanim动画系统: 1)设置AnimatorController时,如果某个动作播放不正常. 首先打开 ...

  10. LayUi超级好用的前端工具

    日期:https://www.layui.com/laydate/ LayUi 首页地址:https://www.layui.com/