开发者

Need Design Advise C++: Want to implement a threaded queue for other threads to pass data

I've not done any thread programming before, so i wanted to ask you guys for some design suggestions and also about stuffs i should be aware of about thread programming.

Environment: MFC/C++, VS2005

Problem: I have a vendor library running threads to poll data and receive reports from devices. Number of threads can reach 100+ depending on the number of devices. Everytime a thread receives data, it needs to call a sequence of functions(from a vendor SDK, not thread safe) to update values on the GUI.

Solution??: My friend suggested me to use a thread with a built in queue to synchronize updating data to the GUI. Whenever the other threads receives data, it'll add an entry to the queue in this thread. This thread will then call the sequence of functions until the queue is empty and wait for new entries.

I did some reading on _beginthreadex(), _endthreadex(), boost::thread, semaphore and mutex concept. How do you think i should implement this? What pitfalls i should be awar开发者_如何学JAVAe of? Please advise.


I've posted some code in a previous answer that should be usable. Though some of the comments there mention I/O Completion ports, they don't really apply to your case. Microsoft's attempt at roughly the same is the SList, but (IMO) this has some pretty serious problems, starting with (IMO) a fatally flawed design (or, if not fatally flawed, at least totally unsuited to your purposes -- and most others, anyway) and then adding some annoyances. The fatal flaw is that it's really designed to act as a stack instead of a queue1. This is almost certainly dead wrong for your application. For annoyances, QueryDepthSlist returns the depth modulo 65536, so if, for example, your depth is 65536, it'll tell you the depth is zero. Second, it only works correctly if you take special steps to align data you put into the list. Both of these can be worked around (in fact, I hesitate to mention the problem with QueryDepthSlist, since you should probably never call it anyway) but the alignment requirement really is quite annoying.

As far as how to create the other threads, since you're apparently using MFC otherwise, you pretty much need to use MFC to create your threads as well -- it does a few extra bits of work when you create a thread. If you're going to use MFC in a particular thread, you must let MFC create that thread. You'll probably want to use your original thread to run the GUI, and create the other threads with AfxBeginThread.

1 Well, okay, "fatal" is overstating the situation a tiny bit, but not much. Basically, you have to use InterlockedFlushSlist, then traverse backward through the list of items to process them in order. Since it's a singly linked list, you can't traverse it in reverse as is. You can either do the forward traverse recursively, and do the processing on the return leg, or you can reverse the list as you traverse it. While I'm sure either can be made to work, you're basically fighting against the design either way.


You might want to check out intel TBB,

http://www.threadingbuildingblocks.org/files/documentation/a00129.html seems to possibly do exactly what you want.


You've got multiple producers and one consumer? You'll get very high performance with a minimum of effort with the Win32 SList API. Use the PUSH and FLUSH operations in the producer and consumer, respectively.

Since you're sending messages to a GUI thread, you could also use PostMessage. But if you're passing pointers through the message queue you have to worry about things like shatter attacks. The private SList is much easier to make robust. You can also use PostMessage to trigger the GUI thread to read from the SList, that's perfectly safe.


look at www.boost.org

the code will be portable across multiple platforms and you can quickly start concentrating on service logic instead of running behind thread wrapper classes.

once you get the basics working and understand what must be possible implementation logic.. then you are better placed to write your own if you think boost is complex, and you might solve the problem on your own.

but by using of boost specifically in your case asio, i think you will be better placed to plan your design and think different aspects of threading model.


Unless the "sequence of calls" is time consuming itself, don't bother to create more threads. Your GUI already has a dedicated thread associated with it, AND a message queue.

Your GUI has a window associated with it - just use SendMessage() from the worker threads to send messages to the window on the main thread for processing and display. SendMessage will block until the GUI thread processes the message, so data pointers passed will still be in scope.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