servcraft/p7Stackful協(xié)程庫
servcraft/p7是使用C實現(xiàn)的stackful協(xié)程庫,提供“半”透明的CSP并發(fā)。
目前,servcraft只支持Linux/GCC/pthread. 由于阻塞IO封裝使用了epoll, 推薦使用Linux 2.6以上。
若要利用servcraft提供的GCC閉包功能,請使用主版本號不低于5的GCC.
servcraft/p7所使用的協(xié)程(coroutines, coro)提供類似goroutine的功能。
-
編寫并發(fā)程序的過程較一般事件驅(qū)動框架更簡單。每個協(xié)程假定自己和其他協(xié)程一樣,被并發(fā)地調(diào)度且獨立地執(zhí)行,因而可以順序編寫邏輯。
-
為使用文件描述符的系統(tǒng)調(diào)用提供了IO阻塞-重調(diào)度接口。協(xié)程阻塞在IO操作上時自動暫停執(zhí)行、引發(fā)重調(diào)度,IO就緒時重新獲得調(diào)度權(quán)。
-
提供Actor風(fēng)格的協(xié)程間通信。協(xié)程可以注冊自身名字,并按注冊的協(xié)程名向其他協(xié)程的內(nèi)建郵箱中(零拷貝地)投遞信息。
-
所有IO和協(xié)程間通信的阻塞接口都自帶超時定時器。
-
提供協(xié)程間瘦自旋鎖和讀寫自旋鎖。讀寫自旋鎖使用盡量公平對待讀者、寫者的機制。
簡介和簡單demo可以在這里獲得。一個粗暴的echo server如下:
#include <stdio.h>
#include "./net_common.h" // common header for necessary network APIs
#include <sys/stat.h>
#include "../servcraft/p7/libp7.h"
#include "../servcraft/p7/p7_root_alloc.h"
#include "../servcraft/include/model_alloc.h"
void test_echo(void *arg) {
intptr_t fd_conn_i64crap = (long long) arg;
int fd_conn = (int) (fd_conn_i64crap & 0xFFFFFFFF);
char msg[32];
memset(msg, 0, sizeof(char) * 32);
int ret = p7_iowrap_timed(recv, P7_IOMODE_READ, 30000, fd_conn, msg, sizeof(msg), 0);
switch (ret) {
case -1:
printf("internal error\n");
break;
case -2:
printf("p7 timed out\n");
break;
default:
p7_iowrap(send, P7_IOMODE_WRITE, fd_conn, msg, strlen(msg), 0);
}
close(fd_conn);
}
void test_timeout(void *arg) {
long long fd_conn_i64crap = (long long) arg;
int fd_conn = (int) (fd_conn_i64crap & 0xFFFFFFFF);
printf("Timed out: %d\n", fd_conn);
}
void test_echo_wrapper(void *arg) {
p7_coro_concat(test_echo, arg, 2048);
}
void test_startup(void *unused) {
printf("startup\n");
}
int main(int argc, char *argv[]) {
__auto_type allocator = p7_root_alloc_get_allocator();
allocator->allocator_.closure_ = malloc;
allocator->deallocator_.closure_ = free;
allocator->reallocator_.closure_ = realloc;
struct p7_init_config config;
config.namespace_config.namespace_size = 1024;
config.namespace_config.rwlock_granularity = 10;
config.namespace_config.spintime = 400;
config.pthread_config.nthreads = atoi(argv[1]);
config.pthread_config.at_startup = test_startup;
config.pthread_config.arg_startup = NULL;
p7_init(config);
int fd_listen;
if ((fd_listen = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
struct sockaddr_in lserv;
lserv.sin_family = AF_INET;
lserv.sin_port = htons(8080);
lserv.sin_addr.s_addr = inet_addr(argv[2]);
bzero(&(lserv.sin_zero), 8);
if (bind(fd_listen, (struct sockaddr *) &lserv, sizeof(lserv)) == -1) {
perror("bind");
exit(1);
}
if (listen(fd_listen, 5) == -1) {
perror("listen");
exit(1);
}
while (1) {
struct sockaddr_in rcli;
socklen_t addrlen = sizeof(rcli);
int fd_conn = p7_iowrap(accept, P7_IOMODE_READ, fd_listen, (struct sockaddr *) &rcli, &addrlen);
intptr_t fd_conn_i64crap = fd_conn;
p7_coro_create(test_echo_wrapper, (void *) fd_conn_i64crap, 512);
}
return 0;
}
評論
圖片
表情
