【发布时间】:2014-01-09 21:15:56
【问题描述】:
我有一个带有受保护构造函数的基类 IRunnable,因此不能创建基类的任何实例。该类有一个纯虚方法run(),它必须由派生类实现。我将 IRunnable * 的指针传递给某种类似 java 的 Executor,它控制多个线程,并将这些 Runnables 分配给它们。 我的问题是,当这样一个 IRunnable * 指针指向 IRunnable 派生类的对象时,它位于另一个线程的堆栈上,被分配给工作线程时,我不能确定派生对象不是在工作线程仍在使用它时被销毁,因为在其线程上拥有对象的线程可能会离开创建对象的范围。 例如:
int main(void)
{
CExecutor myExecutor(...);
for (UInt32 i = 0; i < 2; i++)
{
derivedRunnable myRunnable1; //will be destroyed after each loop iteration
myExecutor.submit(myRunnable1);
}
}
class derivedRunnable : public IRunnable
{
public:
derivedRunnable(const char * name = NULL) : IRunnable(name) {}
~derivedRunnable() {}
void run(void)
{
for (UInt32 i = 0; i < 100; i++)
{
char name [256] = {"\0"};
pthread_getname_np(pthread_self(), name, 255);
printf("%s in step %d\n", name, i);
}
fflush(stdout);
}
};
我在基类 IRunnable 中实现了一个引用计数,并且我在析构函数中执行了一个阻塞调用,该调用只有在使用它的最后一个线程向它注销时才会返回。问题是,派生类 get 的析构函数首先被调用,因此在调用阻塞调用破坏的基类之前,对象将被部分破坏。
在上面的示例中,我收到以下运行时错误:pure virtual method calledterminate called without an active exception
如果我在 .submit() 调用之后插入一些 usec 的 usleep ,它将起作用,因为线程将在它被销毁之前完成可运行对象
class IRunnable
{
friend class CThread;
friend class CExecutor;
private:
CMutex mutx;
CBinarySemaphore sem;
UInt32 userCount;
[...]
virtual void run(void) = 0;
IRunnable(const IRunnable & rhs); //deny
IRunnable & operator= (const IRunnable & rhs); //deny
void registerUser(void)
{
mutx.take(true);
if (0 == userCount++)
sem.take(true);
mutx.give();
}
void unregisterUser(void)
{
mutx.take(true);
if (0 == --userCount)
sem.give();
mutx.give();
}
protected:
IRunnable(const char * n = NULL)
:mutx(true,false)
,sem(true,false)
,userCount(0)
{
setName(n);
}
~IRunnable()
{
sem.take(true);
}
[...]
我能做什么?
【问题讨论】:
标签: c++ multithreading inheritance