view schedular/main.c @ 4:ac10727fee49 default tip

Parallel execution
author Yasutaka Higa <e115763@ie.u-ryukyu.ac.jp>
date Tue, 10 May 2016 16:39:06 +0900
parents 0410aa49eff5
children
line wrap: on
line source

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

enum ThreadType {
    MainThread,
    SchedularThread,
    WorkerThread,
};

enum CodeSegment {
    Schedular,
    Worker,
    CountUp,
    CountStop,
    Exit,
};

struct Context {
    enum ThreadType threadType;
    unsigned int threadId;
    __code (**code) (struct Context*);

    union SubContext {
        struct MainContext {
            unsigned int threadNum;
            pthread_t schedularThread;
            struct Context *schedularContext;
        } main;
        struct WorkerContext {
            unsigned int count;
        } worker;
        struct SchedularContext {
            pthread_t *threads;
        } schedular;
    } *subContext;
};

__code meta(struct Context* context, enum CodeSegment next) {
    goto (context->code[next])(context);
}

__code countUp(struct Context* context) {
    if (context->subContext->worker.count >= 5) goto meta(context, CountStop);

    printf("threadId %u, count %u\n", context->threadId, context->subContext->worker.count);
    context->subContext->worker.count++;

    goto meta(context, CountUp);
}

__code countStop(struct Context* context) {
    printf("count stop: threadId %u\n", context->threadId);
}

__code worker(struct Context* context) {
    goto meta(context, CountUp);
}

__code schedular(struct Context* context) {
    for (unsigned int i = 0; i < 100; i++) {
        printf("schedular %u\n", i);
    }
}

__code initFinish(struct Context* mainContext, enum CodeSegment next) {
    pthread_join(mainContext->subContext->main.schedularThread, NULL);
    goto (mainContext->code[next])(mainContext);
}

__code initWorkers(struct Context* mainContext, enum CodeSegment next) {
    struct Context* schedularContext = mainContext->subContext->main.schedularContext;
    struct Context* workerContext;

    for (unsigned int i = 0; i < mainContext->subContext->main.threadNum; i++) {
        workerContext                           = malloc(sizeof(struct Context));
        workerContext->code                     = mainContext->code;
        workerContext->threadType               = WorkerThread;
        workerContext->threadId                 = i;
        workerContext->subContext               = malloc(sizeof(struct WorkerContext));
        workerContext->subContext->worker.count = 0;

        pthread_create(schedularContext->subContext->schedular.threads+i, NULL, (void*)worker, workerContext);

    }
    goto initFinish(mainContext, next);
}


__code initSchedular(struct Context* mainContext, enum CodeSegment next) {
    struct Context* schedularContext  = (struct Context*)malloc(sizeof(struct Context));

    schedularContext->code                          = mainContext->code;
    schedularContext->threadType                    = SchedularThread;
    schedularContext->subContext                    = malloc(sizeof(struct SchedularContext));
    schedularContext->subContext->schedular.threads = malloc(sizeof(pthread_t) * mainContext->subContext->main.threadNum);
    mainContext->subContext->main.schedularContext  = schedularContext;

    pthread_create(&(mainContext->subContext->main.schedularThread), NULL, (void*)schedular, schedularContext);

    goto initWorkers(mainContext, next);
}

__code init(enum CodeSegment next) {
    struct Context* context  = (struct Context*)malloc(sizeof(struct Context));

    context->code            = malloc(sizeof(__code (**)(struct Context*)) * Exit);
    context->code[Worker]    = worker;
    context->code[CountUp]   = countUp;
    context->code[CountStop] = countStop;

    context->threadType                  = MainThread;
    context->threadId                    = 999;
    context->subContext                  = malloc(sizeof(struct MainContext));
    context->subContext->main.threadNum = 1;

    goto initSchedular(context, next);
}


int main(int argc, char const* argv[]) {
    goto init(Worker);
}