So here is the problem I'm trying to solve, I'm programming in C.
We have a function that can initialize a struct for you.
typedef struct {
int val1;
int val2;
} custom_t;
custom_t init_custom() {
custom_t temp;
temp.val1 = 5;
temp.val2 = 5;
return temp;
}
And you would just use it like so:
custom_t some_name = init_custom();
I have 4 functions that takes the custom_t as input and can do some work with it.
In another file I have a lot of library functions that will run in a multithreaded enviroment. These library functions will all need to do work on the same custom_t variable, no matter the thread.
The library functions won't get the custom_t variable passed to it, because the goal is that another user should be able to use the library functions without thinking of the custom_t variable.
I'm thinking that I have to make the custom_t variable global in the namespace where I define the library functions but I an error saying that global variables must be const.
I am unsure how to achieve this and I would appreciate all the help I can get. If my explanation wasn't good enough feel free to ask any questions and I will try to elaborate.
EDIT: Fixed the variable init typo
With custom_t = init_custom();
you're trying to set a typename (i.e. custom_t
).
Just call it something else:
custom_t my_global_custom = init_custom();
But, to access this from multiple threads and library functions, assuming you'll need to write to it, you'll need to wrap access to this in a mutex:
pthread_mutex_t custom_mutex = PTHREAD_MUTEX_INITIALIZER;
custom_t my_global_custom;
my_global_custom = init_custom();
// how each thread must access it
pthread_mutex_lock(&custom_mutex);
func_that_uses_my_global_custom();
pthread_mutex_unlock(&custom_mutex);
UPDATE:
My example wasn't intended to be literally an initializer but an assignment:
pthread_mutex_t custom_mutex = PTHREAD_MUTEX_INITIALIZER;
custom_t my_global_custom;
custom_t my_global_2;
custom_t
init_custom(void)
{
custom_t temp;
temp.val1 = 5;
temp.val2 = 5;
return temp;
}
void
init_custom2(custom_t *temp)
{
temp->val1 = 5;
temp->val2 = 5;
}
int
main(void)
{
// either one of these should work ..
my_global_custom = init_custom();
init_custom2(&my_global_2);
// start some threads ...
return 0;
}
void *
thread_func(void *)
{
// how each thread must access it:
pthread_mutex_lock(&custom_mutex);
func_that_uses_my_global_custom();
pthread_mutex_unlock(&custom_mutex);
return (void *) 0;
}
UPDATE #2:
But do you know any way to initialize my_global_custom outside the main function? Or is that just not possible?
Another way [under gcc
at least], is to create a contructor function. Given the above functions and definitions, move the init calls into:
void __attribute__((constructor))
my_global_constructor(void)
{
my_global_custom = init_custom();
init_custom2(&my_global_2);
}
Nothing needs to [and nothing should] call this function. It will be called automatically before main
is called because it's now a special function.
These are often used by libraries that want to do some init, but don't want to burden main
with having to know to call (e.g.) init_liba(); init_libb(); ...
In this case, it is called at the "right" time for the library [based upon linkage, etc.].
There is also a __attribute__((destructor))
than can be used to "destroy" things [after main
returns, IIRC].
For more on this, see: How exactly does __attribute__((constructor)) work?
Personally, I now use the above attribute, but, for nostalgia, I like the older .init/.fini
sections.