我正在尝试将一个在C#下实现的线程池移植到Linux下的C++。但是我不知道应该使用哪些函数来实现与AutoResetEvent类似的行为。
我正在尝试将一个在C#下实现的线程池移植到Linux下的C++。但是我不知道应该使用哪些函数来实现与AutoResetEvent类似的行为。
AutoResetEvent最类似于二进制信号量。那些说"条件变量"的人并没有完全错,但是条件变量用于类似情况,而不是相似的对象。你可以在条件变量之上实现一个(无名)AutoResetEvent:
#include <pthread.h>
#include <stdio.h>
class AutoResetEvent
{
public:
explicit AutoResetEvent(bool initial = false);
~AutoResetEvent();
void Set();
void Reset();
bool WaitOne();
private:
AutoResetEvent(const AutoResetEvent&);
AutoResetEvent& operator=(const AutoResetEvent&); // non-copyable
bool flag_;
pthread_mutex_t protect_;
pthread_cond_t signal_;
};
AutoResetEvent::AutoResetEvent(bool initial)
: flag_(initial)
{
pthread_mutex_init(&protect_, NULL);
pthread_cond_init(&signal_, NULL);
}
void AutoResetEvent::Set()
{
pthread_mutex_lock(&protect_);
flag_ = true;
pthread_mutex_unlock(&protect_);
pthread_cond_signal(&signal_);
}
void AutoResetEvent::Reset()
{
pthread_mutex_lock(&protect_);
flag_ = false;
pthread_mutex_unlock(&protect_);
}
bool AutoResetEvent::WaitOne()
{
pthread_mutex_lock(&protect_);
while( !flag_ ) // prevent spurious wakeups from doing harm
pthread_cond_wait(&signal_, &protect_);
flag_ = false; // waiting resets the flag
pthread_mutex_unlock(&protect_);
return true;
}
AutoResetEvent::~AutoResetEvent()
{
pthread_mutex_destroy(&protect_);
pthread_cond_destroy(&signal_);
}
AutoResetEvent event;
void *otherthread(void *)
{
event.WaitOne();
printf("Hello from other thread!\n");
return NULL;
}
int main()
{
pthread_t h;
pthread_create(&h, NULL, &otherthread, NULL);
printf("Hello from the first thread\n");
event.Set();
pthread_join(h, NULL);
return 0;
}
如果您需要使用命名的自动重置事件,您可能需要查看信号量,并且在翻译代码时可能会遇到稍微困难一些的问题。无论哪种方式,我建议仔细查看您平台上的pthread文档,因为条件变量和自动重置事件不同且行为也不同。class event
{
public:
event(): signalled_ (false) {}
void signal ()
{
std::unique_lock<std::mutex> lock(mutex_);
signalled_ = true;
cond_.notify_one ();
}
void wait ()
{
std::unique_lock<std::mutex> lock(mutex_);
while (!signalled_)
cond_.wait (lock);
signalled_ = false;
}
protected:
std::mutex mutex_;
std::condition_variable cond_;
bool signalled_;
};
boost::condition_variable cond;
boost::mutex mut;
bool data_ready;
void wait_for_data_to_process()
{
boost::unique_lock<boost::mutex> lock(mut);
while(!data_ready)
{
cond.wait(lock);
}
}
void prepare_data_for_processing()
{
{ //scope for lock_guard
boost::lock_guard<boost::mutex> lock(mut);
data_ready=true;
}
cond.notify_one();
}
我知道可能有点来不及了,而且我没有有关性能差异的信息,但是使用pthread_kill和sigwait的组合可能是一个可行的替代方案,方法如下:
在适当的地方声明以下内容:
int sigin;
sigset_t sigset;
以以下方式初始化先前的变量:
sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1);
pthread_sigmask(SIG_BLOCK, &sigset, null);
在等待线程中,调用sigwait:
sigwait(&sigset, &sigin);
然后,在应该唤醒等待线程的线程上,您可以这样做:
pthread_kill(p_handle, SIGUSR1);
其中p_handle是您希望取消阻塞的线程句柄。
此示例会阻塞等待的线程,直到传递SIGUSR1信号。由于使用pthread_kill,信号仅到达特定线程。
嗯,很有可能是一个互斥锁——你有多个调用者想要访问共享资源,但只允许一个进入。在互斥锁的情况下,调用者会尝试获取互斥锁(例如phtread_mutex_lock),执行他们的操作,然后释放(pthread_mutex_unlock),以便其他调用者可以进入。