c++ - setjmp 和 longjump 实现线程

标签 c++ multithreading coroutine setjmp

我有一个关于使用 setjmp 和 longjump 来创建可以相互独立运行的函数堆栈的问题。引用this question

此处 B() 的函数堆栈似乎位于 A 的函数堆栈之上,因此当 A 超出范围并且我尝试长跳转到 B() 时,代码出现段错误。修改后的代码是这样的

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

jmp_buf bufferA, bufferB;

void routineB(); // forward declaration 

void routineA()
{
    int r ;

    printf("(A1)\n");

    r = setjmp(bufferA);
    if (r == 0) routineB();

    printf("(A2) r=%d\n",r);

    r = setjmp(bufferA);
    if (r == 0) longjmp(bufferB, 20001);

    printf("(A3) r=%d\n",r);

    r = setjmp(bufferA);
    if (r == 0) longjmp(bufferB, 20002);

    printf("(A4) r=%d\n",r);
}

void routineB()
{
    int r;

    printf("(B1)\n");

    r = setjmp(bufferB);
    if (r == 0) longjmp(bufferA, 10001);

    printf("(B2) r=%d\n", r);

    r = setjmp(bufferB);
    if (r == 0) longjmp(bufferA, 10002);

    printf("(B3) r=%d\n", r);

    r = setjmp(bufferB);
    if (r == 0) longjmp(bufferA, 10003);

    cout << "WHAT" << endl;
}


int main(int argc, char **argv) 
{
    routineA();
    longjmp(bufferB, 123123);
    return 0;
}

我在想,我们可以让每个协程(在本例中为 B 和 A)跳回一个主函数,然后跳转到其中一个协程,前提是它们还活着。这会起作用还是会出现段错误,因为一些可能已死亡的协程堆栈位于想要运行的协程堆栈之上?

如果它看起来确实应该出现段错误,那么如何在 C++ 中实现这样的独立协程(它们可以在其他协程死亡并且不依赖彼此时运行)?

注意:我不想使用 swapcontext、makecontext、setcontext 和 getcontext,因为它们已被弃用。这篇文章的目的是帮助我找到这些功能的替代品

提前致谢!

最佳答案

它应该可以工作,但需要采取一些预防措施。它曾经在九十年代工作。

只要堆栈中较旧的线程不返回,它就可以工作,那么应该没有问题。对于生成器或线程,这意味着它以一些最终 yield 终止,但没有返回。

我记得我要求 IBM 修复他们的 setjmp/longjmp 的 AIX 实现,以便它停止检查(并禁止)其他实现允许的有用行为。这是我当时发现的实现协作线程的最便携方式。

您可以使用基于状态机的堆栈分配器做得更好,以便为不同的线程分配/释放不同大小的堆栈。

据我所知,这非常棘手。我记得多年后 Matz(来自 Ruby)问我关于它的代码,但遗憾的是我当时无法访问它。

无论如何,现在这并不重要,因为 pthread 完成了这项工作。

关于c++ - setjmp 和 longjump 实现线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33408007/

相关文章:

c++ - Variadic 模板基类调用转移

c++ - 将 4 个整数的组合映射到单个值

c++ - 带有 boost::any 的 cout 映射

c# - 如何从一个对象启动两个并行线程?

java - java中繁忙的等待线程

c# - 扩展方法中的协程

C++ uniform_int_distribution 总是在第一次调用时返回 min()

java - 是否有默认的 ExecutorService 或我注定要创建一个并维护它以获得 Future objetcs?

scheme - 实现 yield 并在 Scheme 中发送

c++ - Boost.Coroutine在 sleep 方面如何使用类似Unity3D Coroutine的方式?