使用 ucontext 模拟协程切换

ucontext 定义如下

The ucontext_t type is a structure type suitable for holding the context for a user thread of execution. A thread's context includes its stack, saved registers, and list of blocked signals.

可以用来保存当前线程的堆栈和寄存器,保存执行现场,这就为在一个线程内进行任务切换提供了可能,这种多任务之间的切换就是协程。

示例

#include <stdio.h>
#include <ucontext.h>
#include <unistd.h>
#include <iostream>
using namespace std;

void coroutine_1(void* arg) 
{
	puts("This is from coroutine 1");
}

void coroutine_2(void* arg) 
{
	puts("This is from coroutine 2");
}

定义两个任务 coroutine_1 和 coroutine_2

void context_test()
{
	char stack_1[1024*128];
	ucontext_t co_1, co_save_1;

	getcontext(&co_1);
	co_1.uc_stack.ss_sp = stack_1;
	co_1.uc_stack.ss_size = sizeof(stack_1);
	co_1.uc_stack.ss_flags = 0;
	co_1.uc_link = &co_save_1;

	makecontext(&co_1, (void(*)(void))coroutine_1, 0); // To coroutine_1
	swapcontext(&co_save_1, &co_1); 

	puts("here 33 line");

	char stack_2[1024*128];
	ucontext_t co_2, co_save_2;

	getcontext(&co_2);
	co_2.uc_stack.ss_sp = stack_2;
	co_2.uc_stack.ss_size = sizeof(stack_2);
	co_2.uc_stack.ss_flags = 0;
	co_2.uc_link = &co_save_2;

	makecontext(&co_2, (void(*)(void))coroutine_2, 0); // To coroutine_2
	swapcontext(&co_save_2, &co_2); 

	puts("here 45 line");
}

int main() {
	context_test();
        puts("here 50 line");
	return 0;
}

用 co_1 表示一个新的 context,它指向下一个执行的 context 是 co_save_1。

makecontext 函数修改目前的上下文,去执行 coroutine_1 函数。swapcontext 触发任务切换,同时保存当前上下文到 co_save_1 中,一旦 coroutine_1 执行完会回到当前位置。

同理,用 co_2 表示另一个 context,它指向下一个执行的 context 是 co_save_2。

这样就可以看到如下执行顺序

 context_test——>  coroutine_1
coroutine_1 ——>   context_test
  context_test——>  coroutine_2
coroutine_2 ——>   context_test
 context_test  ——>  main 结束

运行结果

This is from coroutine 1
here 33 line
This is from coroutine 2
here 45 line
here 50 line

转载于:https://my.oschina.net/lvyi/blog/795658

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值