Multithreading with inheritance (C ++)
I am trying to call the Run function on a new thread. Right now I have this code using openMP that doesn't actually start "Run" on a new thread. NOTE. I am not asking for help with OpenMP. This code was just a quick fix. I would rather use the CreateThread () method for this.
vector<ICommand*>* commands;
string strInput;
// For each command...
for(vector<ICommand*>::iterator i = commands->begin(); i != commands->end(); ++i)
{
// ...if the current command we're examining is valid...
if((*i)->ContainsCommand(strInput))
{
// ...run it in a new thread and don't let ZChatInput handle it normally...
#pragma omp sections nowait
{
#pragma omp section
(*i)->Run(strInput);
#pragma omp section
bRet = false;
}
// ...and don't check any more commands.
break;
}
}
So how to do this using only standard and STL? Of course I'm looking for a way that works :)
a source to share
So I figured it out after double checking the MSDN documentation. Here's how I did it, in case any of you are interested:
static vector<ICommand*>* commands;
// This is what we pass to CommandOnThread.
struct CommandParameter
{
string strInput;
ICommand* command;
};
int CommandOnThread(CommandParameter* cp)
{
cp->command->Run(cp->strInput);
delete cp;
return 0;
}
void foo()
{
string strInput;
...
// For each command...
for(vector<ICommand*>::iterator i = commands->begin(); i != commands->end(); ++i)
{
// ...if the current command we're examining is valid...
if((*i)->ContainsCommand(strInput))
{
// Put the CP on the stack.
CommandParameter* temp = new CommandParameter;
if(temp == NULL)
{
Print("Out of memory!");
bRet = false;
break;
}
// ...set up the parameters to createthread...
temp->strInput = strInput;
temp->command = *i;
// ...run it in a new thread...
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)CommandOnThread, temp, NULL, NULL);
// ...and don't check any more commands.
bRet = false;
break;
}
}
}
a source to share
You can try something like this:
vector<ICommand*>* commands;
string strInput;
void CommandOnThread(void* command)
{
(ICommand*)command->Run();
}
// For each command...
for(vector<ICommand*>::iterator i = commands->begin(); i != commands->end(); ++i)
{
// ...if the current command we're examining is valid...
if((*i)->ContainsCommand(strInput))
{
//Attach the input to the command
(*i)->AttachInput(strInput);
_beginthread(CommandOnThread, 0, *i);
break;
}
}
To do this, you need to slightly modify the command line interface to pass the command input in two steps: first, store the input in a command object, and then call Run () with no arguments. You can replace _beginthread with CreateThread if you like that they are very similar.
Just to clarify, you cannot use an instance method as a function parameter for _beginthread (or CreateThread). The solution above is to pass an object (command) to a function and then call its instance method (Run). However, in this case, you cannot pass additional arguments to the stream function, and therefore you cannot pass arguments to the instance method. The simplest solution for this is to somehow attach the argument to the instance before passing it to the stream function.
Hope this helps. Of course, this solution is not possible unless you can change the interface and implementation of the Command class.
a source to share
Are you sure you want to create a thread for each command? Creating a theme is expensive. If you absolutely need this part to be asynchronous - create a synchronized queue, specify the number of threads (as long as your scalability is here) will block them in the queue, and then put a message (pointer?) Into the queue in your loop.
Responding to your comment:
// setup
sync_queue wq; // that would be protected by mutex and a conditional var or two
for (i = 0; i <parallel_factor; ++ i) start_thread (th_func, wq);
...
// your loop body:
...
if (valid_input) q.put (item);
...
// thread function
void th_func (sync_queue & q)
{
work_item * pwi;
while ((pwi = q.get ())) do_it (pwi);
}
Has the meaning?
a source to share