简体   繁体   English

使由函数初始化的变量可用于多线程环境中的函数

[英]Make a variable that is initialized by a function available to a function in multithreaded environment

So here is the problem I'm trying to solve, I'm programming in C. 所以这是我要解决的问题,我正在用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. 我有4个函数将custom_t用作输入,并且可以使用它做一些工作。

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. 无论线程如何,这些库函数都需要在同一个custom_t变量上工作。

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. 库函数不会传递给custom_t变量,因为目标是另一个用户应该能够使用库函数而无需考虑custom_t变量。

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. 我在想我必须在定义库函数的名称空间中将custom_t变量设置为全局变量,但是出现一个错误,指出全局变量必须为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(); 使用custom_t = init_custom(); you're trying to set a typename (ie custom_t ). 您正在尝试设置类型名称 (即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: 更新#2:

But do you know any way to initialize my_global_custom outside the main function? 但是您知道在主函数之外初始化my_global_custom的任何方法吗? Or is that just not possible? 还是那不可能?

Another way [under gcc at least], is to create a contructor function. [至少在gcc下]的另一种方法是创建构造函数。 Given the above functions and definitions, move the init calls into: 根据上述功能和定义,将init调用移至:

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. 它会在调用main 之前自动被调用,因为它现在是一个特殊功能。

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 (eg) init_liba(); init_libb(); ... 这些通常用于那些希望做一些初始化库,但希望负担 main有不必知道调用(如) init_liba(); init_libb(); ... init_liba(); init_libb(); ... init_liba(); init_libb(); ... In this case, it is called at the "right" time for the library [based upon linkage, etc.]. init_liba(); init_libb(); ...在这种情况下,它在库的“正确”时间被调用(基于链接等)。

There is also a __attribute__((destructor)) than can be used to "destroy" things [after main returns, IIRC]. 还有一个__attribute__((destructor))可以用来“破坏”事物[在main返回之后,IIRC]。

For more on this, see: How exactly does __attribute__((constructor)) work? 有关更多信息,请参见: __attribute __((constructor))到底如何工作?

Personally, I now use the above attribute, but, for nostalgia, I like the older .init/.fini sections. 就个人而言,我现在使用上述属性,但是出于怀旧之情,我喜欢旧的.init/.fini部分。

As clarified in you comment on @CraigEstey's answer, the problem is not that the variable needs to be const , but that its initializer needs to be a compile-time constant. 正如您对@CraigEstey的答案所做的评论所阐明的那样,问题不在于变量不必为const ,而是其初始值设定项必须为编译时常量。 One approach to this sort of problem is to define a static initialization value via a macro instead of as a function return value. 解决此类问题的一种方法是通过宏而不是函数返回值来定义静态初始化值。 For example, in some appropriate header file declare 例如,在一些适当的头文件中声明

typedef struct {
    int val1;
    int val2;
} custom_t;

#define CUSTOM_T_INITIALIZER { .val1 = 5, .val2 = 5 }

You can then initialize variables of type custom_t like so: 然后,您可以像这样初始化custom_t类型的变量:

custom_t some_name = CUSTOM_T_INITIALIZER;

, including at file scope. ,包括文件范围内的。

Update: 更新:

If you need to assign a value to your file-scope or static-duration variable that is not compile-time constant (including if it has an aggregate type and the value desired for one of its members is not a compile-time constant), then you cannot use an initializer for that purpose. 如果您需要为文件范围或静态持续时间变量分配一个非编译时常量的值(包括其具有聚合类型并且其成员之一所需的值不是编译时常量),那么您将无法为此使用初始化程序。 Instead, you must arrange to assign the wanted value to that variable after the program starts, perhaps by calling an initialization function of some sort. 相反,您必须安排在程序启动后将所需的值分配给该变量,可能是通过调用某种初始化函数来实现的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM