[英]Using functor in pthread_create
What this code do: 该代码的作用:
Several commands executed to completion(if(current seconds == some seconds) stop). 几个执行完成的命令(如果(当前秒==几秒)停止)。 CommandProcessor(functor) run this commands.
CommandProcessor(functor)运行此命令。 Pointer of this class I try to throw to pthread_create.
我尝试将此类的指针扔给pthread_create。
The question: 问题:
It is possible to use class object as callable? 可以将类对象用作可调用对象吗?
command.h 命令
#ifndef COMMAND_H
#define COMMAND_H
#include <iostream>
#include "commandprocessor.h"
class CommandProcessor;
using namespace std;
class Command
{
static CommandProcessor *commandProcessor;
time_t stopSeconds;
public:
Command(int _stopSeconds);
static void setProcessor(CommandProcessor *_commandProcessor);
void execute();
};
#endif // COMMAND_H
command.cpp command.cpp
#include "command.h"
CommandProcessor* Command::commandProcessor = NULL;
Command::Command(int _stopSeconds)
{
stopSeconds = _stopSeconds;
}
void Command::setProcessor(CommandProcessor *_commandProcessor)
{
commandProcessor = _commandProcessor;
}
void Command::execute()
{
time_t seconds;
time_t now = time(NULL);
seconds = localtime(&now)->tm_sec;
cout << seconds << endl;
if(seconds != stopSeconds)
commandProcessor->addCommand(this);
}
commandprocessor.h 命令处理器
#ifndef COMMANDPROCESSOR_H
#define COMMANDPROCESSOR_H
#include <list>
#include "command.h"
using namespace std;
class Command;
class CommandProcessor
{
list< Command* > commandsList;
public:
void addCommand(Command *_command);
void operator()();
};
#endif // COMMANDPROCESSOR_H
commandprocessor.cpp commandprocessor.cpp
#include "commandprocessor.h"
void CommandProcessor::addCommand(Command *_command)
{
commandsList.push_back(_command);
}
void CommandProcessor::operator()()
{
while(commandsList.size() > 0)
{
Command *command = commandsList.front();
commandsList.pop_front();
command->execute();
}
}
main.cpp main.cpp
#include <iostream>
#include <pthread.h>
#include "commandprocessor.h"
#define MAX_THREADS 2
using namespace std;
int main(int argc, char **args)
{
CommandProcessor *processor = new CommandProcessor();
Command::setProcessor(processor);
processor->addCommand(new Command(53));
processor->addCommand(new Command(24));
processor->addCommand(new Command(15));
pthread_t threads[MAX_THREADS];
for(int i=0; i < MAX_THREADS; i++)
{
pthread_create(&threads[i], NULL, processor(), NULL); // error: 'processor' cannot be used as a function
}
return 0;
}
DISCLAIMER : this is the kind of thing that you really shouldn't be doing in C++, as it includes messing around with void*
. 免责声明:这是您实际上不应该在C ++中做的事情,因为它包括弄乱
void*
。 It needs to be used here because of the interaction with the C API. 由于与C API的交互,因此需要在此处使用它。 If you can, use std::thread from C++11 or boost::thread if you're using an older compiler.
如果可以,请使用C ++ 11中的std :: thread ;如果使用的是较旧的编译器,请使用boost :: thread 。
To answer your question : yes, it is perfectly fine to make a class object as a callable (as a "function") once you implement operator()
for it. 要回答你的问题:是的,一旦为它实现了
operator()
,就可以将一个类对象作为可调用的对象(作为“函数”)。 You already did that, but the problem is the extra code needed to implement the interface between C++ and the C API for Pthreads. 您已经做到了,但是问题是实现C ++和Pthreads的C API之间的接口所需的额外代码。
The main reason why you're getting the " processor
cannot be used as a function" error here is because processor
is a CommandProcessor*
and, as such, needs a dereference. 出现“无法将
processor
用作功能”错误的主要原因是processor
是CommandProcessor*
,因此需要取消引用。 However, even doing (*processor)()
wouldn't help you, because pthread_create
is defined as follows : 但是,即使执行
(*processor)()
也无济于事,因为pthread_create
的定义如下:
int pthread_create(phread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
This means that the function to be executed must return void*
and take a void*
. 这意味着要执行的函数必须返回
void*
并采用void*
。 The documentation also states that the parameter of start_routine
has the value of arg
originally given to the respective call to pthread_create
. 该文档还指出,
start_routine
的arg
最初将arg
的值arg
赋予了对pthread_create
的相应调用。
However, you cannot pass a pointer to CommandProcessor::operator()()
to pthread_create
for a much more important reason : it is a member function. 但是,由于更重要的原因,您不能将指向
CommandProcessor::operator()()
的指针传递给pthread_create
:它是成员函数。 All non- static
class member functions need to be called with an object so that they can refer to this
inside their body. 所有非
static
类的成员函数需要一个对象被调用,以便他们可以参考this
自己的身体里面。
The solution to your problem is to make a static function that will match the prototype required by pthread_create
, and pass the pointer to a CommandProcessor
as the arg
of pthread_create
. 解决您的问题的方法是制作一个与
pthread_create
所需原型相匹配的静态函数,并将指针作为pthread_create
的arg
传递给CommandProcessor
。 Have a look at this : 看看这个:
static void* processor_executor(void *arg)
{
CommandProcessor *processor = static_cast<CommandProcessor*>(arg);
(*processor)();
return NULL;
}
int main(int argc, char **argv)
{
/* ... */
for(int i=0; i < MAX_THREADS; i++)
{
pthread_create(&threads[i], NULL, processor_executor, static_cast<void*> (processor));
}
/* ... */
}
This way, operator()
is executed inside the thread created by pthread_create
, using the same CommandProcessor
object as the one in main()
. 这样,
operator()
在pthread_create
创建的线程内执行,使用与main()
相同的CommandProcessor
对象。
Keep in mind that accessing the same data from within many parallel threads will lead to data races. 请记住,从许多并行线程中访问相同的数据将导致数据争用。 Use mutexes, semaphores, or condition variables to protect the data from parallel access.
使用互斥量,信号量或条件变量来保护数据免受并行访问。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.