Reputation: 2124
Assume we have a legacy C file with some functions to solve linear equations and several corresponding global variables.
lineq.c:
/* macro definitions */
...
/* global vars */
...
/* some functions that make use of above variables */
void solveLinEq(...);
Now we want to use this legacy library in a modern multi-threaded C++ application. Therefore, we want to write a kind of wrapper class LinEqSolver
that provides an OO interface for solving linear equations and internally calls the functions of our legacy C library.
However, it should be possible that there are multiple instances of LinEqSolver
used by different threads. This requires that each instance/each thread has its own copies of the global variables in lineq.c
. How can this be achieved, if we don't want to modify the lineq.c
?
A possible solution I can imagine is to copy the global variables and the functions from the C file into the class LinEqSolver
, making them data and function members. Then, each instance of LinEqSolver
would operate on its private copy of the former globale variables. However, this copy-paste programming style is rather bad, especially when there is an update to lineq.c
and we need to copy-paste the changes into our code again.
What other possibilities do I have where the actual code to solve linear equations stays in lineq.c
and is just called from LinEqSolver
?
Upvotes: 1
Views: 524
Reputation: 10557
You can use thread_local
keyword from C++11. This will work well if your function always initializes all needed static variables in the beginning.
If you have more complex picture - more work will be needed. For example:
int myVar1, myVar2;
void InitStaticVars()
{
....
}
void solveLinEq(...);
If you will simply add thread_local
specifier to the variables above and call initialization function at the beginning of your program, it will initialize these variables only for the calling thread. On all other threads their initial values will be zeroes.
Upvotes: 1
Reputation: 4812
I would just bite the bullet and modify it to add the globals into a struct that should be passed as a pointer to all calls in lineq.c.
It is then easy to wrap this with a c++ class and have an instance per thread etc.
Another alternative would be to modify the c file to use __declspec(thread) or similar. However if you plan to put this code in a dll then you can expect insurmountable problems with that (on Windows, at least).
Upvotes: 0
Reputation: 2499
You could put lineq.c
in a shared object and load it multiple times with dlopen
and RTLD_PRIVATE
and use dlsym
for each thread, so the global variables are separate for every thread. Unfortunately RTLD_PRIVATE
isn't supported by glibc. Workaround for this would be to copy the shared object for every thread with a distinct name and use dlopen
to the copy of the shared object with RTLD_LOCAL
. lineq.c
remains untouched.
Upvotes: 1