Thanks for the reply Jens. Here is what I think you are suggesting: service SlowRunner { i32 createOperation(), void slowOperation(1: i32 instanceID), } service SlowStopper { void stopEverything(1: i32 instanceID), }
So with my interface, a client would call SlowClient::slowOperation() in the "main thread", and SlowClient::stopEverything() on the "stop thread", both on the same SlowClient instance. With this new interface, you are suggesting that the "main thread" call SlowRunnerClient::createOperation(), then call SlowRunnerClient::slowOperation(). If I need to stop things, then the "stop thread" will need to get the value of the instanceID, then call SlowStopper::stopEverything() on a SlowStopper instance. This solves the problem as specified in my post, at the cost of extra connections. In reality, it doesn't solve my problem. My desired interface is actually more like this: service GenericService { string doSomething(1: string cmd), } One of the commands would be "doSlowOperation" and another would be "stopEverything". There would also be per connection state, to service hypothetical commands like "addToQueue" and "removeFromQueue". So even with this, it would be possible to add a bunch of instance ids to the service, and force the client and server implementations to create lots of connections and session tracking. However, that seems like it is adding one session tracking system (instanceIDs) on top of a different session tracking system (connections). I'm fine if Thrift doesn't currently support such a use case, and I will gladly develop and contribute the support. I have several uses for this threading support in my company. I just want to make sure that I'm not duplicating the work that already exists in some corner of Thrift I haven't become familiar with yet. From: "Jens Geyer" <jensge...@hotmail.com> To: <dev@thrift.apache.org>, Date: 12/04/2012 04:00 PM Subject: Re: How should I implement multi-threaded clients and multi-threaded connections in C++? 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: dev@thrift.apache.org 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.