longjmp和多线程:读写线程实例

因为多线程的问题比较复杂。这里再给个实际内容的例子。

这个例子中,读写线程通过一个bx缓冲区合作。如果缓冲区为空,读线程调用yield原语让出处理机让写线程来写。如果缓冲区写满了,写线程也是调用yield原语让读线程来读。

写线程由主程序启动。读线程由写线程启动。程序的功能是从当前目录读取一个文本文件并显示出来。读线程比写线程先运行。因为一开始缓冲区为空,读线程第一次读就需要让出处理机,让写线程开始写 buffer。

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

typedef int BOOL;
#define TRUE    1
#define FALSE   0


typedef struct _Context_ {
    jmp_buf mainBuf;
    int finish;
    struct {
        jmp_buf buf;
        int state;
    } thread[2];
} Context;


Context gCtx;
static int next_thread;
int run;

#define resume() \
    if (gCtx.thread[run].state==0) \
    { \
        longjmp(gCtx.thread[run].buf, 1); \
    }


#define yield() \
    if (0 == setjmp(gCtx.thread[run].buf)) \
    { \
        longjmp(gCtx.mainBuf, 1); \
    }

#define MAXBUFS 10
struct buffer {
        char buf[MAXBUFS][128];
        int pos;
        int bc;
        int eobf;
};
struct buffer bx;

void bx_read(char *s, int n)
{
restart:
        if (bx.bc) {
                strncpy(s, bx.buf[bx.pos], n);
                s[n-1]='\0';
                bx.bc--;
                bx.pos++; if(bx.pos>=MAXBUFS) bx.pos=0;
                return;
        } else if (bx.eobf) {
                gCtx.finish=1;
                gCtx.thread[run].state=1;
                yield();
        }
        else {
                yield();
                goto restart;
        }
}

void bx_write(char *s, int n)
{
        int wpos;
        if(bx.bc>=MAXBUFS)  {
                yield();
        }
        wpos = bx.pos+bx.bc;
        if(wpos>=MAXBUFS) wpos-=MAXBUFS;

        if(n<128) {
                strcpy(bx.buf[wpos], s);
        }else {
                strncpy(bx.buf[wpos], s, 128);
                bx.buf[wpos][127]='\0';
        }
        bx.bc++;
}

typedef void (*pf) (void *);
BOOL start_coroutine(pf func, void *arg);
void coroutine_read(void *arg);

void coroutine_write(void *arg)
{
        FILE *fp;
        char s[128];
        int len;
        fp = fopen("b.c", "r");

        if( !fp)  {
                printf("can not open `b.c'\n");
                exit(0);
        }
        if (setjmp(gCtx.thread[run].buf)!=0) goto next;
        start_coroutine(coroutine_read, NULL);
next:
        while ( fgets(s, 128, fp)!= NULL) {
                len = strlen(s);
                if( len) {
                        --len; if(s[len]=='\n') s[len]='\0';else ++len;
                }
                if( len) {
                        --len; if(s[len]=='\r') s[len]='\0';else ++len;
                }
                bx_write(s, len+1);
        }
        bx.eobf=1;
        gCtx.thread[run].state=1;
        fclose(fp);
        yield();
}

void coroutine_read(void *arg)
{
        char buf[128];
        while(!bx.eobf|| bx.bc) {
                bx_read(buf, 128);
                printf("%s\n", buf);
        }
        gCtx.thread[run].state=1;
        yield();
}


BOOL start_coroutine(pf func, void *arg)
{
    int reserve[256];
    int thread_id;

    thread_id = next_thread++;
    run = thread_id;
    func(arg);
    return TRUE;
}


int sched()
{
    int s;
    if (run == 0) s = 1; else s = 0;
    if (gCtx.thread[s].state == 0) run = s;
    return run;
}

int main()
{
    int i;

    if (setjmp(gCtx.mainBuf)!=0) goto resched;
    start_coroutine(coroutine_write, NULL);
    while (TRUE) {
      resched:
        i = sched();
        printf("sched thread(%d) to run\n", i);
        if (gCtx.thread[i].state == 0) {
            resume();
        } else break;
    }
    printf("done\n");
    return 0;
}


相关推荐

  1. longjmp线线实例

    2024-07-22 07:30:02       18 阅读
  2. JVM线

    2024-07-22 07:30:02       58 阅读
  3. C++线文件

    2024-07-22 07:30:02       22 阅读
  4. 线实例

    2024-07-22 07:30:02       21 阅读
  5. 【Python】线线的使用

    2024-07-22 07:30:02       58 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-22 07:30:02       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-22 07:30:02       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-22 07:30:02       45 阅读
  4. Python语言-面向对象

    2024-07-22 07:30:02       55 阅读

热门阅读

  1. 【CF】1216F-WiFi 题解

    2024-07-22 07:30:02       17 阅读
  2. 牛客周赛 Round 52VP(附D的详细证明)

    2024-07-22 07:30:02       17 阅读
  3. Android13 应用代码中修改热点默认密码

    2024-07-22 07:30:02       14 阅读
  4. 【React】事件绑定、React组件、useState、基础样式

    2024-07-22 07:30:02       16 阅读
  5. postman接口测试工具详解

    2024-07-22 07:30:02       16 阅读
  6. Symfony数据库抽象层:深入理解其工作原理

    2024-07-22 07:30:02       15 阅读
  7. 设计模式--职责链模式

    2024-07-22 07:30:02       17 阅读
  8. PXIe-6592

    PXIe-6592

    2024-07-22 07:30:02      13 阅读
  9. FPGA 中的 IOE与IO BANK

    2024-07-22 07:30:02       17 阅读
  10. 前端部署后提示用户刷新页面

    2024-07-22 07:30:02       16 阅读
  11. 编写测试用例:策略、技巧与最佳实践

    2024-07-22 07:30:02       17 阅读
  12. 自动化测试的艺术:Xcode中GUI测试的全面指南

    2024-07-22 07:30:02       17 阅读