创建一个由多线程环境

时间:2016-08-24 22:29:25

标签: c multithreading shared-resource

所以这就是我试图解决的问题,我在C编程。

我们有一个可以为你初始化结构的函数。

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

custom_t init_custom() {
  custom_t temp;

  temp.val1 = 5;
  temp.val2 = 5;


  return temp;
}

你会像这样使用它:

custom_t some_name = init_custom();

我有4个函数,它们将custom_t作为输入,可以使用它做一些工作。

在另一个文件中,我有很多将在多线程环境中运行的库函数。无论是什么线程,这些库函数都需要对同一个custom_t变量进行操作。

库函数不会传递给它的custom_t变量,因为目标是另一个用户应该能够使用库函数而不需要考虑custom_t变量。

我认为我必须在我定义库函数的命名空间中使custom_t变量全局化,但我错误地说全局变量必须是const。

我不确定如何实现这一目标,我将非常感谢能得到的所有帮助。如果我的解释不够好,请随意提出任何问题,我会尽力详细说明。

编辑: 修复了变量init typo

2 个答案:

答案 0 :(得分:3)

使用custom_t = init_custom();,您尝试设置 typename (即custom_t)。

只需将其称为其他内容:

custom_t my_global_custom = init_custom();

但是,要从多个线程和库函数访问它,假设您需要写入它,您需要在互斥锁中包含对此的访问权限:

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);

<强>更新

我的示例并非意图字面 初始化,而是分配

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;
}

更新#2:

  

但是你知道在主函数之外初始化my_global_custom的方法吗?或者这是不可能的?

[至少在gcc之下]的另一种方法是创建构造函数函数。鉴于上述功能和定义,将init调用移至:

void __attribute__((constructor))
my_global_constructor(void)
{

    my_global_custom = init_custom();
    init_custom2(&my_global_2);
}

没有什么需要[并且没有 ]调用此函数。它将在调用 main之前自动调用,因为它现在是一个特殊功能。

这些通常用于想要执行某些初始化的库,但不要想要负担 main,而不得知道来调用(例如)init_liba(); init_libb(); ...在这种情况下,它会在&#34;右边&#34;图书馆的时间[基于联系等]。

还有一个__attribute__((destructor))可用于&#34;销毁&#34;事件[在main之后返回,IIRC]。

有关详情,请参阅:How exactly does __attribute__((constructor)) work?

就个人而言,我现在使用上述属性,但是,对于怀旧情绪,我喜欢较旧的.init/.fini部分。

答案 1 :(得分:1)

正如你在@ CraigEstey的回答中所阐述的那样,问题不在于变量需要const,而是它的初始值设定项需要是编译时常量。解决此类问题的一种方法是通过宏而不是函数返回值来定义静态初始化值。例如,在一些适当的头文件声明

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

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

然后您可以像这样初始化custom_t类型的变量:

custom_t some_name = CUSTOM_T_INITIALIZER;

,包括文件范围。

更新

如果需要为不是编译时常量的文件范围或静态持续时间变量赋值(包括它是否具有聚合类型,并且其成员之一所需的值不是编译时)常数),那么你不能为此目的使用初始化器。相反,您必须安排在程序启动后将所需值分配给该变量,可能是通过调用某种初始化函数。