- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我遇到了一个关于游戏循环线程安全的轻微难题。我下面的是 3 个线程(包括主线程),它们可以一起工作。一种用于事件管理(主线程),一种用于逻辑,一种用于渲染。所有这 3 个线程都存在于它们自己的类中,如下所示。在基本测试中,该结构可以正常工作。该系统使用 SFML 并使用 OpenGL 进行渲染。
int main(){
Gamestate gs;
EventManager em(&gs);
LogicManager lm(&gs);
Renderer renderer(&gs);
lm.start();
renderer.start();
em.eventLoop();
return 0;
}
但是,正如您可能已经注意到的,我有一个“Gamestate”类,旨在充当需要在线程之间共享的所有资源的容器(主要是将 LogicManager 作为编写器,将 Renderer 作为读取器。 EventManager 主要用于窗口事件)。我的问题是:(1 和 2 是最重要的)
1) 这是处理事情的好方法吗?意思是使用“全局”Gamestate 类是个好主意吗?有更好的方法吗?
2) 我的意图是让 Gamestate 在 getters/setters 中有互斥量,除了它对读取不起作用,因为我无法在对象仍然锁定时返回它,这意味着我必须将同步放在外面getters/setters 并公开互斥量。这也意味着我将拥有大量用于所有不同资源的互斥体。解决这个问题最优雅的方法是什么?
3) 我让所有线程访问“bool run”以检查是否继续它们的循环
while(gs->run){
....
}
如果我在 EventManager 中收到退出消息,run 将设置为 false。我是否需要同步该变量?我会把它设置为 volatile 吗?
4) 不断取消引用指针等是否会对性能产生影响?例如 gs->objects->entitylist.at(2)->move();做所有那些“->”和“。”导致任何重大放缓?
最佳答案
1) Is this a good way of going about things? Meaning is having a "global" Gamestate class a good idea to use? Is there a better way of going about it?
对于游戏而言,相对于一些可重用的代码,我认为全局状态就足够了。您甚至可以避免传递游戏状态指针,而是真正将其设为全局变量。
2) My intention was to have Gamestate have mutexes in the getters/setters, except that doesn't work for reading because I can't return the object while it's still locked, which means I'd have to put synchronization outside of the getters/setters and make the mutexes public. It also means I'd have a bloody ton of mutexes for all the different resources. What is the most elegant way of going about this problem?
我会尝试从交易的角度考虑这一点。将每个状态更改包装到它自己的互斥锁定代码中不仅会影响性能,而且如果代码获取一个状态元素,对其执行一些计算并稍后设置值,而其他代码修改了该状态,则可能会导致实际上不正确的行为之间的相同元素。因此,我尝试以这样的方式构建 LogicManager
和 Renderer
,以便将所有与 Gamestate 的交互都捆绑在几个地方。在该交互期间,线程应在状态上持有一个互斥体。
如果你想强制使用互斥锁,那么你可以在至少有两个类的地方创建一些结构。我们称它们为 GameStateData
和 GameStateAccess
。 GameStateData
将包含所有状态,但不提供对其的公共(public)访问。 GameStateAccess
将是 GameStateData
的友元,并提供对其私有(private)数据的访问。 GameStateAccess
的构造函数将获取对 GameStateData
的引用或指针,并锁定该数据的互斥量。析构函数将释放互斥体。这样,您操纵状态的代码将简单地编写为一个 block ,其中 GameStateAccess
对象在范围内。
但是仍然存在一个漏洞:如果从此 GameStateAccess
类返回的对象是指向可变对象的指针或引用,那么此设置不会阻止您的代码携带此类指针受互斥量保护的范围。为防止这种情况,请注意您的编写方式,或者使用一些自定义的类似指针的模板类,一旦 GameStateAccess
超出范围就可以将其清除,或者确保您只按值传递内容不是引用。
使用C++11,上述锁管理思想可以实现如下:
class GameStateData {
private:
std::mutex _mtx;
int _val;
friend class GameStateAccess;
};
GameStateData global_state;
class GameStateAccess {
private:
GameStateData& _data;
std::lock_guard<std::mutex> _lock;
public:
GameStateAccess(GameStateData& data)
: _data(data), _lock(data._mtx) {}
int getValue() const { return _data._val; }
void setValue(int val) { _data._val = val; }
};
void LogicManager::performStateUpdate {
int valueIncrement = computeValueIncrement(); // No lock for this computation
{ GameStateAccess gs(global_state); // Lock will be held during this scope
int oldValue = gs.getValue();
int newValue = oldValue + valueIncrement;
gs.setValue(newValue); // still in the same transaction
} // free lock on global state
cleanup(); // No lock held here either
}
3) I have all of the threads accessing "bool run" to check if to continue their loops
while(gs->run){
....
}run gets set to false if I receive a quit message in the EventManager. Do I need to synchronize that variable at all? Would I set it to volatile?
对于这个应用程序,一个易失但不同步的变量应该没问题。您必须将其声明为 volatile,以防止编译器生成缓存该值的代码,从而隐藏另一个线程的修改。
作为替代方案,您可能想使用 std::atomic
变量。
4) Does constantly dereferencing pointers and such have an impact on performance? eg
gs->objects->entitylist.at(2)->move();
Do all those->
and.
cause any major slowdown?
这取决于备选方案。在许多情况下,编译器将能够保留例如的值。上面代码中的gs->objects->entitylist.at(2)
,如果重复使用,就不用反复计算了。总的来说,我认为由于所有这些指针间接寻址而导致的性能损失是次要问题,但这很难确定。
关于c++ - 构建和同步多线程游戏循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12684844/
我是 PHP 新手。我一直在脚本中使用 for 循环、while 循环、foreach 循环。我想知道 哪个性能更好? 选择循环的标准是什么? 当我们在另一个循环中循环时应该使用哪个? 我一直想知道要
我在高中的编程课上,我的作业是制作一个基本的小计和顶级计算器,但我在一家餐馆工作,所以制作一个只能让你在一种食物中读到。因此,我尝试让它能够接收多种食品并将它们添加到一个价格变量中。抱歉,如果某些代码
这是我正在学习的一本教科书。 var ingredients = ["eggs", "milk", "flour", "sugar", "baking soda", "baking powder",
我正在从字符串中提取数字并将其传递给函数。我想给它加 1,然后返回字符串,同时保留前导零。我可以使用 while 循环来完成此操作,但不能使用 for 循环。 for 循环只是跳过零。 var add
编辑:我已经在程序的输出中进行了编辑。 该程序要求估计给定值 mu。用户给出一个值 mu,同时还提供了四个不等于 1 的不同数字(称为 w、x、y、z)。然后,程序尝试使用 de Jaeger 公式找
我正在编写一个算法,该算法对一个整数数组从末尾到开头执行一个大循环,其中包含一个 if 条件。第一次条件为假时,循环可以终止。 因此,对于 for 循环,如果条件为假,它会继续迭代并进行简单的变量更改
现在我已经习惯了在内存非常有限的情况下进行编程,但我没有答案的一个问题是:哪个内存效率更高;- for(;;) 或 while() ?还是它们可以平等互换?如果有的话,还要对效率问题发表评论! 最佳答
这个问题已经有答案了: How do I compare strings in Java? (23 个回答) 已关闭 8 年前。 我正在尝试创建一个小程序,我可以在其中读取该程序的单词。如果单词有 6
这个问题在这里已经有了答案: python : list index out of range error while iteratively popping elements (12 个答案) 关
我正在尝试向用户请求 4 到 10 之间的整数。如果他们回答超出该范围,它将进入循环。当用户第一次正确输入数字时,它不会中断并继续执行 else 语句。如果用户在 else 语句中正确输入数字,它将正
我尝试创建一个带有嵌套 foreach 循环的列表。第一个循环是循环一些数字,第二个循环是循环日期。我想给一个日期写一个数字。所以还有另一个功能来检查它。但结果是数字多次写入日期。 Out 是这样的:
我想要做的事情是使用循环创建一个数组,然后在另一个类中调用该数组,这不会做,也可能永远不会做。解决这个问题最好的方法是什么?我已经寻找了所有解决方案,但它们无法编译。感谢您的帮助。 import ja
我尝试创建一个带有嵌套 foreach 循环的列表。第一个循环是循环一些数字,第二个循环是循环日期。我想给一个日期写一个数字。所以还有另一个功能来检查它。但结果是数字多次写入日期。 Out 是这样的:
我正在模拟一家快餐店三个多小时。这三个小时分为 18 个间隔,每个间隔 600 秒。每个间隔都会输出有关这 600 秒内发生的情况的统计信息。 我原来的结构是这样的: int i; for (i=0;
这个问题已经有答案了: IE8 for...in enumerator (3 个回答) How do I check if an object has a specific property in J
哪个对性能更好?这可能与其他编程语言不一致,所以如果它们不同,或者如果你能用你对特定语言的知识回答我的问题,请解释。 我将使用 c++ 作为示例,但我想知道它在 java、c 或任何其他主流语言中的工
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况有关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
我是 C 编程和编写代码的新手,以确定 M 测试用例的质因数分解。如果我一次只扫描一次,该功能本身就可以工作,但是当我尝试执行 M 次时却惨遭失败。 我不知道为什么 scanf() 循环有问题。 in
这个问题已经有答案了: JavaScript by reference vs. by value [duplicate] (4 个回答) 已关闭 3 年前。 我在使用 TSlint 时遇到问题,并且理
我尝试在下面的代码中添加 foreach 或 for 循环,以便为 Charts.js 创建多个数据集。这将允许我在此折线图上创建多条线。 我有一个 PHP 对象,我可以对其进行编码以稍后填充变量,但
我是一名优秀的程序员,十分优秀!