博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ucontext实现的用户级多线程框架
阅读量:6271 次
发布时间:2019-06-22

本文共 6280 字,大约阅读时间需要 20 分钟。

昨天看CN-Erlounge-IV讲搞的其中一篇<erlang进程模型在C++中的实践>,对用coroutine实现用户态的线程非常感兴趣,于是查下资料

写了个简单的实验框架,其中schedule算法的实现很简单,只是遍历所有可以执行的coroutine.

代码如下:

uthread.h

/* * brief: 用ucontext实现的用户级线程框架 * author: kenny huang * date: 2009/10/13 * email: huangweilook@21cn.com */ #ifndef _UTHREAD_H #define _UTHREAD_H #include 
#include
#include
#include
#define MAX_UTHREAD 128 typedef int uthread_id; #define INVAID_ID -1 //用户态线程的当前状态 enum thread_status {
ACTIVED = 0,//可运行的 BLOCKED,//被阻塞 SLEEP,//主动休眠 DIE,//死死亡 }; class runnable {
public: virtual void main_routine() = 0; }; class Scheduler; /* * 用户态线程 */ class u_thread {
friend class Scheduler; private: u_thread(runnable *rable,unsigned int ssize,uthread_id uid) :ssize(ssize),_status(BLOCKED),rable(rable),uid(uid) {
stack = new char[ssize]; ucontext.uc_stack.ss_sp = stack; ucontext.uc_stack.ss_size = ssize; getcontext(&ucontext); } ~u_thread() {
delete []stack; } static void star_routine(); public: ucontext_t &GetContext() {
return ucontext; } void SetStatus(thread_status _status) {
this->_status = _status; } thread_status GetStatus() {
return _status; } uthread_id GetUid() {
return uid; } //休眠time时间 static void sleep(uthread_id utid,int t); private: ucontext_t ucontext; char *stack;//coroutine使用的栈 unsigned int ssize;//栈的大小 thread_status _status; runnable *rable; uthread_id uid; }; /* * 任务调度器 */ class Scheduler {
//friend void u_thread::star_routine(); friend class u_thread; public: static void scheduler_init(); static void schedule(); static uthread_id uthread_create(runnable *rable,unsigned int stacksize); private: static u_thread *GetCurrentUThread() {
if(current == -1) return NULL; return threads[current]; } //休眠time时间 static void sleep(uthread_id utid,int t); private: static std::list
activeList;//可运行uthread列表 static std::list
> sleepList;//正在睡眠uthread列表 static char stack[4096]; static ucontext_t ucontext; static u_thread *threads[MAX_UTHREAD]; static int total_count; static int current;//在uthread创建时使用的 }; #endif

uthread.cpp

