C++静态类成员引用 self

发布于 2024-10-25 20:22:10 字数 718 浏览 1 评论 0原文

我很好奇这是否是我可以做的事情:

using namespace tthread;
class E_thread {
    static std::list<E_thread*> all_threads;
    thread th;
    E_messageQueue queue;
public:
    E_thread(void (*threadFunction)(void *), void * threadFuncArg) {
        all_threads.push_back(this);
        th = thread(threadFunction,threadFuncArg);
    }
    ~E_thread() {
        queue.push_terminate_thread_message();
        th.join();
        all_threads.remove(this);
    }
};

我的目的是让任何线程都可以轻松地生成新线程或向另一个线程发送消息,并且线程列表也能够自行清理。据我了解,我可以将 all_threads 替换为全局 std::list ,如果我愿意的话,它可以达到相同的目的,但不是这是一种获得这种“全球性”的更干净的方法吗?

对此有点不安的是,我没有强制我的新线程有一个消息读取循环,以便能够处理终止消息。

I'm curious as to whether this is something that I can do:

using namespace tthread;
class E_thread {
    static std::list<E_thread*> all_threads;
    thread th;
    E_messageQueue queue;
public:
    E_thread(void (*threadFunction)(void *), void * threadFuncArg) {
        all_threads.push_back(this);
        th = thread(threadFunction,threadFuncArg);
    }
    ~E_thread() {
        queue.push_terminate_thread_message();
        th.join();
        all_threads.remove(this);
    }
};

My intention is to make it easy for any thread to spawn new threads or to send messages to another thread, and the thread list also is capable of cleaning up after itself. As far as I understand it I could replace all_threads with a global std::list<E_thread*> which serves the same purpose if I wanted to, but isn't this a cleaner method of getting that sort of "globalness"?

What's a little uneasy about this is that I haven't forced my new threads to have a message reading loop, to be able to handle the terminate message.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

伪心 2024-11-01 20:22:10

大多数情况下,这很好。您需要使用某种互斥体来保护对 all_threads 的访问(读取或修改两者)。另外,如果您在程序运行过程中经常销毁线程,那么最好使用 ::std::set

另外,我对是否拥有任何类型的全局变量有些疑问。我认为如果您有一个“线程管理器”对象,您在创建线程时传递了一个“线程管理器”对象,或者可能有一个线程工厂来跟踪它创建的所有线程,那么它会更干净。

全局变量使程序更难测试,并使它们更脆弱并且以后修改的能力更差。

This is fine, mostly. You need to protect access (reading or modifying both) to all_threads with a mutex of some sort. Also, you would be better served to use a ::std::set if you destroy threads often during the course of your program.

Also, I sort of question having global variables of any kind. I think it would be cleaner if you had a 'thread manager' object that you passed in what you created a thread, or maybe a thread factory that kept track of all the threads it created.

Global variables make programs much harder to test, and make them more brittle and less capable of being modified later.

初相遇 2024-11-01 20:22:10
  • 如果多个线程尝试加入同一个线程,某些操作系统上的未定义行为

  • all_threads 需要受到保护通过 push_backremove 的互斥体以及可能尝试迭代它的任何其他读取器

    • 如果迭代 all_threads 的其他线程可能尝试对 th 执行某些操作,您可能需要在互斥锁保护块中包含对 th 的修改在其分配之前或期间
  • this有串行化线程破坏的倾向,因为push_terminate_thread_message被发送到单个线程,然后join完成。通常最好先发送所有终止消息,然后再执行所有连接

  • 对我来说,线程如何了解队列并不明显,尽管 threadFuncArg 在某些有限的情况下可能会被滥用

Omnifarious 关于适当线程池的建议更具吸引力。

  • undefined behaviour on some OS if multiple threads attempt to join the same thread

  • all_threads needs to be protected by a mutex for the push_back, remove, and any other reader that may try to iterate over it

    • you may want to include modifications to th in the mutex-protected block if other threads iterating all_threads may try to do something to th before or during its assignment
  • this has a tendency to serialise thread destruction, as push_terminate_thread_message is sent to a single thread, then a join is done. It's generally better to send all the termination messages then do all the joins.

  • it's not obvious to me how the threads are supposed to know about the queues, though the threadFuncArg might be abused for this in some limited circumstances

Omnifarious's suggestion of a proper thread pool is much more appealing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文