我试图理解新的C++ 11标准中的基本多线程机制.我能想到的最基本的例子如下:
这个例子也被用在许多关于多线程的学校书籍中,关于通信过程的一切都很好.但是,在停止使用者线程时我遇到了问题.
我希望消费者运行直到它获得明确的停止信号(在大多数情况下,这意味着我等待生产者完成所以我可以在程序结束之前停止消费者).不幸的是,C++ 11线程缺少一种中断机制(例如我从Java中的多线程中知道).因此,我必须使用标志isRunning
来表示我想要一个线程停止.
现在的主要问题是:在我停止生产者线程之后,队列为空并且消费者在等待a condition_variable
再次填充队列时获取信号.所以我需要通过notify_all()
在退出之前调用变量来唤醒线程.
我找到了一个有效的解决方案,但似乎有些混乱.下面列出了示例代码(很抱歉,但不知何故,我无法为"最小"最小示例减少代码大小):
队列类:
class Queue{
public:
Queue() : m_isProgramStopped{ false } { }
void push(int i){
std::unique_lock<std::mutex> lock(m_mtx);
m_q.push(i);
m_cond.notify_one();
}
int pop(){
std::unique_lock<std::mutex> lock(m_mtx);
m_cond.wait(lock, [&](){ return !m_q.empty() || m_isProgramStopped; });
if (m_isProgramStopped){
throw std::exception("Program stopped!");
}
int x = m_q.front();
m_q.pop();
std::cout << "Thread " << std::this_thread::get_id() << " popped " << x << "." << std::endl;
return x;
}
void stop(){
m_isProgramStopped = …
Run Code Online (Sandbox Code Playgroud) 在摆弄复制省略时,我遇到了这种奇怪的行为:
class Obj {
public:
Obj() = default;
Obj(Obj&&) = delete;
Obj(const Obj&) { std::cout << "Copy" << std::endl; }
};
Obj f1() {
Obj o;
return o; // error C2280: move constructor is deleted
}
Obj f2() {
Obj o;
return Obj(o); // this however works fine
}
int main() {
Obj p = f1();
Obj q = f2();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
GCC 和 Clang 接受此代码并且能够在两种情况下使用复制省略。
在f1()
MSVC 中抱怨它无法返回,o
因为Obj
删除了 的移动构造函数。但是,我希望它能够依靠复制构造函数。这是 MSVC 中的错误还是这种期望的行为(我不明白)和 GCC/Clang …
我在这里发现了几个问题,这些问题涉及检查给定类型是否存在成员函数、自由函数或运算符。提议的解决方案解决了手头的问题,但每个解决方案都使用不同的方法。我试图找到一种方法来以相同或至少类似的方式处理这些问题中的每一个。
检查类型C
是否有成员func
有效:
template<typename, typename T>
struct has_member {
static_assert(
std::integral_constant<T, false>::value,
"Second template parameter needs to be of function type.");
};
template<typename C, typename Ret, typename... Args>
struct has_member<C, Ret(Args...)> {
private:
template<typename T, std::enable_if_t<
std::is_same
<
decltype(std::declval<T>().func(std::declval<Args>()...)),
Ret
>::value
> * = nullptr >
static constexpr std::true_type check(T*);
template<typename>
static constexpr std::false_type check(...);
typedef decltype(check<C>(nullptr)) type;
public:
static constexpr bool value = type::value;
};
Run Code Online (Sandbox Code Playgroud)
这取自这个问题的最高投票答案: 检查类是否具有给定签名 的成员函数编译条件刚刚从返回类型移至模板参数。
检查是否operator+
存在也可以:
template<typename C, typename …
Run Code Online (Sandbox Code Playgroud) c++ ×3
c++11 ×1
c++14 ×1
c++17 ×1
copy-elision ×1
enable-if ×1
interrupt ×1
templates ×1
visual-c++ ×1