我目前正在编写ac/c ++ dll以供以后在Delphi中使用,我对Delphi中的线程比c/c ++更熟悉,尤其是boost.所以我想知道如何实现以下场景?
class CMyClass
{
private:
boost::thread* doStuffThread;
protected:
void doStuffExecute(void)
{
while(!isTerminationSignal()) // loop until termination signal
{
// do stuff
}
setTerminated(); // thread is finished
};
public:
CMyClass(void)
{
// create thread
this->doStuffThread = new boost::thread(boost::bind(&CMyClass::doStuffExecute, this));
};
~CMyClass(void)
{
// finish the thread
signalThreadTermination();
waitForThreadFinish();
delete this->doStuffThread;
// do other cleanup
};
}
Run Code Online (Sandbox Code Playgroud)
我有关于提升线程,信号和互斥量的红色无数文章,但我不明白,可能是因为它是星期五;)或者我认为这样做是不可行的?
关心丹尼尔
我很好奇volatile关键部分使用的资源是否必要。假设我有两个线程在两个 CPU 上执行,并且它们正在竞争共享资源。我知道我需要一种锁定机制来确保只有一个线程正在该共享资源上执行操作。下面是将在这两个线程上执行的伪代码。
take_lock();
// Read shared resource.
read_shared_resouce();
// Write something to shared resource.
write_shared_resource();
release_lock();
Run Code Online (Sandbox Code Playgroud)
我想知道是否需要使该共享资源成为易失性的,以确保当一个线程读取共享资源时,线程不仅会从寄存器中获取值,而且实际上会从该共享资源中读取值。或者也许我应该使用访问器函数通过一些内存屏障操作来使对该共享资源的访问变得易失,而不是使该共享资源变得易失?
我有一个相当简单的情况:我在一个线程中有一个高速数据生成器,它生成一个带有[变长]元素的缓冲区.填充此缓冲区后,我有一个将其写入磁盘的使用者.
现在,生成器线程需要返回生成ASAP,如果缓冲区尚未被消费者线程写入,则会旋转到位:
int volatile datatogo=0; // global with starting condition
while(datatogo != 0) // spin, buffer not yet written out
{
if (recflag == 0) return; // recording is terminated
}
// clipped code fills buffer, then:
datatogo = lengthoffill;
Run Code Online (Sandbox Code Playgroud)
...在另一个线程中,缓冲区编写器执行此操作:
while(recflag)
{
if (datatogo)
{
if (m_File.write(sbuffer,datatogo) == -1)
{
recflag=0; // bail NOW
}
datatogo = 0; // buffer transferred
}
usleep(100); // 100 uS
}
Run Code Online (Sandbox Code Playgroud)
这样做的最终结果是写入磁盘消费者在完成写入时放弃了CPU,知道生产者必须花一些时间来实际填充缓冲区.当消费者在没有数据时睡着了,CPU可供生产者使用.消费者睡眠时间为100 uS,检查数据,如果没有,则返回睡眠状态,因此除了睡眠状态之外,它在该状态下没有做太多事情.
但是,因为睡眠时间是任意的,所以这不可能是最佳的; 即使我仔细调整它以在我的机器上工作(8核,3 GHz),它在另一台机器上的行为也会不同.有时会有数据准备好被写入,消费者刚刚进入睡眠状态,将整个100美元扔出窗外,可以这么说.我也对这种小型计时窗口的分辨率和可靠性有疑虑 - 而较大的窗口将无法工作.
所以.Qt中有多种机制来控制对事物的访问,这基本上就是我想做的事情.但我不明白哪一个(如果有的话)会做我想做的事,这是:
1)让消费者睡眠直到缓冲区已满,然后写入并返回睡眠状态,或直到作业停止,这样它就可以关闭文件(它可以检查唤醒时哪个)
2)当生成器只在缓冲区被写出时才会休眠,否则填充缓冲区并返回生成其内容.
我需要尽可能多的CPU可用 - …
{使用Visual Studio 2010和Win7}
class Base
{
public:
Base() : terminateCondition(false)
{
//spawn new thread and set entry point to newThreadFunc()
}
virtual ~Base() // edited to say it's virtual.
{
terminateCondition=true;
//wait for thread to join
}
virtual void vfunc() = 0;
static void __stdcall newThreadFunc(void *args)
{
while(!terminateCondition)
pThis->vfunc();
}
volatile bool terminateCondition;
};
class Derived : public Base
{
public:
virtual void vfunc()
{
//Do Something
}
};
Derived* dPtr=new Derived; //now assume pThis is dptr
//later somewhere …Run Code Online (Sandbox Code Playgroud) 这可能是一个与语言无关的问题,但实际上我对 C++ 的情况感兴趣:如何用支持 MT 编程的 C++ 版本编写多线程程序,即具有内存模型的现代 C++,如何证明是正确的?
在旧的 C++ 中,MT 程序只是根据 pthread 语义编写,并根据 pthread 规则进行验证,这在概念上很简单:正确使用原语并避免数据竞争。
现在,C++ 语言语义是根据内存模型定义的,而不是根据原始步骤的顺序执行来定义的。(该标准还提到了“抽象机器”,但我不再明白它的含义。)
如何用非顺序语义证明 C++ 程序的正确性?一个程序没有一个接一个地执行原始步骤,怎么能推理出这个程序呢?
我有一些 C++ 代码,大致包含以下逻辑:
class wrapper_info {
public:
bool isConnected();
void connectedHandler();
void disconnectedHandler();
protected:
bool _connected;
}
void wrapper_info::connectedHandler() {
_connected = true;
}
void wrapper_info::disconnectedHandler() {
_connected = false;
}
bool wrapper_info::isConnected() {
return _connected;
}
extern "C"
bool is_connected(void *obj) {
wrapper_info *wrapper_obj = reinterpret_cast<wrapper_info*>(obj);
return wrapper_obj->isConnected();
}
Run Code Online (Sandbox Code Playgroud)
由于大多数我无法控制的原因,不同的线程(在不同的 CPU 内核上运行)按以下方式调用这些函数。
线程 1、2、3:is_connected(obj)
线程2:connectedHandler()连接发起时。
disconnectedHandler()当连接断开时线程3 。
我认为,如果重复调用 和connectedHandler(),可能会出现问题disconnectedHandler(),两个线程写入的问题_connected以及写入的顺序会出现问题,从而导致错误的最终值。民意调查也可能存在问题_connected。
我的问题是:
_connected? …是否有可能通过内存屏障实现易失性变量的相同“保证”(始终读/写内存而不是寄存器)?只需在一个线程中写入变量,然后在另一个线程中读取其值。下面的内容是等价的吗?
#define rmb() __sync_synchronize()
#define wmb() __sync_synchronize()
static volatile int a;
static int b;
//invoked by thread 1
static void writer(void)
{
...
a = 1;
...
b = 1;
wmb();
}
//invoked by thread 2
static void reader(void)
{
...
while (a != 1)
;
// do something
...
while (b != 1)
rmb();
// do something
}
Run Code Online (Sandbox Code Playgroud)
编辑:好的,我知道 volatile 不能保证原子性、可见性或顺序。内存屏障除了排序之外还提供其他功能吗?还有能见度?除了 _Atomic C11 或 gcc/clang 原子内置函数之外,还有其他东西可以保证可见性吗?