【问题标题】:How to encapsulate C/C++ library code to be runnable in a separate thread with multiple instances?如何封装 C/C++ 库代码以在具有多个实例的单独线程中运行?
【发布时间】:2025-12-26 10:15:16
【问题描述】:

想象一个项目的开发时间跨度超过 10 年。有些部分是 C 语言,有些是 C++ 语言,所有代码都使用全局函数和全局变量。该架构本质上是单线程设计的,并以这种方式不断发展。但现在我们考虑使用多核架构。

现在正在评估的一个想法是将代码的一部分重构到一个库中,以便可以创建多个实例,以便它们可以在单独的线程中运行并且不会相互干扰。

目前最受关注的建议是将所有库文件包装到带有宏定义的命名空间中,例如:

namespace VARIANT {
    // all the code
}

然后在标题或项目级别定义VARIANT。这将使得在不同的命名空间中有不同的上下文成为可能。卖点是这种方法需要最少的代码更改,并且引入任何回归的风险很低。

但是如果在某些时候我们需要使Variant1 的行为不同于Variant2,事情就会变得棘手,因为没有办法将宏定义的值与预处理器宏中的字符串进行比较。

有没有更优雅的方法来实现这一点?

【问题讨论】:

  • 优雅的方法是重构整个东西而不使用全局变量,但你已经知道了;)
  • 我不确定命名空间是否“优雅”——您必须将 C 文件转换为 C++ 文件(C 不支持命名空间!)并且您必须重新编译使用它的每个新线程的整个库!

标签: c++ c macros namespaces


【解决方案1】:

分步做,每次测试:

1) typedef 一个包含所有全局变量的结构。 malloc 之一,并编辑现有代码以引用它。测试 - 应该与使用全局变量完全相同。

2) 创建一个线程来运行一个代码实例。测试 - 应该与使用全局变量完全相同。

3) 尝试多个线程。

一步一个脚印……

请尽量不要尝试任何障碍!

【讨论】:

    【解决方案2】:

    重构一个旧项目并使其成为多线程并不是那么简单。首先,你有 C 和 C++ 代码的混合,你不能在这里盲目地遵循 C++ 方法。您需要在以下区域而不是命名空间:-

    1. 找出所有需要同步的代码块、容器,如listlarge array 等对象。
    2. 找出线程的相互依赖性以及如何控制它们。例如,一个线程将生成报告并插入到表中,而第二个线程需要该信息来生成其最终报告,现在您需要找出代码库中线程之间的这种依赖关系,并需要找出它们的控制机制.
    3. C++ 中的旧式多线程非常棘手,因此您需要将代码迁移到 C++11,这样多线程的实现要容易得多。

    4. 正如您所说,在您当前的项目中有很多全局变量,您需要正确考虑如何在不同线程之间共享这些变量以及如何同步访问这些变量。

    这些是您在开始重构之前需要提前考虑很多方面的一些提示,否则您的所有努力都会付诸东流。

    祝你的计划好运。

    【讨论】:

      【解决方案3】:

      另一个变体可能是发现所有全局变量并将它们设为thread_local。需要 C++11 或至少提供相同的编译器扩展(__thread 使用较旧的 GCC)。

      如果我没看错this question,你甚至不需要将你的 C 文件转换成 C++ 文件(你的方法需要它,因为 C 不支持命名空间......),但你需要 C11。

      【讨论】:

      • 这似乎是一个不错的选择。当然,一个全面的重构策略会比这更广泛,但thread_local 提供了与namspace 类似的每线程分离,只是以更简洁的方式。