[英]Mutex can't acquire lock
I have a problem where one of my functions can't aquire the lock on one of the 2 mutexes I use. 我有一个问题,我的功能之一无法获取我使用的2个互斥锁之一上的锁。 I did a basic debug in VC++2010 , setting some breakpoints and it seems if anywhere the lock is acquired, it does get unlocked.
我在VC ++ 2010中进行了基本调试,设置了一些断点,并且似乎在任何地方获得了锁都可以将其解锁。
The code that uses mutexes is as follow: 使用互斥锁的代码如下:
#define SLEEP(x) { Sleep(x); }
#include<windows.h>
void Thread::BackgroundCalculator( void *unused ){
while( true ){
if(MUTEX_LOCK(&mutex_q, 5) == 1){
if(!QueueVector.empty()){
//cut
MUTEX_UNLOCK(&mutex_q);
//cut
while(MUTEX_LOCK(&mutex_p,90000) != 1){}
//cut
MUTEX_UNLOCK(&mutex_p);
}
}
SLEEP(25);
}
}
Then somwhere else: 然后在其他地方:
PLUGIN_EXPORT void PLUGIN_CALL
ProcessTick(){
if(g_Ticked == g_TickMax){
if(MUTEX_LOCK(&mutex_p, 1) == 1){
if(!PassVector.empty()){
PassVector.pop();
}
MUTEX_UNLOCK(&mutex_p);
}
g_Ticked = -1;
}
g_Ticked += 1;
}
static cell AMX_NATIVE_CALL n_CalculatePath( AMX* amx, cell* params ){
if(MUTEX_LOCK(&mutex_q,1) == 1){
QueueVector.push_back(QuedData(params[1],params[2],params[3],amx));
MUTEX_UNLOCK(&mutex_q);
return 1;
}
return 0;
}
init: 在里面:
PLUGIN_EXPORT bool PLUGIN_CALL Load( void **ppData ) {
MUTEX_INIT(&mutex_q);
MUTEX_INIT(&mutex_p);
START_THREAD( Thread::BackgroundCalculator, 0);
return true;
}
Some variables and functions: 一些变量和函数:
int MUTEX_INIT(MUTEX *mutex){
*mutex = CreateMutex(0, FALSE, 0);
return (*mutex==0);
}
int MUTEX_LOCK(MUTEX *mutex, int Timex = -1){
if(WaitForSingleObject(*mutex, Timex) == WAIT_OBJECT_0){
return 1;
}
return 0;
}
int MUTEX_UNLOCK(MUTEX *mutex){
return ReleaseMutex(*mutex);
}
MUTEX mutex_q = NULL;
MUTEX mutex_p = NULL;
and defines: 并定义:
# include <process.h>
# define OS_WINDOWS
# define MUTEX HANDLE
# include <Windows.h>
# define EXIT_THREAD() { _endthread(); }
# define START_THREAD(a, b) { _beginthread( a, 0, (void *)( b ) ); }
Thread header file: 线程头文件:
#ifndef __THREAD_H
#define __THREAD_H
class Thread{
public:
Thread ( void );
~Thread ( void );
static void BackgroundCalculator ( void *unused );
};
#endif
Well I can't seem to find the issue. 好吧,我似乎找不到问题。 After debugging I wanted to "force" aquiring the lock by this code (from the pawn abstract machine):
调试后,我想通过以下代码“强制”获取锁(从典当抽象机中获取):
if (strcmp("/routeme", cmdtext, true) == 0){
new fromnode = NearestPlayerNode(playerid);
new start = GetTickCount();
while(CalculatePath(fromnode,14,playerid+100) == 0){
printf("0 %d",fromnode);
}
printf("1 %d",fromnode);
printf("Time: %d",GetTickCount()-start);
return 1;
}
but it keeps endless going on, CalculatePath calls static cell AMX_NATIVE_CALL n_CalculatePath( AMX* amx, cell* params ) 但它不断进行下去,CalculatePath调用静态单元格AMX_NATIVE_CALL n_CalculatePath(AMX * amx,cell * params)
That was a bit of surprise. 这有点令人惊讶。 Does anyone maybe see a mistake?
有人看到错误吗?
If you need the full source code it is available at: 如果您需要完整的源代码,请访问:
http://gpb.googlecode.com/files/RouteConnector_174alpha.zip http://gpb.googlecode.com/files/RouteConnector_174alpha.zip
Extra info: PLUGIN_EXPORT bool PLUGIN_CALL Load gets only executed at startup. 额外信息:PLUGIN_EXPORT bool PLUGIN_CALL仅在启动时执行加载。
static cell AMX_NATIVE_CALLs get only executed when called from a vitrual machine 静态单元格AMX_NATIVE_CALLs仅在从虚拟机调用时执行
ProcessTick() gets executed every process tick of the application, after it has finished its own jobs it calls this one in the extensions. ProcessTick()在应用程序的每个进程滴答结束后都会执行,它在完成自己的工作后会在扩展程序中调用它。
For now I only tested the code on windows, but it does compile fine on linux. 到目前为止,我仅在Windows上测试了代码,但在Linux上确实可以很好地编译。
Edit: removed linux code to shorten post. 编辑:删除了linux代码以缩短发布时间。
From what I see your first snippet unlocks mutex based on some condition only, ie in pseudocode it is like: 根据我的见解,您的第一个代码段仅基于某些条件来解锁互斥锁,即在伪代码中,它就像:
mutex.lock ():
if some_unrelated_thing:
mutex.unlock ()
As I understand your code, this way the first snippet can in principle lock and then never unlock. 据我了解您的代码,原则上,第一个代码段可以锁定然后再解锁。
Another potential problem is that your code is ultimately exception-unsafe. 另一个潜在的问题是您的代码最终是不安全的异常。 Are you really able to guarantee that no exceptions happen between lock/unlock operations?
您真的能够保证锁定/解锁操作之间不会发生异常吗? Because if any uncaught exception is ever thrown, you get into a deadlock like described.
因为如果曾经抛出任何未捕获的异常,您将陷入描述的僵局。 I'd suggest using some sort of RAII here.
我建议在这里使用某种RAII。
EDIT: 编辑:
Untested RAII way of performing lock/unlock: 未经测试的RAII执行锁定/解锁方式:
struct Lock
{
MUTEX& mutex;
bool locked;
Lock (MUTEX& mutex)
: mutex (mutex),
locked (false)
{ }
~Lock ()
{ release (); }
bool acquire (int timeout = -1)
{
if (!locked && WaitForSingleObject (mutex, timeout) == WAIT_OBJECT_0)
locked = true;
return locked;
}
int release ()
{
if (locked)
locked = ReleaseMutex (mutex);
return !locked;
}
};
Usage could be like this: 用法可能是这样的:
{
Lock q (mutex_q);
if (q.acquire (5)) {
if (!QueueVector.empty ()) {
q.release ();
...
}
}
}
Note that this way ~Lock
always releases the mutex, whether you did that explicitly or not, whether the scope block exited normally or due to an uncaught exception. 请注意,无论您是否明确地执行此操作,无论
~Lock
范围块是正常退出还是由于未捕获的异常,〜Lock都会始终释放互斥锁。
I'm not sure if this is intended behavior, but in this code: 我不确定这是否是预期的行为,但是在以下代码中:
void Thread::BackgroundCalculator( void *unused ){
while( true ){
if(MUTEX_LOCK(&mutex_q, 5) == 1){
if(!QueueVector.empty()){
//cut
MUTEX_UNLOCK(&mutex_q);
//cut
while(MUTEX_LOCK(&mutex_p,90000) != 1){}
//cut
MUTEX_UNLOCK(&mutex_p);
}
}
SLEEP(25);
}
if the QueueVector.empty
is true you are never unlocking mutex_q
. 如果
QueueVector.empty
为true,则永远不会解锁mutex_q
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.