C面向对象: 升级版本实现:同步逻辑、少量连续失败则增补、多次连续失败则拉长同步周期
// 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面向对象: 升级版本实现:同步逻辑、少量连续失败则增补、多次连续失败则拉长同步周期的更多相关文章
- H5+ 重写在线升级版本比较代码
重写h5+在线升级版本比较代码 hello h5+版本在线升级提供了如下的版本比较方法,逻辑比较繁琐,相关判断多余,非常不宜读. 先判断新旧版本有无, 接着分割为数组比较数组项大小,而且还只取了前四项 ...
- IDEA升级版本后界面出现变小,字体变细的问题解决
笔者在今天升级了最新版本的IDEA 2019后发现,该版本的IDEA出现了非常诡异的事情如下图: 升级版本后字体居然发生了变化(通过官方导入的我自己的settings文件)还是出现了问题. 问题解决方 ...
- SQLSERVER 升级版本的方法
1. 以SQLSERVER2014为例说明 SQLSERVER升级版本的方法, 也适用于evaluation 版本超过180天之后的处理. 2. 打开所有的应用 看到有一个 sqlserver2008 ...
- R 升级版本
从3.4.1 升级到最新 懒得去官网下载 在R studio 执行一下代码 install.packages("installr") library(installr) updat ...
- Git的升级版本
关于升级版本,例如我们要升级service版本,我们可以这样子操作 1.在master里面pull完了之后,到自己的分支,然后merge master里面的代码,然后把pom文件 里面的版本升一级,然 ...
- 所有的 Unix Like 系统都会内建 vi 文书编辑器。vim 是vi的升级版本,它不仅兼容vi的所有指令 ,而且还有一些新的特性在里面。
所有的 Unix Like 系统都会内建 vi 文书编辑器.vim 是vi的升级版本,它不仅兼容vi的所有指令 ,而且还有一些新的特性在里面. https://blog.csdn.net/carolz ...
- Maven-内部多个项目依赖自动升级版本的部署
需要自动升级版本的AAA项目发布 (有内部依赖时) 步骤比较复杂, 有一些需要根据实际情况调整. 考虑了以下几种可能性: 依赖模块的版本有更新 依赖模块版本没更新 依赖模块的版本号: 直接定义, 用属 ...
- 第10章 同步设备I/O和异步设备I/O(2)_同步IO和异步IO基础
10.3 执行同步设备I/O (1)对设备读写操作的函数 ①ReadFile/WriteFile函数 参数 描述 hFile 文件句柄 pvBuffer 指向要接收文件数据的缓冲区或把缓冲区数据写入设 ...
- 使用Red Gate Sql Compare 数据库同步工具进行SQL Server的两个数据库的结构比较、同步
将测试版的项目同步(部署)到正式版的时候,两个数据库的结构比较与同步时,如果修改数据库的时候没有记录好修改了那些表,很难将两个数据库进行同步 RedGate Sql Compare使用简介说明: 1. ...
随机推荐
- Linux系统时间同步方法
在Windwos中,系统时间的设置很简单,界面操作,通俗易懂,而且设置后,重启,关机都没关系.系统时间会自动保存在BIOS时钟里面,启动计算机的时候,系统会自动在BIOS里面取硬件时间,以保证时间的不 ...
- 安装oracleXE快捷版(二)
-bash-3.2$ 是oracle用户下的提示符 [root@localhost ~]# 是root用户下的提示符 #用root去修改oracle用户的密码123456[root@localhost ...
- Java 获取一段时间内的每一天
有时候我们会遇到一些业务场景,需要去获取一段时间内的每一天日期 public static List<Date> findDates(Date dBegin, Date dEnd) { L ...
- 【Maven】Mac操作系统下安装配置maven环境变量
1.下载maven 下载地址:http://maven.apache.org/download.cgi 2.解压设置maven本地地址解压后 我放在 /Users/david/developer/ap ...
- java初探(1)之防止库存为负以及防超买
在秒杀业务中,会出现当只剩一个库存时,但有多个人仍然秒杀成功,且都减库存成功,因此,在减库存,更新数据库的时候,需要在sql语句上进行判断,是否库存大于0. @Update("update ...
- 02_套接字编程(socket抽象层)
1.套接字概述 1.套接概述: 套接是进行网络通信的一种手段(socket) 2.套接字分类: 流式套接字(SOCK_STREAM): 传输层基于tcp协议进行通信 数 ...
- C010:书号分解ISBN
代码: #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { int prefix,groupIndentifier ...
- ES ElasticSearch 7.x 下动态扩大索引的shard数量
ES ElasticSearch 7.x 下动态扩大索引的shard数量 背景 在老版本的ES(例如2.3版本)中, index的shard数量定好后,就不能再修改,除非重建数据才能实现. 从ES6. ...
- 浏览器调试的必知必会,零基础足够详细-第一节console面板、移动端调试
前言 本文已经发布视频点击查看 开发过程中,浏览器的调试非常重要,可以说是必备的技巧,本文我就会分享一些自己掌握的技巧,欢迎补充 我们默认使用Chrome浏览器,但是你使用新edge浏览器也是可以的 ...
- UI自动化时,解决selenium中无法点击Element:ElementClickInterceptedException
在跑自动化时,页面上有2个下拉框,两个下拉框无论屏蔽哪一段都会成功,但是同时放开跑时会报错,百度给的解释是上面的下拉框元素覆盖了下面下拉框的元素定位,才会导致报错 百度的解决办法有2种: elemen ...