Good thread-safe queue approach?

I am looking for a way to optimize the following code, for an open source project that I am developing, or to make it more efficient by moving the hard work to another thread.

void ProfilerCommunication::AddVisitPoint(ULONG uniqueId) { CScopedLock<CMutex> lock(m_mutexResults); m_pVisitPoints->points[m_pVisitPoints->count].UniqueId = uniqueId; if (++m_pVisitPoints->count == VP_BUFFER_SIZE) { SendVisitPoints(); m_pVisitPoints->count=0; } } 

The above code is used by the OpenCover profiler (an open source coverage tool for .NET written in C ++) when every visit point is called. A mutex is used to protect some shared memory (a 64K block shared between several 32/64 bit processes and C ++ / C #) when it completely signals the host process. Obviously, this is pretty hard for every breakpoint, and I would like to make the kick easier.

I am thinking about using a queue that is pushed by the above method, and a thread that issues data and fills the shared memory.

Q. Is there a thread-safe queue in C ++ (Windows STL) that I can use, or a queue lock, because I do not want to replace one problem with another? Do people think my approach is reasonable?


EDIT 1: I just found concurrent_queue.h in the include folder - could this be my answer ...?

+4
source share
4 answers

Ok, I will add my own answer - concurrent_queue works very well

using the details described in this MSDN article. I implemented a parallel queue (both tasks and my first C ++ lambda expression :)). I didn’t think for a long time that this is a thorn.

 inline void AddVisitPoint(ULONG uniqueId) { m_queue.push(uniqueId); } ... // somewhere else in code m_tasks.run([this] { ULONG id; while(true) { while (!m_queue.try_pop(id)) Concurrency::Context::Yield(); if (id==0) break; // 0 is an unused number so is used to close the thread/task CScopedLock<CMutex> lock(m_mutexResults); m_pVisitPoints->points[m_pVisitPoints->count].UniqueId = id; if (++m_pVisitPoints->count == VP_BUFFER_SIZE) { SendVisitPoints(); m_pVisitPoints->count=0; } } }); 

Results:

  • Application without tools = 9.3
  • Application with the old toolkit handler = 38.6
  • Application with a new tool handler = 16.2
+1
source

It is mentioned here that not all container operations are thread safe on Windows. Only a limited number of methods . And I don’t believe that C ++ standards mention stream containers. Maybe I'm wrong, but I checked the standards, nothing came

0
source

Is it possible to offload client communication into a separate thread? Checkpoints can then use the local thread store to record their hits and only to communicate with the local stream to pass the link when populated. The communication flow can then spend its time transferring data to the actual collector, since it is no longer on a hot trip.

0
source

You can use a lock-free queue. Herb Sutter has several articles here .

0
source

Source: https://habr.com/ru/post/1369649/


All Articles