相关疑难解决方法(0)

你将如何实现一个基本的事件循环?

如果你使用过gui工具包,你就知道有一个事件循环/主循环应该在一切完成后执行,这将使应用程序保持活跃并响应不同的事件.例如,对于Qt,您可以在main()中执行此操作:

int main() {
    QApplication app(argc, argv);
    // init code
    return app.exec();
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,app.exec()是应用程序的主循环.

实现这种循环的显而易见的方法是:

void exec() {
    while (1) {
        process_events(); // create a thread for each new event (possibly?)
    }
}
Run Code Online (Sandbox Code Playgroud)

但是这会将CPU限制在100%并且实际上是无用的.现在,我如何实现这样一个响应的事件循环,而不必完全占用CPU?

回答在Python和/或C++中受到赞赏.谢谢.

脚注:为了学习,我将实现自己的信号/插槽,我会用它们来生成自定义事件(例如go_forward_event(steps)).但是如果你知道如何手动使用系统事件,我也想知道这一点.

c++ python event-loop blocking

56
推荐指数
5
解决办法
3万
查看次数

使用互斥量作为信号量?

我需要两个线程以"tick tock"模式进行.当使用信号量实现时,这看起来很好:

Semaphore tick_sem(1);
Semaphore tock_sem(0);

void ticker( void )
{
   while( true )
   {
      P( tick_sem );
      do_tick();
      V( tock_sem );
   }
}

void tocker( void )
{
   while( true )
   {
      P( tock_sem );
      do_tock();
      V( tick_sem );
   }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用互斥锁(在技术上是一个二进制信号量)做同样的事情,它有一个奇怪的代码气味.

std::mutex tick_mutex;
std::mutex tock_mutex;
tock_mutex.lock();

void ticker( void )
{
   while( true )
   {
      tick_mutex.lock();
      do_tick();
      tock_mutex.unlock();
   }
}

void tocker( void )
{
   while( true )
   {
      tock_mutex.lock()
      do_tock();
      tick_mutex.unlock();
   }
}
Run Code Online (Sandbox Code Playgroud)

我认为气味是互斥不是为了将信息传达给另一个线程.(c ++ …

c++ concurrency mutex semaphore c++11

13
推荐指数
2
解决办法
5230
查看次数

为什么条件变量需要锁定(因此也需要互斥锁)

条件变量是c ++ 11的一个方面我还在苦苦挣扎.从我收集到的条件变量非常类似于信号量.

但话说回来,信号量不需要锁定才能运行.条件变量可以.而锁又需要一个互斥锁.因此,为了使用信号量的相当简单的功能,我们现在不仅需要管理条件变量.但也是一个互斥锁和一个锁.

那么为什么条件变量需要这个呢?通过添加此要求可以提供哪些附加功能?

c++ concurrency flags multithreading c++11

13
推荐指数
2
解决办法
2900
查看次数

实现类似于Qt的高性能互斥锁

我有一个多线程科学应用程序,其中几个计算线程(每个核心一个)必须将其结果存储在公共缓冲区中.这需要互斥机制.

工作线程只花费一小部分时间写入缓冲区,因此互斥锁在大多数时间都处于解锁状态,并且锁定很有可能立即成功而无需等待另一个线程解锁.

目前,我已经使用Qt的QMutex执行任务,并且运行良好:互斥锁的开销可以忽略不计.

但是,我必须将它移植到c ++ 11/STL.使用std :: mutex时,性能下降了66%,并且线程花费大部分时间来锁定互斥锁.

在另一个问题之后,我认为Qt使用基于简单原子标志的快速锁定机制,针对互斥锁尚未锁定的情况进行了优化.并发锁定发生时会回退到系统互斥锁.

我想在STL中实现这一点.是否有一种基于std :: atomic和std :: mutex的简单方法?我已经深入研究了Qt的代码,但对于我的使用似乎过于复杂(我不需要锁定超时,pimpl,小占用空间等......).

编辑:我试过一个螺旋锁,但这不能很好地工作,因为:

定期(每隔几秒),另一个线程锁定互斥锁并刷新缓冲区.这需要一些时间,因此此时所有工作线程都会被阻止.自旋锁使调度繁忙,导致刷新比使用适当的互斥锁慢10-100倍.这是不可接受的

编辑:我试过这个,但它不起作用(锁定所有线程)

class Mutex
{
public:
    Mutex() : lockCounter(0) { }

    void lock()
    {
        if(lockCounter.fetch_add(1, std::memory_order_acquire)>0)
        {
            std::unique_lock<std::mutex> lock(internalMutex);
            cv.wait(lock);
        }
    }

    void unlock();
    {
        if(lockCounter.fetch_sub(1, std::memory_order_release)>1)
        {
            cv.notify_one();
        }
    }


private:
    std::atomic<int> lockCounter;
    std::mutex internalMutex;
    std::condition_variable cv;
};
Run Code Online (Sandbox Code Playgroud)

谢谢!

编辑:最终解决方案

MikeMB的快速互斥体工作得非常好.

作为最终的解决方案,我做了:

  • 使用带有try_lock的简单螺旋锁
  • 当一个线程无法try_lock而不是等待时,它们会填充一个队列(不与其他线程共享)并继续
  • 当线程获得锁定时,它会使用当前结果更新缓冲区,但也会将结果存储在队列中(它会处理其队列)
  • 缓冲区刷新效率更高:阻塞部分只交换两个指针.

c++ qt mutex stl c++11

12
推荐指数
1
解决办法
2730
查看次数

std :: mutex with RAII但在后台线程中完成并释放

我有一个偶尔从GigE相机获得一个帧的功能,并希望它快速返回.标准程序是这样的:

// ...
camera.StartCapture();
Image img=camera.GetNextFrame();
camera.StopCapture(); // <--  takes a few secs
return img;
Run Code Online (Sandbox Code Playgroud)

返回数据准备就绪GetNextFrame()并且StopCapture()非常慢; 因此,我想img尽快返回,并产生一个后台线程StopCapture().但是,在(不太可能)再次启动采集的情况下,我希望通过互斥锁保护访问.有些地方可以抛出异常,所以我决定使用RAII风格的锁,它将在范围退出时释放.同时,我需要将锁转移到后台线程.像这样的东西(伪代码):

class CamIface{
   std::mutex mutex;
   CameraHw camera;
public:
   Image acquire(){
      std::unique_lock<std::mutex> lock(mutex); // waits for cleanup after the previous call to finish
      camera.StartCapture();
      Image img=camera.GetNextFrame();
      std::thread bg([&]{
         camera.StopCapture(); // takes a long time
         lock.release(); // release the lock here, somehow
       });
       bg.detach();
       return img;
       // do not destroy&release lock here, do it in the bg thread …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading mutex c++11

11
推荐指数
2
解决办法
915
查看次数

等待回调完成的最佳方式

在下面的代码中,main()函数调用request()函数,该函数调用th_request_async()函数,其中mm_th_done_cb().

只有在执行mm_th_done_cb()之后,才能在main中继续进行最佳和最有效的方法.

DUMMY CODE

int mm_th_done_cb(int error_code, th_result_s* th_result, void* user_data)
{
    return 0;
}

void request()
{
    th_request_s MyItemInfo;
    strncpy(MyItemInfo.origin_path, szUrl, 1024+1);
    MyItemInfo.orientation = 0;
    MyItemInfo.func = mm_th_done_cb;
    MyItemInfo.used_cache = 1;
    th_request_async(MyItemInfo);
}


int main()
{
    request();
    // Here I need to do something only after mm_th_done_cb() has been excuted.
}
Run Code Online (Sandbox Code Playgroud)

c++ multithreading synchronization

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

同步非常快的线程

在下面的例子中(理想化的"游戏")有两个线程.更新数据并将RenderThread其"呈现"到屏幕的主线程.我需要的是那两个要同步的东西.我没有能力运行几次更新迭代而不为它们中的每一个运行渲染.

我使用a condition_variable来同步这两个,所以理想情况下,更快的线程将花费一些时间等待更慢.但是,如果其中一个线程在很短的时间内完成迭代,则条件变量似乎不起作用.它似乎很快就会重新获取互斥锁的锁定,然后wait另一个线程才能获取它.即使notify_one被称为

#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
#include <functional>
#include <mutex>
#include <condition_variable>

using namespace std;

bool isMultiThreaded = true;

struct RenderThread
{
    RenderThread()
    {
        end = false;
        drawing = false;
        readyToDraw = false;
    }

    void Run()
    {
        while (!end)
        {
            DoJob();
        }
    }

    void DoJob()
    {
        unique_lock<mutex> lk(renderReadyMutex);
        renderReady.wait(lk, [this](){ return readyToDraw; });
        drawing = true;

        // RENDER DATA
        this_thread::sleep_for(chrono::milliseconds(15)); // simulated render time
        cout << "frame " …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading synchronization

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

如何在c ++中使用boost实现与信号量类似的东西?

我注意到提升似乎不支持信号量.获得类似效果的最简单方法是什么?

c++ multithreading boost boost-thread boost-interprocess

8
推荐指数
2
解决办法
2万
查看次数

C++ 11非阻塞生产者/消费者

我有一个C++ 11应用程序,它具有生成数据的高优先级线程,以及一个消耗它的低优先级线程(在我的情况下,将其写入磁盘).我想确保高优先级的生产者线程永远不会被阻止,即它只使用无锁算法.

使用无锁队列,我可以从生产者线程将数据推送到队列,并从消费者线程中轮询它,从而实现上述目标.我想修改我的程序,以便消费者线程在非活动状态而不是轮询时阻塞.

似乎C++ 11条件变量可能对阻塞使用者线程很有用.有人能告诉我一个如何使用它的例子,同时避免消费者睡觉时数据仍在队列中吗?更具体地说,我想确保在生产者将最后一个项目推入队列后,消费者总是在某个有限的时间内被唤醒.生产者保持非阻塞也很重要.

multithreading producer-consumer c++11

8
推荐指数
1
解决办法
4282
查看次数

C++ 11中的非阻塞信号量?

本网站上的一些问题涉及C++ 11中引入的多线程支持中缺少信号量对象.许多人建议使用互斥锁或条件变量或两者的组合来实现信号量.

但是,这些方法都不允许增加和减少信号量,同时保证调用线程不被阻塞,因为通常必须在读取信号量值之前获取锁定.例如,POSIX信号量具有函数,sem_post()并且sem_trywait()两者都是非阻塞的.

是否可以仅使用C++ 11多线程支持实现非阻塞信号量?或者我是否一定要为此使用依赖于操作系统的库?如果是这样,为什么C++ 11修订版不包含信号量对象?

一个类似的问题在3年内没有得到回答.(注意:我相信我要问的问题要广泛得多,除了生产者/消费者之外,还有一些非阻塞信号量对象的其他用途.如果有人认为我的问题是重复的,请告诉我如何我可以回想一下旧问题,因为这仍然是一个悬而未决的问题.)

c++ multithreading c++11

7
推荐指数
1
解决办法
3049
查看次数