zoukankan      html  css  js  c++  java
  • 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
    ");
        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 
    ", 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 
    ", 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 
    "); 
    
            // 使用方法 我没写,这套代码还没在实际的板子上跑过,是我重构的。
    }
    
    
    
     
    所有的东西可以分为部门 和 下属的管理员 。
    
    到时候我写一个嵌入式产品 只需要两三个部门 哪怕下属搞七八个管理员都没事。
    
    
    
    包括同步相关的那些逻辑,现在也用另一种思想修改过了。
    
    思路清晰:  正常模式(包含异常检测), 发送异常通知,  异常处理。   这个思路是万能的。可复用的。



    普通写法版本:
    https://www.cnblogs.com/happybirthdaytoyou/p/10331059.html










    .
    /************* 社会的有色眼光是:博士生、研究生、本科生、车间工人; 重点大学高材生、普通院校、二流院校、野鸡大学; 年薪百万、五十万、五万; 这些都只是帽子,可以失败千百次,但我和社会都觉得,人只要成功一次,就能换一顶帽子,只是社会看不见你之前的失败的帽子。 当然,换帽子决不是最终目的,走好自己的路就行。 杭州.大话西游 *******/
  • 相关阅读:
    Oracle数据库-建库、建表空间,建用户
    创建oracle数据库的表空间、用户、目录、导入导出文件等信息
    使用 UML 进行业务建模:理解业务用例与系统用例的相似和不同之处
    DataSet用法详细
    DataSet和DataTable详解
    经典SQL语句集锦
    JS脚本验证大全
    用Unity写一个12306验证器的恶搞图生成软件
    SQL Server中 sysobjects、syscolumns、systypes
    如何在oracle中导入导出(备份&恢复)dmp数据库文件
  • 原文地址:https://www.cnblogs.com/happybirthdaytoyou/p/10350420.html
Copyright © 2011-2022 走看看