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);
}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);
  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;
}

// 例如: 创建一个同步部门的管理员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);
}

int main(void)
{
  printf(" Hello \n"); 

        // 使用方法 我没写,这套代码还没在实际的板子上跑过,是我重构的。
}

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

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

猜你喜欢

转载自www.cnblogs.com/happybirthdaytoyou/p/10350420.html