New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarification of behavior regarding threads #517

Open
jnjaeschke opened this Issue Jan 9, 2019 · 5 comments

Comments

Projects
None yet
3 participants
@jnjaeschke
Copy link

jnjaeschke commented Jan 9, 2019

We encountered problems using FMUs from different threads.
Depending on frameworks or libraries used (e.g. Qt, COM-Server) a FMU can crash when it is accessed from different threads (e.g. instantiated in thread A, used in thread B, free'd in thread C).

Quoting the FMI2 specification, sec. 2.1 "FMI Application Programming Interface":

FMI functions of one instance don't need to be thread safe. [For example, if the functions of one instance of an FMU are accessed from more than one thread, (...)]"

So, implicitly it is assumed that you may call FMUs from different threads. But it is not explicitly stated that the exporting tool has to ensure that the FMU works in a multi-threaded environment and can be instantiated, used and free'd from different threads.

Thinking of how much time it cost to figure out that this was a problem (and to find a solution for it) from both an importing and exporting tool vendor's view, I would propose to add a sentence to the specification stating

A FMU must by design be capable of being called from different threads.
[It has to be expected that fmi functions are called from several threads. Any threading-sensitive portions of code have to be encapsulated in a fashion that they are not affected by being called from different threads.]

That way it is explicitly defined that a FMU must be robust enough to handle this and the exporting tool vendors are required to take care if they use thread-sensitive libraries.

@pmai

This comment has been minimized.

Copy link
Collaborator

pmai commented Jan 9, 2019

Hmmm, how is this supposed to work? An FMU would have to be robust against all kinds of threading schemes, unknown to itself, since it does not know about the threading scheme used by the host (i.e. does the host use some form of green threads? Does it use OS-provided threads, does it roll its own? What are suitable locking schemes? What about necessary threading restrictions of the OS?).

While it would be nice to add informative (non-normative) text pointing out common problems, I don't think FMU authors can provide blanket guarantees that their code is going to work with any kind of threading system...

@andreas-junghanns

This comment has been minimized.

Copy link
Contributor

andreas-junghanns commented Jan 9, 2019

I have to add to Pierre's scepticism: An FMU has a state and callers must know the state of the FMU. If multiple threads call into the FMU they all might change its state. They would have to share their understanding of which state the FMU is in in order to each comply with the standard's function call restrictions. If someone wants to go down this path, they can now do so. Why should every FMU add the overhead to be thread safe? If your environment requires this, you could add a thread-safety layer around the calls to the imported FMUs.

@jnjaeschke

This comment has been minimized.

Copy link

jnjaeschke commented Jan 9, 2019

Fair enough...

Then how about going the other way and restrict the importing tools to only call the FMU from one thread? That would solve that problem as well. Calling a FMU multi-threaded is possibly not the best coding style anyways ...

@andreas-junghanns

This comment has been minimized.

Copy link
Contributor

andreas-junghanns commented Jan 9, 2019

I don't understand: Why should we unnecessarily restrict the use of an FMU to a single thread? All we need to do is clarify that the FMU is not responsible for thread-safe usage and delegate this responsibility to the importer. What do we gain declaring one use case illegal?

@jnjaeschke

This comment has been minimized.

Copy link

jnjaeschke commented Jan 10, 2019

Ah, how do I get out of this one? :)

Initially I wanted to propose "okay, let's state explicitly that it might be dangerous to (a) rely on threading-sensitive libraries on the exporter's side and (b) to use a FMU in a multi-threaded way". With that information given in the spec hopefully nobody tries to go that path(s) and one compatibility issue (and that is an acceptance issue for FMI!) is gone.

What I got out of your comments was "robustness can't be guaranteed (Pierre), using FMUs multi-threaded is dangerous (Andreas)".
So I thought, okay what does one gain by allowing to use a FMU multi-threaded? I couldn't think of any points ... if you want to use a FMU multi-threaded, put it in a thread and communicate with it using that thread. Then you're safe.

That being said it was (my) logical conclusion. If we restrict this, the few people that would have implemented their FMU / importing tool in such a manner know that (and more important, they know why!) they have to change their code. And the other users that did not use such mean things in the first place won't care anyway.

Overall, this is a minor issue that 99% of users perhaps won't ever come across because presumably almost no FMUs rely on thread-sensitive libs and almost no importers use the FMUs multi-threaded. But for us, exactly that combination happened. Not just with our FMU and our tool but also with a FMU from a different vendor. And it cost some time to debug and find a solution for this (... which is "don't use FMUs multi-threaded. That only gets you into trouble.").

To conclude ... it would be okay for me to just put an informational message into the spec that says "when you use FMUs multi-threaded, we hope you know what you're doing. And if you export FMUs, have in mind that they might be used multi-threaded". But if we restrict it, we gain more safety as this problem can't occur anymore (at least not for valid FMUs and valid importing tools). And we lose... actually nothing (I guess). Even more, such a clear statement (especially if there also is a good motivation given for that decision) would lead to a clearer and better standard.
Then there's no room for interpretation or devs thinking "ahh, nevermind, that might just work."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment