我们有一个由我们正在积极开发的 fortran 二进制文件支持的 java 应用程序。我主要在 java 方面,我认为我的工作是保护在 fortran 上工作的人免受一些可能会打扰他们的讨厌的系统事情的影响,比如并发性,而不是强迫他们公开复杂的 API。
我按照这些思路做出的一个决定是将 Java 中的 JNA 样式回调传递到我们的 fortran 二进制文件中。当这个回调被执行时,我们的调用栈看起来像这样:
UIframework.click.java -- com.sun#1234
OurCode.UIHandlers.java -- our.code#2345
OurCode.doHeavyComputation.java -- our.code#4567
JNASurrogates.java -- com.sun.jna#456
JNASurrogates.proxy.f99 -- com.sun.proxies
HeavyComputation.f99 -- /code/algorithm.f99#1234
JNASurrogates.executeCallback.proxy.f99 -- com.sun.proxies
JNASurrogates.java -- com.sun.jna#1234
OurCode.computationComponents.java -- our.code#6789
//bottom of callstack
我的问题是线程之一:如何处理对同一个内存中 fortran DLL 的两个线程访问?我的问题植根于如何在内存中处理调用堆栈的确切细节:为了让 fortran 编译器生成可以从 JNA 调用的代码,而无需一个程序计数器破坏另一个,该编译器必须具有某种与 JVM 就调用堆栈的存储位置达成共识。X86 是否为我们提供了某种单独的程序计数器容器Pthreads
,java.lang.Thread
, 和其他线程库都利用这些容器,允许安全隔离调用堆栈?
为了让事情变得真正有趣,我也在讨论使用Quasar —— 对于那些不熟悉的人,Quasar 提供了所谓的“纤维”,它们是“轻量级线程”,由堆栈协同程序实现,这意味着 Quasar 执行堆栈的直接操作-帧。
问题是,虽然我在概念上很乐意将 公开OurCode.computationComponents
为回调,但一些业务需求决定了我不能。与其要求我们杰出的 fortran 程序员将他们现有的代码转换为具有显式入口和出口(返回)点的东西,我更愿意使用协程来利用我们现有的代码。
这个想法是协同例程将产生OurCode.computationComponents.java
任何作为返回值传递给computationComponents
. 然后调用者将完成计算组件回调通常所做的工作,将结果从 with 传入,这将返回并最终返回到HeavyComputation.f99
doHeavyComputation
resumeHeavyComputation
computationComponents
HeavyComputation.f99
我当然可以使用阻塞队列和多线程来完成所有这些工作,但试图限制自己使用一个线程意味着我对 Quasar 有一些了解,这有几个原因。
Quasar 能否处理并安全地恢复与我们正在使用的堆栈一样复杂的堆栈?