C语言协程库async

13 篇文章 0 订阅

C语言协程库async

本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.

介绍

基于protothreads开发的C语言协程库。关于protothreads可参考文章:

开源

特点

  • 极小的系统占用,适合单片机等资源有限的场所
  • 支持单次运行任务和周期运行任务
  • 任务运行在协程之上,不用加锁,数据不会冲突

依赖

依赖的包:

https://github.com/jdhxyy/tztime.git
https://github.com/jdhxyy/tzmalloc.git
https://github.com/jdhxyy/tzlist.git
https://github.com/jdhxyy/pt.git

使用cip可以一键安装依赖的包:cip:C/C++包管理工具

API

// 运行间隔类型
// 单次运行
#define ASYNC_ONLY_ONE_TIME 0
// 无间隔运行
#define ASYNC_NO_WAIT -1

// 时间单位
// 毫秒
#define ASYNC_MILLISECOND 1000
// 秒
#define ASYNC_SECOND 1000000
// 分
#define ASYNC_MINUTE 60000000
// 小时
#define ASYNC_HOUR 3600000000


// AsyncFunc 协程函数类型.必须是基于pt实现的函数
typedef int (*AsyncFunc)(void);

// AsyncLoad 模块载入.mid是通过tzmalloc申请的内存id
void AsyncLoad(int mid);

// AsyncStart 启动协程
// interval是运行间隔.单位:us
// interval是ASYNC_ONLY_ONE_TIME时是单次运行,是ASYNC_NO_WAIT时无间隔运行
bool AsyncStart(AsyncFunc func, int interval);

// AsyncStop 停止协程
void AsyncStop(AsyncFunc func);

// AsyncRun 协程运行
void AsyncRun(void);

注意

  • 在多线程环境下使用使用函数AsyncStart,AsyncStop得加互斥锁,防止资源冲突
  • 调用AsyncStart函数即可启动协程,协程函数必须是pt函数
  • AsyncRun函数可放在独立的线程中循环执行

测试用例

在windows环境下开发测试。共启动4个协程任务:

  • task1:500ms打印一次
  • task2:1s打印一次
  • task3:单次运行
  • task4:无等待运行。任务函数内控制2s打印一次
#include <stdio.h>
#include <windows.h>
#include <time.h>
#include <stdlib.h>

#include "async.h"
#include "tzmalloc.h"
#include "tztime.h"
#include "pt.h"

#define RAM_INTERNAL 0

static int gMid = -1;

static uint64_t getTime(void);

static int task1(void);
static int task2(void);
static int task3(void);
static int task4(void);

int main() {
    TZTimeLoad(getTime);
    TZMallocLoad(RAM_INTERNAL, 20, 100 * 1024, malloc(100 * 1024));
    gMid = TZMallocRegister(RAM_INTERNAL, "dcom", 4096);

    AsyncLoad(gMid);
    AsyncStart(task1, 500 * ASYNC_MILLISECOND);
    AsyncStart(task2, 1 * ASYNC_SECOND);
    AsyncStart(task3, ASYNC_ONLY_ONE_TIME);
    AsyncStart(task4, ASYNC_NO_WAIT);
    while (1) {
        AsyncRun();
    }
    return 0;
}

static uint64_t getTime(void) {
    struct timeval t;
    gettimeofday(&t, NULL);
    return t.tv_sec * 1000000 + t.tv_usec;
}

static int task1(void) {
    static struct pt pt;
    uint64_t now;
    int ms;

    PT_BEGIN(&pt);

    now = getTime();
    ms = (int)(now / 1000);
    printf("%d task1\n", ms);

    PT_END(&pt);
}

static int task2(void) {
    static struct pt pt;
    uint64_t now;
    int ms;

    PT_BEGIN(&pt);

    now = getTime();
    ms = (int)(now / 1000);
    printf("%d task2\n", ms);

    PT_END(&pt);
}

static int task3(void) {
    static struct pt pt;
    uint64_t now;
    int ms;

    PT_BEGIN(&pt);

    now = getTime();
    ms = (int)(now / 1000);
    printf("%d task3\n", ms);

    PT_END(&pt);
}

static int task4(void) {
    static struct pt pt;
    static uint64_t time;
    uint64_t now;
    int ms;

    PT_BEGIN(&pt);

    time = getTime();
    PT_WAIT_UNTIL(&pt, getTime() - time > 2 * ASYNC_SECOND);

    now = getTime();
    ms = (int)(now / 1000);
    printf("%d task4\n", ms);
    PT_END(&pt);
}

测试输出:

17582 task3
18083 task1
18583 task2
18584 task1
19084 task1
19583 task2
19584 task4
19585 task1
20086 task1
20584 task2
20587 task1
21087 task1
21584 task2
21584 task4
21587 task1
22087 task1
22584 task2
22588 task1
23088 task1
23584 task4
23584 task2
23588 task1
24089 task1
24585 task2
24590 task1
25090 task1
25585 task2
25585 task4
25591 task1
26091 task1
26585 task2
26591 task1
27091 task1
27586 task4
27586 task2
27592 task1
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
orchid是一个构建于强大的boost基础上的C ,类似于python下的gevent/eventlet,为用户提供基于协程的并发模型。 协程,顾名思义,协作式程序,其思想是,一系列互相依赖的协程间依次使用CPU,每次只有一个协程工作,而其他协程处于休眠状态。协程在控制离开时暂停执行,当控制再次进入时只能从离开的位置继续执行。 协程已经被证明是一种非常有用的程序组件,不仅被python、lua、ruby等脚本语言广泛采用,而且被新一代面向多核的编程语言如golang rust-lang等采用作为并发的基本单位。 协程可以被认为是一种用户空间线程,与传统的抢占式线程相比,有2个主要的优点: 与线程不同,协程是自己主动让出CPU,并交付他期望的下一个协程运行,而不是在任何时候都有可能被系统调度打断。因此协程的使用更加清晰易懂,并且多数情况下不需要锁机制。 与线程相比,协程的切换由程序控制,发生在用户空间而非内核空间,因此切换的代价非常的小。 green化 术语“green化”来自于python下著名的协程greenlet,指改造IO对象以能和协程配合。某种意义上,协程与线程的关系类似与线程与进程的关系,多个协程会在同一个线程的上下文之中运行。因此,当出现IO操作的时候,为了能够与协程相互配合,只阻塞当前协程而非整个线程,需要将io对象“green化”。目前orchid提供的green化的io对象包括: tcp socket(还不支持udp) descriptor(目前仅支持非文件类型文件描述符,如管道和标准输入/输出,文件类型的支持会在以后版本添加) timer (定时器) signal (信号) chan:协程间通信 chan这个概念引用自golang的chan。每个协程是一个独立的执行单元,为了能够方便协程之间的通信/同步,orchid提供了chan这种机制。chan本质上是一个阻塞消息队列,后面我们将看到,chan不仅可以用于同一个调度器上的协程之间的通信,而且可以用于不同调度器上的协程之间的通信。 多核 建议使用的scheduler per cpu的的模型来支持多核的机器,即为每个CPU核心分配一个调度器,有多少核心就创建多少个调度器。不同调度器的协程之间也可以通过chan来通信。协程应该被创建在哪个调度器里由用户自己决定。 进一步信息请阅读doc目录下tutorial。如果您发现任何bug或者有任何改进意见,请联系[email protected] 标签:orchid

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值