逐步实现TCP服务端Step04-4:令Control更抽象

直接继承自Control的NControl和SControl代表了两种主控类,一种专注于通信,另一种则不需要通信。对专注于通信的类而言,Recover功能并非必要,不支持通信的主控类因不与client直连,可在client无感的情况下重启进程,此时的Recover功能是必要的。要实现Recover,主控类就需要构建在一块共享内存之上。

简单地说,在Control的基础之上,NControl要实现一套与通信相关的方法及属性且不需要SharedMemory属性,SControl需要SharedMemory属性,与通信相关的内容一律不要。

按照目前的设计,假设NControl自己实现了一个用于通信的方法,若想通过g_ncontrol直接调用到该方法的话,父类Control就必须要给出一个虚的方法。但这个方法显然是SControl所不需要的。类似地,SControl必需的shared_memory_属性,在NControl中是完全没用的。

Control要做的再抽象一些,它不应过问个别类特有的属性或方法:

说一下这几个类的命名,Control是祖先,它并不关心具体内容,可以理解为“什么都不控制”,类名不带前缀,直接用Control 。 CQControl是管控了code队列的主控类,CQ前缀是CodeQueue的缩写。同理,RecoverControl是带有恢复功能的主控类。CommControl控制了通信功能,它是NControl的父类,CommControl需要控制队列,因此对CQControl进行了继承。LocalControl是SControl的父类,Local这个前缀是相对于Comm而言的,它不处理对外通信,只关注本地的对象处理。同时,由于它要支持恢复功能,因而对RecoverControl做了继承。

CQControl和RecoverControl的Init方法都加了一个is_callback参数,这参数用于标识当前Init执行完成后,是否需要回调那个发起此次Init调用的对象的Init方法。就是父类的Init执行完了,是否要触发子类的OnInit方法。OnInit的触发在前篇已讨论过,这里加了is_callback参数是考虑到LocalControl进行了多继承,若不加以控制的话,随着CQControl::Init和RecoverControl::Init调用的完成,OnInit将会被触发两次,或者一次OnInit一次OnRecover,这是不合理的。这里应该以RecoverControl::Init为主,让其进行回调,关闭CQControl::Init的回调。

注意LocalControl的多继承形成了“菱形关系”,RecoverControl和CodeQueue都继承自Control,若在LocalControl或其子类中使用Control中的方法,就会出现名字冲突的问题。C++提供了虚继承机制来规避这个问题,将源于多个父类的同名方法视作一个方法。相关代码:

经过这次处理,细化了Control的分类,把原本混在一起的功能拆分到各个类中。

最后,在CommControl类中加了一个简单的set_listen_port方法,让NControl对象支持端口号设置。

s的新版本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include "base.h"
#include "scontrol.h"

LocalControl* g_scontrol = NULL;

int Init();
int main(int argc, char** argv)
{
    if (Init() < 0) 
        return -1;
    if (g_scontrol->PrepareToRun() < 0)
        return -1;

    g_scontrol->Run();

    return 0;
}

int Init()
{
    SharedMemory* main_shm = NULL;
    bool is_new_shm = false;
    if (!(main_shm = SHMFactory::CreateProduct(0x1109,
        SControl::CountSize(), is_new_shm))) {
        std::cout << "Create share memeory for " 
            << "code queue failed." << std::endl;
        return 1;
    }
    SControl::shared_memory_ = main_shm;
    g_scontrol = new SControl(0x1110, 0x1111); 
    if (!g_scontrol) {
        std::cout << "New control failed." << std::endl;
        return -1;
    }
    return 0;
}

netio的新版本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include "ncontrol.h"

CommControl* g_ncontrol = NULL;

int Init();
int main(int argc, char** argv)
{
    if (argc != 2) {
        std::cout << "Usage: " 
            << argv[0] << " port" << std::endl;
        return 0;
    }
    if (Init() < 0)
        return -1;

    g_ncontrol->set_listen_port(atoi(argv[1]));

    if (g_ncontrol->PrepareToRun() < 0)
        return -1;

    g_ncontrol->Run();

    return 0;
}

int Init()
{
    g_ncontrol = new NControl(0x1110, 0x1111); 
    if (!g_ncontrol) {
        std::cout << "New control failed." << std::endl;
        return -1;
    }
    return 0;
}

相关文件:


<==  index  ==>