正确 pthread_t 初始化和处理

Correct pthread_t initialization and handling

我知道 pthread_t 应该被视为一个不透明的值,但是我不知道在用作 class 成员时如何初始化它,以及如何检查它的有效性.

考虑此代码示例:

class MyClass
{
public:
    pthread_t thread;

    MyClass()
        : thread(0) // Wrong because pthread_t should be an opaque value,
                    // so how should I initialize it?
    {}

    ~MyClass()        
    {
        if( thread ) // Wrong, but how can I verify if it is valid?
            pthread_join(thread, NULL);
    }
};

我也理解如果pthread_create()失败,可能是pthread_t值不一致。所以我应该只依赖 pthread_create() 的 return 值。但这意味着我应该将此 returned 值与 pthread_t 一起保留并使用它来检查线程有效性?在这种情况下,我应该如何在 class 构造函数中初始化这个值?

class MyClass
{
public:
    pthread_t thread;
    int threadValid;

    MyClass()
        : thread(0), // Wrong because pthread_t should be an opaque value,
                     // so how should I initialize it?
        , threadValid(1) // pthread_create return zero in case of success,
                         // so I can initialize this to any nonzero value?
    {}

    ~MyClass()        
    {
        if( threadValid == 0 ) // Nonzero means thread invalid.
                               // Is this the correct approach?
        {
            pthread_join(thread, NULL);
            threadValid = 1;
        }
    }
};

我有一个 Windows API 背景,并且有一个线程有它的 HANDLE 值,可以安全地初始化为 NULL,并且可以检查NULL,如果 CreateThread() 失败,它只会一直 returns NULL。使用 pthreads 就没有办法保持这种简洁明了的方法吗?

pthread_t 是 C 类型,所以它必须有一个平凡的默认构造函数;所以你可以对它进行值初始化:

    : thread(), // ...

您对 threadValid 的用法似乎有些混乱。最好将其设置为 bool,最初设置为 false,然后在 pthread_create 成功后才将其设置为 true

不幸的是,您只能使用保护变量来了解其值是否有意义。 因此,例如您不能使用 0,因为它在某些系统上是有效的 pthread_t(例如 DG/UX)。 您应该必须使用其他东西来知道该值是否可以使用,并且您应该对其进行值初始化。

如果您可以在可移植性(例如非生产代码)上做出妥协,请考虑 Linux 和 Android pthread_t 应该像一个 int 类型,而在 Darwin 上它应该是一个句柄,所以如果你将它初始化为 0,它就会工作。

But this means that I should keep this returned value along with pthread_t and use it to check thread validity?

是的,或者更简单地保留一个布尔值,就像已经提到的那样。

And in this case, how should I initialize in the class constructor this value?

不要初始化,在C++中不强制初始化成员。

pthread_t   thread_handle;
pthread_attr_t  thread_attributes;

pthread_attr_init(&thread_attributes);
pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_JOINABLE);

threadValid = (::pthread_create(&thread_handle, &thread_attributes, function, data) == 0);

关闭时:

if (threadValid) {
    ::pthread_join(thread_handle, 0);
}

尽管如此,请不要开始您的话题in the constructor