How to execute a method in another thread?

11,816

Solution 1

There are several ways to achieve this, depending upon the complexity you want to accept. Complexity of the code is directly proportional to the flexibility desired. Here's a simple one (and quite well used):

Define a classes corresponding to each functionality your server exposes. Each of these classes implements a function called execute and take a basic structure called input args and output args.

Inside the service register these methods classes at the time of initialization. Once a request comes to the thread, it will have only two args, Input and Ouput, Which are the base classes for more specialized arguments, required by different method classes.

Then you write you service class as mere delegation which takes the incoming request and passes on to the respective method class based on ID or the name of the method (used during initial registration).

I hope it make sense, a very good example of this approach is in the XmlRpc++ (a c++ implementation of XmlRpc, you can get the source code from sourceforge).

To recap:

struct Input {
  virtual ~Input () = 0;
};

struct Ouput {
  virtual ~Output () = 0;
};

struct MethodInterface {
   virtual int32_t execute (Input* __input, Output* __output)  = 0;
};

// Write specialized method classes and taking specialized input, output classes
class MyService {


  void registerMethod (std::string  __method_name, MethodInterface* __method);
  //external i/f
  int32_t execute (std::string __method, Input* __input, Output* __output);
};

You will still be using the queue mechanism, but you won't need any wrappers.

Solution 2

My standard reference for this problem is here.

Implementing a Thread-Safe Queue using Condition Variables

As @John noted, this uses Boost.Thread.

I'd be careful about the synchronous case you described here. It's easy to get perf problems if the producer (the sending thread) waits for a result from the consumer (the service thread). What happens if you get 1000 async calls, filling up the queue with a backlog, followed by a sync call from each of your producer threads? Your system will 'play dead' until the queue backlog clears, freeing up those sync callers. Try to decouple them using async only, if you can.

Solution 3

IMHO, If you want to decouple method execution and thread context, you should use Active Object Pattern (AOP)

However, you need to use ACE Framework, which supports many OSes, e.g. Windows, Linux, VxWorks

You can find detailed information here

Also, AOP is a combination of Command, Proxy and Observer Patterns, if you know the details of them, you may implement your own AOP. Hope it helps

Share:
11,816
amso
Author by

amso

I am an engineer of electricity. My work currently is focused on embedded systems running linux. Most software that I write is coded in C and/or C++. I also have some practice in perl, which I use when nothing else can do the task. Cheers.

Updated on June 04, 2022

Comments

  • amso
    amso almost 2 years

    I'm looking for a solution for this problem in C or C++.
    edit: To clarify. This is on a linux system. Linux-specific solutions are absolutely fine. Cross-plaform is not a concern.

    I have a service that runs in its own thread. This service is a class with several methods, some of which need to run in the own service's thread rather than in the caller's thread.

    Currently I'm using wrapper methods that create a structure with input and output parameters, insert the structure on a queue and either return (if a "command" is asynchronous) or wait for its execution (if a "command" is synchronous).

    On the thread side, the service wakes, pops a structure from the queue, figures out what to execute and calls the appropriate method.

    This implementation works but adding new methods is quite cumbersome: define wrapper, structure with parameters, and handler. I was wondering if there is a more straightforward means of coding this kind of model: a class method that executes on the class's own thread, instead of in the caller's thread.

    edit - kind of conclusion:
    It seems that there's no de facto way to implement what I asked that doesn't involve extra coding effort.
    I'll stick with what I came up with, it ensures type safeness, minimizes locking, allows sync and async calls and the overhead it fairly modest.
    On the other hand it requires a bit of extra coding and the dispatch mechanism may become bloated as the number of methods increases. Registering the dispatch methods on construction, or having the wrappers do that work seem to solve the issue, remove a bit of overhead and also remove some code.

  • amso
    amso over 13 years
    Can you format the code so that it is perceivable as such as well as more readable? Thanks! Your solution looks somewhat like what I am doing now. I'd have to write a wrapper class per method/functionality and a method to invoke that functionality from the outside. Or did I misread the answer?
  • stefaanv
    stefaanv over 13 years
    boost::bind works to combine function with parameters, but you still need some (polymorphic?) dispatching because the compiler can't decide what the other thread must call.
  • amso
    amso over 13 years
    This needs a little less code than what I'm using now but loses the ability to pass arbitrary parameters or use sync/async calls.