对于C++(不确定原帖中在问什么语言),另一种简单的选择是使用
std::optional<pthread_t>
(如果您无法使用C++17或更高版本,则可以使用boost版本,或者自己实现类似的东西)。但我认为
this one仍然是最简单的选择,只要您不需要将
pthread_self()
视为任何地方有效。
然后使用
.has_value()
检查值是否有效,并感到高兴:
std::optional<pthread_t> create_thread (...) {
pthread_t thread;
if (pthread_create(&thread, ...))
return std::optional<pthread_t>();
else
return thread;
}
std::optional<pthread_t> id = create_thread(...);
if (id.has_value()) {
pthread_join(id.value(), ...);
} else {
...;
}
在比较有效值时,您仍然需要使用pthread_equal
,因此所有相同的警告都适用。但是,您可以可靠地将任何值与无效值进行比较,因此像这样的内容将是可以接受的:
const std::optional<pthread_t> InvalidID;
pthread_t id1 = ;
std::optional<pthread_t> id2 = ;
if (id1 == InvalidID) { }
if (id1 != InvalidID) { }
if (id2 == InvalidID) { }
if (id2 != InvalidID) { }
顺便说一下,如果你想要给自己一些适当的比较运算符,或者如果你想要制作一个可插拔替换的 pthread_t(在这种情况下,你不必调用 .value()),那么你就需要编写自己的小包装类来处理所有的隐式转换。这很简单,但也有点跑题,所以我会在这里放一些代码,并在评论中提供信息,如果有人问的话。这里有 3 个选项,取决于你想支持多老的 C++。它们提供了对 pthread_t 的隐式转换(不能使用 pthread_t*),因此代码更改应该是最小的:
#include <optional>
struct thread_id {
thread_id () =default;
thread_id (const pthread_t &t) : t_(t) { }
operator pthread_t () const { return value(); }
friend bool operator == (const thread_id &L, const thread_id &R) {
return (!L.valid() && !R.valid()) || (L.valid() && R.valid() && pthread_equal(L.value(), R.value()));
}
friend bool operator == (const pthread_t &L, const thread_id &R) { return thread_id(L) == R; }
bool valid () const { return t_.has_value(); }
void reset () { t_.reset(); }
pthread_t value () const { return t_.value(); }
private:
std::optional<pthread_t> t_;
};
#include <optional>
struct thread_id {
thread_id () =default;
thread_id (const pthread_t &t) : t_(t) { }
operator pthread_t () const { return value(); }
friend bool operator == (const thread_id &L, const thread_id &R) {
return (!L.valid() && !R.valid()) || (L.valid() && R.valid() && pthread_equal(L.value(), R.value()));
}
friend bool operator == (const thread_id &L, const pthread_t &R) {return L==thread_id(R);}
friend bool operator == (const pthread_t &L, const thread_id &R) {return thread_id(L)==R;}
friend bool operator != (const thread_id &L, const thread_id &R) {return !(L==R);}
friend bool operator != (const thread_id &L, const pthread_t &R) {return L!=thread_id(R);}
friend bool operator != (const pthread_t &L, const thread_id &R) {return thread_id(L)!=R;}
bool valid () const { return t_.has_value(); }
void reset () { t_.reset(); }
pthread_t value () const { return t_.value(); }
private:
std::optional<pthread_t> t_;
};
struct bad_pthread_access : public std::runtime_error {
bad_pthread_access () : std::runtime_error("value() called, but !valid()") { }
};
struct thread_id {
thread_id () : valid_(false) { }
thread_id (const pthread_t &t) : thr_(t), valid_(true) { }
operator pthread_t () const { return value(); }
friend bool operator == (const thread_id &L, const thread_id &R) {
return (!L.valid() && !R.valid()) || (L.valid() && R.valid() && pthread_equal(L.value(), R.value()));
}
friend bool operator == (const thread_id &L, const pthread_t &R) { return L==thread_id(R); }
friend bool operator == (const pthread_t &L, const thread_id &R) { return thread_id(L)==R; }
friend bool operator != (const thread_id &L, const thread_id &R) { return !(L==R); }
friend bool operator != (const thread_id &L, const pthread_t &R) { return L!=thread_id(R); }
friend bool operator != (const pthread_t &L, const thread_id &R) { return thread_id(L)!=R; }
bool valid () const { return valid_; }
void reset () { valid_ = false; }
pthread_t value () const {
if (!valid_) throw bad_pthread_access();
return thr_;
}
private:
pthread_t thr_;
bool valid_;
};
pthread_t invalid_thread = pthread_self()
来提高可读性。 - Tony Delroystd::optional<pthread_t>
是另一个可能的选择。 - Jason C