小编Via*_*lov的帖子

是否为记录器创建单独的线程?

我在Qt中编写了一个多线程应用程序(几个线程都有自己的事件循环).记录时,我希望记录器在日志中包含一个线程ID(它们具有有意义的名称).Qt默认记录器似乎无法做到这一点.所以我有三个选择:

  1. 每个线程都自己进行日志记录(这涉及互斥,因此可能是最糟糕的方法,但我不确定)
  2. 有一个专用的记录器线程和其他线程直接将事件发布到它(可能比3更快)
  3. 与2.相同但是消息是通过信号/插槽系统调度的(实际上,这也会导致发布事件).

哪一个更好,一般的最佳做法是什么?


在评论中提出问题后要澄清一些事项:

  • QThread有一个标准方法postEvent(),它是线程安全的.

所以问题就变成了,记录器线程是否需要为每个事件做足够的工作来证明在某种队列中编组事件数据的成本是合理的

  • 这就是问题的实质.我知道最好的答案是"测量!",但目前应用程序处于早期开发阶段,没有太多可衡量的.从一开始就选择合适的设计总是好的.
  • 在我的情况下,线程可能是一个好主意:它是一个媒体播放器,所以有GUI线程,回放线程,DB /媒体库线程,网络线程池......换句话说,整个动物园的线程.

c++ logging qt multithreading

9
推荐指数
1
解决办法
1593
查看次数

Makefile调用函数.如何获得所有论点

当我在Makefile中定义自定义函数时,就像这样

define add_target
${1}: ${2} ${3}
endef
Run Code Online (Sandbox Code Playgroud)

如何获得已提供给所有参数的列表$(call add_target, ...)

所以这$(call add_target, A, B)将扩展到A: B ,$(call add_target, A, B, C, D)并将扩展到A: B C D

GNU手册只说明了这一点

当make扩展此函数时,它会将每个参数分配给临时变量$(1),$(2)等.变量$(0)将包含变量.没有最大数量的参数参数.

但没有关于如何获得所有参数.

makefile gnu-make

6
推荐指数
1
解决办法
6284
查看次数

SFINAE不能用于constexpr功能吗?

为了支持可移植性,我想根据size_t32位或64位的事实选择一个常量.代码:

using namespace std;

namespace detail {
    template<enable_if<is_same<size_t, uint32_t>::value,void*>::type = nullptr>
    constexpr static const size_t defaultSizeHelper() {
        return ( (size_t) 1 << 30 ) / 2 * 5; //2,5 Gb
    }
    template<enable_if<is_same<size_t, uint64_t>::value,void*>::type = nullptr>
    constexpr size_t defaultSizeHelper() {
        return numeric_limits<size_t>::max() / 2;
    }
}

constexpr static size_t defaultSize = detail::defaultSizeHelper();
Run Code Online (Sandbox Code Playgroud)

由于这个代码不能编译 error: 'std::enable_if<false, void*>::type' has not been declared. template<enable_if<is_same<size_t, uint64_t>::value,void*>::type = nullptr>

编译器 - GCC 4.9

在我看来,编译器不会将SFINAE原则应用于a constexpr.那我该怎么办?

c++ templates enable-if constexpr c++11

5
推荐指数
2
解决办法
1317
查看次数

Java:Pattern在Scanner中的行为有所不同

遇到了Java中正则表达式匹配的奇怪行为.第一个输出命令true按预期打印,但是当打包相同的字符串时Scanner,输出为false.我究竟做错了什么?

public static void main(String[] args) {
  Pattern p = Pattern.compile(" *\\[");
  System.out.println(p.asPredicate().test("[]")); //true

  Scanner s = new Scanner("[]");
  System.out.println(s.hasNext(" *\\[")); //false
}
Run Code Online (Sandbox Code Playgroud)

java regex java.util.scanner

3
推荐指数
1
解决办法
133
查看次数

这种无锁的 dlist 插入安全吗?

我需要在双向链表的头部实现子列表的无锁插入。该列表有一个虚拟头,因此每个线程都尝试将其部分插入到头节点之后。这个设计对我来说似乎不错,但是,我没有足够的专业知识来证明这一点。

struct Node {
  std::atomic<Node*> next;
  std::atomic<Node*> prev;
};
Node head;

// concurrently insert `first`..`last` sublist after `head`
void insertSublist(Node* first, Node* last) {
  first->prev = &head;
  Node* current_next = head.next;

  while (true) {
    last->next = current_next;
    if (head.next.compare_exchange_weak(current_next, first)) {
      current_next->prev = last;
      return;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我需要在这些情况下验证这个设计:

变体1

不执行列表删除,所有线程只是在循环中进行插入。

变体2

有 1 个线程,以随机顺序从列表中删除节点,但它永远不会删除紧随头节点之后的节点。

for (auto* node : nodes_to_be_removed) {
  if (node->prev == &head)
    continue;
  // perform removal 
}
Run Code Online (Sandbox Code Playgroud)

插入完成后,node->prev是最后更改的链接。所以改变后,其他线程(除了reminder)都不能访问该节点或其前一个节点next链接。这个推理有效还是我遗漏了什么?


@peter-cordes 回答后的一些澄清。

  • 该列表不是线性可遍历的,因此从这个角度来看,不一致的列表状态不是问题。
  • 如果删除插入器要修改(以添加反向链接)但尚未修改的节点

    我希望检查 …

c++ concurrency linked-list atomic lock-free

3
推荐指数
1
解决办法
286
查看次数