Hi Ben,
just as an idea what I would be trying:
1. extract the implementation of slowOperation() and stopEverything() from
the service into a dedicated class and make that one threadsafe.
2. if you need only one instance of this implementation class, make it a
singleton or even a static class. if you want to have more than one in
parallel, you need a (threadsafe) container for them. In the latter case go
to step 3, otherwise continue with 4
3. Give each implemenation instance an ID and return this ID through an
additional createOperation() method to the client. This ID must be passed in
when slowOperation() or stopEverything() are called to locate the correct
implementation instance. Since createOperation() creates a new
implementation instance, don't forget that this instance must be deleted
afterwards.
4. modify the service methods accordingly, they now just call the
implementation and create/free the instances.
5. the client is now free to open another connection to the server to call
stopEverything(). This call sets some kind of abort flag at the
implementation instance identified through the ID. The flag ist tested
repeatedly by slowOperation().
Could that work for you?
JensG
-----Ursprüngliche Nachricht-----
From: Ben Craig
Sent: Tuesday, December 4, 2012 10:20 PM
To: [email protected]
Subject: How should I implement multi-threaded clients and multi-threaded
connections in C++?
Suppose I have a .thrift spec similar to the following:
service Slow
{
void slowOperation(),
void stopEverything(),
}
When my application launches, my code will establish a connection with the
server, and hold on to that connection for the lifetime of the app. When
a user launches a dialog box from this application, I want to call
slowOperation(). If the user hits "Cancel" on the dialog, I want to run
stopEverything(). stopEverything should cause slowOperation to stop what
it is doing and complete.
I have several problems with this setup right now. First, the
codegenerated SlowClient class isn't thread safe. If multiple threads try
to access it at the same time, bad things will happen. Second, as far as
I can tell, the existing servers only process messages on one thread per
connection. That means that even if I managed to send a stopEverything()
call while a slowOperation() was in progress, the server wouldn't process
that message until the slowOperation was complete.
Does the C++ library / compiler currently have anything that can satisfy
this requirement? I'm looking at some of the COB / Continuation OBject
stuff, but it doesn't look like it makes the SlowClient thread safe (but
maybe the AsyncChannel is supposed to be safe instead?). It also looks
like there isn't an easy way to get this behavior for any given transport.
I'm fine adding support for this kind of use case, but I want to make sure
that nothing already exists that I've overlooked before I go down that
path.