ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

Programming Sandboxコミュの[お題]Coroutine

  • mixiチェック
  • このエントリーをはてなブックマークに追加

コメント(3)

GCC拡張機能を使ったインチキくさいやつ

--- myco.h ---
#ifndef __MYCO_H__
#define __MYCO_H__

#include <stddef.h>

typedef struct co co_t;

struct co {
    void *rp;
};

#define co_isactive(co) ((co)->rp != NULL)
#define co_resume(co) if ((co)->rp) goto *(co)->rp
#define co_return(co,ret) do { (co)->rp = NULL; return ret; } while (0)
#define co_suspend(co,ret) ({__label__ _rp; (co)->rp = &&_rp; return (ret); _rp:;})
#define co_sub(co, ret, func, args...) ({ \
        __label__ _rp; _rp: (ret) = (func)((co)+1, ## args); \
        if (co_isactive((co)+1)) {(co)->rp = &&_rp; return (ret);} \
        (ret); \
})

extern co_t *co_create(int);
extern void co_destroy(co_t *);

#endif /* !__MYCO_H__ */

--- myco.c ---
#include <stdlib.h>

#include "myco.h"

co_t *
co_create(int n)
{
    co_t *co;
    int i;

    if ((co = malloc(sizeof(co_t) * n + 1)) == NULL)
        return NULL;
    for (i = 0; i < n + 1; i++)
        co[i].rp = NULL;
    return co;
}

void
co_destroy(co_t *co)
{
    free(co);
}
ucontextを使った場合

#include <ucontext.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "hexdump.h"

static ucontext_t uctx_main, uctx_func1, uctx_func2;

#define die(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
#define R(f...) printf("%10.10s:%4d", __func__, __LINE__), printf("    "f), printf("\n")

static void
func1(void)
{
    R("Start");

    R("Suspend to func2");
    if (swapcontext(&uctx_func1, &uctx_func2) == -1)
        die("swapcontext");
    R("Resume");

    R("End");
}

static void
func2(void)
{
    R("Start");

    R("Suspend to func1");
    if (swapcontext(&uctx_func2, &uctx_func1) == -1)
        die("swapcontext");
    R("Resume");

    R("End");
}

static size_t
use_stack_size(unsigned char *stack, size_t max)
{
    size_t size;

    for (size = 0; size < max; size++) {
        if (stack[size] != 0xee) {
            return max - size;
        }
    }

    return max;
}

int
main(int argc, char **argv)
{
    char func1_stack[16384];
    char func2_stack[16384];

    R("Start");

    memset(func1_stack, 0xee, sizeof(func1_stack));
    memset(func2_stack, 0xee, sizeof(func2_stack));

    if (getcontext(&uctx_func1) == -1)
        die("getcontext");
    uctx_func1.uc_stack.ss_sp = func1_stack;
    uctx_func1.uc_stack.ss_size = sizeof(func1_stack);
    uctx_func1.uc_link = &uctx_main;
    makecontext(&uctx_func1, func1, 0);

    if (getcontext(&uctx_func2) == -1)
        die("getcontext");
    uctx_func2.uc_stack.ss_sp = func2_stack;
    uctx_func2.uc_stack.ss_size = sizeof(func2_stack);
    uctx_func2.uc_link = (argc > 1) ? NULL : &uctx_func1;
    makecontext(&uctx_func2, func2, 0);

    R("Suspend to func2");
    if (swapcontext(&uctx_main, &uctx_func2) == -1)
        die("swapcontext");
    R("Resume");

    hexdump(stdout, func1_stack, sizeof(func1_stack));
    hexdump(stdout, func2_stack, sizeof(func2_stack));

    printf("ucontext_t size     : %u\n", sizeof(ucontext_t));
    printf("func1 use stack size: %u\n", use_stack_size(func1_stack, sizeof(func1_stack)));
    printf("func2 use stack size: %u\n", use_stack_size(func2_stack, sizeof(func2_stack)));

    R("End");
    return EXIT_SUCCESS;
}
> if ((co = malloc(sizeof(co_t) * n + 1)) == NULL)

(n + 1)にしないと、と11年前の私につっこんでみるテスト

>>2

そして、 ucontextはdeprecatedになってしまったね、と。

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

Programming Sandbox 更新情報

Programming Sandboxのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。