【发布时间】:2013-09-11 10:05:18
【问题描述】:
我正在尝试构建对象,这需要一段时间才能在单独的线程中构建。 (稍后在渲染循环运行时实时加载游戏资源:))
当对象仍在构建时,对该对象的请求不会失败,而是做一些替换。 (就像在游戏中绘制没有纹理,而纹理仍在加载时)。 我的解决方法是使用State-Pattern - 一种状态表示可用状态,用于仍在加载。 (我的第一个是 Proxy,但你真的不想看到那个代码!)
这是完整的源代码:
#include <thread>
#include <iostream>
#include <list>
using namespace std;
class Object
{
private:
int _data;
/// Classes for states ///
class IState
{
public:
virtual void Use(Object *obj) = 0;
};
class Unavailable : public IState
{
public:
void Use(Object *obj)
{cout << "Object not avaiable..." << endl;}
};
class Avaiable : public IState
{
public:
void Use(Object *obj)
{cout << "Data is: " << obj->_data << endl;}
};
////////////////////////
IState *_state;
void ChangeState(IState *newstate)
{
delete _state;
_state = newstate;
}
void Construct() //Can this be part of IState?
{
this_thread::sleep_for(chrono::seconds(1)); //Work hard
_data = 50;
ChangeState(new Avaiable());
}
public:
Object()
{
//Set the state to unavaiable
_state = new Unavailable();
//Construct the object in seperate thread
thread constructor(&Object::Construct, this); //How do I refer to Construct if its a member of IState?
constructor.detach();
//Thread runs while out of scope!
}
~Object()
{delete _state;}
void Use()
{
//Redirect actions
_state->Use(this);
}
};
int main()
{
{
list<Object*> objects;
for (int i = 0; i < 10; i++)
{
this_thread::sleep_for(chrono::milliseconds(500));
objects.push_back(new Object()); //I can't use Object as the list type, because of push_back()
//copying the Object then DELETING it, thus deleting the state
for (auto obj : objects) //The objects, which are already build shoud write "50"
//otherwise it should write "Not avaiable" as a replacement
{
obj->Use();
}
}
//Free the objects (I really want to avoid this....)
for (auto obj : objects)
delete obj;
} //Extra scope to prevent false memory leaks!
_CrtDumpMemoryLeaks(); //Reports memory leak somewhere. Couldn't track the block back to my code(...)
}
问题是(如代码中所述):
- 如何移动
Construct()接口中的Construct()方法以改进设计(如果对象已经可用,则放弃Construct()调用!) - 我可以列出
Object而不是Object*吗? - 内存泄漏可能是什么? (我无法使用
_CrtSetBreakAlloc将代码块追溯到我自己的代码?!)
期待您的答案和设计方面的问题。 (我刚开始处理软件架构,所以如果这种方法是垃圾,请纠正我;))
【问题讨论】:
-
_state 不是线程安全的。
-
你可以让对象移动;那么您将不需要
new和额外的间接级别,只需将其放入容器中即可。您也可以使用向量而不是列表,这样会更有效。最简单的方法是存储unique_ptr而不是裸指针;这也将修复当前无效的复制语义并消除对显式析构函数的需求。 -
@MikeSeymour:他无法移动/复制对象,它正在另一个线程中构建(否则他必须同步移动:-/)。
-
这里有几个问题:
_state不同步(原子/互斥体),最好表示为std::unique_ptr<State>,并且对象可能在线程完成执行之前被销毁(boom )。您可以使用shared_ptr解决后一个问题,而使用互斥锁(或std::atomic<State*>,但这需要您学习如何正确处理内存)来解决前一个问题。 -
@MatthieuM。
shared_ptrs 可以原子处理,所以他免费获得。
标签: c++ c++11 architecture stdthread