views:

725

answers:

8

In my application I have two threads

  1. a "main thread" which is busy most of the time
  2. an "additional thread" which sends out some HTTP request and which blocks until it gets a response.

However, the HTTP response can only be handled by the main thread, since it relies on it's thread-local-storage and on non-threadsafe functions.

I'm looking for a way to tell the main thread when a HTTP request was responsed and what the response is. The main thread should be interrupted by the additional thread and process the HTTP response as soon as possible, and afterwards continue working from the point where it was interrupted before.

  • One way I can think about is that the additional thread suspends the main thread using SuspendThread, copies the TLS from the main thread using some inline assembler, executes the response-processing function itself and resumes the main thread afterwards.

  • Another way in my thoughts is, setting a break point onto some specific address in the second threads callback routine, so that the main thread gets notified when the second threads instruction pointer steps on that break point - and therefore - has received the HTTP response.

However, both methods don't seem to be nicely at all, they hurt even if just thinking about them, and they don't look really reliable.

What can I use to interrupt my main thread, saying it that it should be polite and process the HTTP response before doing anything else? Answers without dependencies on libraries are appreciated, but I would also take some dependency, if it provides some nice solution.

Following question (regarding the QueueUserAPC solution) was answered and explained that there is no safe method to have a push-behaviour in my case.

A: 

It looks like the answer should be discoverable from Microsoft's MSDN. Especially from this section on 'Synchronizing Execution of Multiple Threads'

Jonathan Leffler
I don't need synchronization in my case. What I want is to interrupt the main thread's current execution to process something else and to let it resume its old work afterwards.
Etan
That's what 'synchronization' means - letting threads communicate with each other about what they are up to so that things happen in an orderly manner.
Jonathan Leffler
Ah kay, thanks. I understood under *synchronization* things like access to critical memory sections or things where you have to wait for another thread to reach a certain spot.
Etan
+1  A: 

I might not understand the question, but CreateSemaphore and WaitForSingleObject should work. If one thread is waiting for the semaphore, it will resume when the other thread signals it.

Update based on the comment: The main thread can call WaitForSingleObject with a wait time of zero. In that situation, it will resume immediately if the semaphore is not signaled. The main thread could then check it on a periodic basis.

Mark Wilkins
The main thread shouldn't wait for the HTTP response, it should just be **interrupted** as soon as an HTTP response arrives. At *any* time! If there was no response, it should continue it's normal execution.
Etan
I think I understand now. I also don't think there is any way to do that ... at least in a clean fashion. I suppose you could force an exception in the thread to make it stop what it is doing. Resuming would be a problem. It sounds to me like there is an architectural problem if things must work this way.
Mark Wilkins
I think what MarkW told is right. WaitForSingleObject can sort your problem if i am understanding ur question properly.
Abhi
Forcing the exception would be my second thought: setting a breakpoint in the second threads callback function such that it breaks as soon as it gets there.
Etan
A: 

If your main thread is GUI thread why not send a Windows message to it? That what we all do to interact with win32 GUI from worker threads.

Oleg Zhylin
The main thread is not a GUI thread. However, the concept of a message queue sounds nice! Sadly, it is also based on a "pull"-mechanism from the main thread instead of a "push"-mechanism from the additional thread.
Etan
Yes, but one that works pretty well. What is your main thread doing anyways?
sdg
If your thread isn't a GUI thread you can use PostThreadMessage to achieve the same result. But of course you are free to use any message queuing mechanism that suits your purposes.
Oleg Zhylin
A: 

One way to do this that is determinate is to periodically check if a HTTP response has been received.

It's better for you to say what you're trying to accomplish.

cheez
+2  A: 

What you are describing is what QueueUserAPC does. But The notion of using it for this sort of synchronization makes me a bit uncomfortable. If you don't know that the main thread is in a safe place to interrupt it, then you probably shouldn't interrupt it.

I suspect you would be better off giving the main thread's work to another thread so that it can sit and wait for you to send it notifications to handle work that only it can handle.

PostMessage or PostThreadMessage usually works really well for handing off bits of work to your main thread. Posted messages are handled before user input messages, but not until the thread is ready for them.

John Knoeller
I tried it with `QueueUserAPC`. However, it doesn't seem to work as my other [question](http://stackoverflow.com/questions/1980145/callback-specified-in-queueuserapc-does-not-get-called) states.
Etan
The Main thread can be borrowed to run the APC only when it's in the kernel, this usually happens when you are doing IO.
John Knoeller
+2  A: 

This may be one of those times where one works themselves into a very specific idea without reconsidering the bigger picture. There is no singular mechanism by which a single thread can stop executing in its current context, go do something else, and resume execution at the exact line from which it broke away. If it were possible, it would defeat the purpose of having threads in the first place. As you already mentioned, without stepping back and reconsidering the overall architecture, the most elegant of your options seems to be using another thread to wait for an HTTP response, have it suspend the main thread in a safe spot, process the response on its own, then resume the main thread. In this scenario you might rethink whether thread-local storage still makes sense or if something a little higher in scope would be more suitable, as you could potentially waste a lot of cycles copying it every time you interrupt the main thread.

Brian Cline
A: 

In this situation I would do a couple of things. First and foremost I would re-structure the work that the main thread is doing to be broken into as small of pieces as possible. That gives you a series of safe places to break execution at. Then you want to create a work queue, probably using the microsoft slist. The slist will give you the ability to have one thread adding while another reads without the need for locking.

Once you have that in place you can essentially make your main thread run in a loop over each piece of work, checking periodically to see if there are requests to handle in the queue. Long-term what is nice about an architecture like that is that you could fairly easily eliminate the thread localized storage and parallelize the main thread by converting the slist to a work queue (probably still using the slist), and making the small pieces of work and the responses into work objects which can be dynamically distributed across any available threads.

Chris
A: 

The mainthread always waits for a message. Process the message and again waits for the next message.

ashokgk