#include "uthread.h" #include 
#include
#include
ucontext_t Scheduler::ucontext; char Scheduler::stack[4096]; u_thread *Scheduler::threads[128]; int Scheduler::total_count = 0; int Scheduler::current = -1; std::list
Scheduler::activeList; std::list
> Scheduler::sleepList; void u_thread::sleep(uthread_id utid,int t) { Scheduler::sleep(utid,t); } void u_thread::star_routine() { u_thread *current_uthread = Scheduler::GetCurrentUThread(); assert(current_uthread); //回到Scheduler::uthread_create current_uthread->SetStatus(ACTIVED); ucontext_t &cur_context = current_uthread->GetContext(); swapcontext(&cur_context,&Scheduler::ucontext); current_uthread->rable->main_routine(); current_uthread->SetStatus(DIE); } void Scheduler::scheduler_init() { for(int i = 0; i < MAX_UTHREAD; ++i) threads[i] = 0; getcontext(&ucontext); ucontext.uc_stack.ss_sp = stack; ucontext.uc_stack.ss_size = sizeof(stack); ucontext.uc_link = NULL; makecontext(&ucontext,schedule, 0); } void Scheduler::schedule() { while(total_count > 0) { //首先执行active列表中的uthread std::list
::iterator it = activeList.begin(); std::list
::iterator end = activeList.end(); for( ; it != end; ++it) { if(*it && (*it)->GetStatus() == ACTIVED) { ucontext_t &cur_context = (*it)->GetContext(); swapcontext(&ucontext,&cur_context); uthread_id uid = (*it)->GetUid(); if((*it)->GetStatus() == DIE) { printf("%d die/n",uid); delete threads[uid]; threads[uid] = 0; --total_count; activeList.erase(it); break; } else if((*it)->GetStatus() == SLEEP) { printf("%d sleep/n",uid); activeList.erase(it); break; } } } //看看Sleep列表中是否有uthread该醒来了 std::list
>::iterator its = sleepList.begin(); std::list
>::iterator ends = sleepList.end(); time_t now = time(NULL); for( ; its != ends; ++its) { //可以醒来了 if(now >= its->second) { u_thread *uthread = its->first; uthread->SetStatus(ACTIVED); activeList.push_back(uthread); sleepList.erase(its); break; } } } printf("scheduler end/n"); } uthread_id Scheduler::uthread_create(runnable *rable,unsigned int stacksize) { if(total_count >= MAX_UTHREAD) return INVAID_ID; int i = 0; for( ; i < MAX_UTHREAD; ++i) { if(threads[i] == 0) { threads[i] = new u_thread(rable,stacksize,i); ++total_count; current = i; ucontext_t &cur_context = threads[i]->GetContext(); cur_context.uc_link = &ucontext; makecontext(&cur_context,u_thread::star_routine, 0); swapcontext(&ucontext, &cur_context); current = -1; activeList.push_back(threads[i]); return i; } } } void Scheduler::sleep(uthread_id utid,int t) { if(utid == INVAID_ID) return; assert(threads[utid]); time_t now = time(NULL); now += t; printf("wake up time %u/n",now); //插入到sleep列表中 sleepList.push_back(std::make_pair(threads[utid],now)); //保存当前上下文切换回scheduler threads[utid]->SetStatus(SLEEP); ucontext_t &cur_context = threads[utid]->GetContext(); swapcontext(&cur_context,&Scheduler::ucontext); }

uthreadtest.cpp

// kcoroutine.cpp : 定义控制台应用程序的入口点。 // #include "uthread.h" class runable_test : public runnable {
public: runable_test(const char *name):name(name){} void main_routine() {
for(int i =0 ; i < 10 ; ++i) {
printf("%s/n",name); u_thread::sleep(uid,1); printf("%s wake up/n",name); } } const char *name; uthread_id uid; }; int main() {
//首先初始化调度器 Scheduler::scheduler_init(); runable_test t1("0"); runable_test t2("1"); runable_test t3("2"); runable_test t4("3"); //创建4个用户级线程 t1.uid = Scheduler::uthread_create(&t1,4096); t2.uid = Scheduler::uthread_create(&t2,4096); t3.uid = Scheduler::uthread_create(&t3,4096); t4.uid = Scheduler::uthread_create(&t4,4096); printf("create finish/n"); //开始调度线程的运行 Scheduler::schedule(); return 0; }

在linux下执行

g++ -o test uthreadtest.cpp uthread.cpp

便可生成可执行文件

转载于:https://www.cnblogs.com/sniperHW/archive/2012/04/02/2429640.html

你可能感兴趣的文章
BOOT.INI文件参数
查看>>
vmstat详解
查看>>
新年第一镖
查看>>
unbtu使用笔记
查看>>
MaxCompute 学习计划(一)
查看>>
OEA 中 WPF 树型表格虚拟化设计方案
查看>>
Android程序开发初级教程(一) 开始 Hello Android
查看>>
使用Gradle打RPM包
查看>>
“我意识到”的意义
查看>>
淘宝天猫上新辅助工具-新品填表
查看>>
再学 GDI+[43]: 文本输出 - 获取已安装的字体列表
查看>>
nginx反向代理
查看>>
操作系统真实的虚拟内存是什么样的(一)
查看>>
hadoop、hbase、zookeeper集群搭建
查看>>
python中一切皆对象------类的基础(五)
查看>>
modprobe
查看>>
android中用ExpandableListView实现三级扩展列表
查看>>
%Error opening tftp://255.255.255.255/cisconet.cfg
查看>>
java读取excel、txt 文件内容,传到、显示到另一个页面的文本框里面。
查看>>
《从零开始学Swift》学习笔记(Day 51)——扩展构造函数
查看>>