C言語シミュレーション虚ベースクラス-シミュレーションlighttpd fdevent実装


Lighttpdのfdeventの実装過程を見て、その実装をシミュレートする例を書きます.
虚ベースクラスはfdos(osオペレーティングシステム、fdは勝手に追加されても意味がありません)で、windows、linux、macの3つの派生クラスがあります.
それらのすべてのpublic方法はopen,close,playgameです.
/// fdos.h

#ifndef FDOS_H_INCLUDED
#define FDOS_H_INCLUDED

typedef enum
{
    OS_UNSET = -1,
    OS_WINDOWS,
    OS_LINUX,
    OS_MAC
}fd_type;

typedef struct fdos
{
    fd_type type;
    int maxfds;

    int (*open)(struct fdos *os);
    void (*close)(struct fdos *os);
    void (*playgame)(struct fdos *os, char *name);
}fdos;

// public
fdos* fdos_init(fd_type type, int maxfds);
void fdos_free(fdos *os);

int fdos_open(fdos *os);
void fdos_close(fdos *os);
void fdos_playgame(fdos *os, char *name);

// private
int fdos_windows_init(fdos *os);
int fdos_linux_init(fdos *os);
int fdos_mac_init(fdos *os);

#endif // FDOS_H_INCLUDED
/// fdos.cpp

#include "fdos.h"
#include <stdio.h>
#include <stdlib.h>

fdos* fdos_init(fd_type type, int maxfds)
{
    fdos *os;

    os = (fdos*)malloc(sizeof(*os));
    os->maxfds = maxfds;

    switch (type)
    {
        case OS_WINDOWS:
        if (0 != fdos_windows_init(os))
        {
            printf("windows init fail
"); return NULL; } return os; case OS_LINUX: if (0 != fdos_linux_init(os)) { printf("linux init fail
"); return NULL; } return os; case OS_MAC: if (0 != fdos_mac_init(os)) { printf("mac init fail
"); return NULL; } return os; case OS_UNSET: break; } printf("fdos init fail
"); return NULL; } void fdos_free(fdos *os) { if (os) { free(os); } } int fdos_open(fdos *os) { return os->open(os); } void fdos_close(fdos *os) { return os->close(os); } void fdos_playgame(fdos *os, char *name) { return os->playgame(os, name); }
/// fdwindows.cpp

#include "fdos.h"
#include <stdio.h>

static int fdos_windows_open(fdos *os)
{
    printf("windows open
"); return 0; } static void fdos_windows_close(fdos *os) { printf("windows close
"); } static void fdos_windows_playgame(fdos *os, char *name) { printf("windows playgame: %s
", name); } int fdos_windows_init(fdos *os) { os->type = OS_WINDOWS; // x ,##x // #x, , : // #define MY_CONST(x) #x // printf("%s", MY_CONST(hello)); // :hello #define SET(x) \ os->x = fdos_windows_##x; // :fdos_windows_open SET(open); // :fdos_windows_close SET(close); // :fdos_windows_playgame SET(playgame); return 0; }
/// fdlinux.cpp

#include "fdos.h"
#include <stdio.h>

static int fdos_linux_open(fdos *os)
{
    printf("linux open
"); return 0; } static void fdos_linux_close(fdos *os) { printf("linux close
"); } static void fdos_linux_playgame(fdos *os, char *name) { printf("linux playgame: %s
", name); } int fdos_linux_init(fdos *os) { os->type = OS_LINUX; #define SET(x) \ os->x = fdos_linux_##x; SET(open); SET(close); SET(playgame); return 0; }
/// fdmac.cpp

#include "fdos.h"
#include <stdio.h>

static int fdos_mac_open(fdos *os)
{
    printf("mac open
"); return 0; } static void fdos_mac_close(fdos *os) { printf("mac close
"); } static void fdos_mac_playgame(fdos *os, char *name) { printf("mac playgame: %s
", name); } int fdos_mac_init(fdos *os) { os->type = OS_MAC; #define SET(x) \ os->x = fdos_mac_##x; SET(open); SET(close); SET(playgame); return 0; }
/// main.cpp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "fdos.h"

/// test
int main(void)
{
    fdos *os = fdos_init(OS_WINDOWS, 3);
    fdos_open(os);
    fdos_playgame(os, "wow");
    fdos_close(os);
    fdos_free(os);

    os = fdos_init(OS_LINUX, 3);
    fdos_open(os);
    fdos_free(os);

    os = fdos_init(OS_MAC, 3);
    fdos_playgame(os, "zx");
    fdos_free(os);

    return 0;
}