- this seems to be stable now and handles lag quite well i think

This commit is contained in:
Mark Vejvoda 2013-03-02 07:33:01 +00:00
parent 951cd33ef4
commit 47aa0050b8
8 changed files with 112 additions and 9 deletions

View File

@ -613,12 +613,14 @@ void Commander::updateNetwork(Game *game) {
GameSettings *gameSettings = game->getGameSettings();
if( networkManager.isNetworkGame() == false ||
(world->getFrameCount() % gameSettings->getNetworkFramePeriod()) == 0) {
//printf("Commander world->getFrameCount() = %d gameSettings->getNetworkFramePeriod() = %d\n",world->getFrameCount(),gameSettings->getNetworkFramePeriod());
//printf("#1 Commander world->getFrameCount() = %d gameSettings->getNetworkFramePeriod() = %d\n",world->getFrameCount(),gameSettings->getNetworkFramePeriod());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] networkManager.isNetworkGame() = %d,world->getFrameCount() = %d, gameSettings->getNetworkFramePeriod() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkManager.isNetworkGame(),world->getFrameCount(),gameSettings->getNetworkFramePeriod());
//std::vector<NetworkCommand> replayList = getReplayCommandListForFrame();
if(getReplayCommandListForFrame(world->getFrameCount()) == false) {
//printf("#2 Commander world->getFrameCount() = %d gameSettings->getNetworkFramePeriod() = %d\n",world->getFrameCount(),gameSettings->getNetworkFramePeriod());
GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) perfTimer.start();

View File

@ -1726,10 +1726,11 @@ void Game::update() {
ClientInterface *clientInterface = dynamic_cast<ClientInterface *>(networkManager.getClientInterface());
if(clientInterface != NULL) {
uint64 lastNetworkFrameFromServer = clientInterface->getCachedLastPendingFrameCount();
//if(lastNetworkFrameFromServer > 0 && lastNetworkFrameFromServer > world.getFrameCount() + gameSettings.getNetworkFramePeriod()) {
if(lastNetworkFrameFromServer > 0 && lastNetworkFrameFromServer > world.getFrameCount()) {
//int frameDifference = lastNetworkFrameFromServer - (world.getFrameCount() + gameSettings.getNetworkFramePeriod());
int frameDifference = lastNetworkFrameFromServer - world.getFrameCount();
if(lastNetworkFrameFromServer > 0 && lastNetworkFrameFromServer > (world.getFrameCount() + gameSettings.getNetworkFramePeriod())) {
//if(lastNetworkFrameFromServer > 0 && lastNetworkFrameFromServer > world.getFrameCount()) {
int frameDifference = ((lastNetworkFrameFromServer - world.getFrameCount()) / gameSettings.getNetworkFramePeriod()) * gameSettings.getNetworkFramePeriod();
//int frameDifference = lastNetworkFrameFromServer - world.getFrameCount();
printf("Client will speed up: %d frames lastNetworkFrameFromServer: %lld world.getFrameCount() = %d updateLoops = %d\n",frameDifference,(long long int)lastNetworkFrameFromServer,world.getFrameCount(),updateLoops);

View File

@ -68,6 +68,7 @@ ClientInterface::ClientInterface() : GameNetworkInterface() {
gotIntro = false;
lastNetworkCommandListSendTime = 0;
currentFrameCount = 0;
lastSentFrameCount = 0;
clientSimulationLagStartTime = 0;
networkGameDataSynchCheckOkMap = false;
@ -199,9 +200,12 @@ void ClientInterface::update() {
(lastNetworkCommandListSendTime > 0 && lastSendElapsed >= ClientInterface::maxNetworkCommandListSendTimeWait)) {
lastNetworkCommandListSendTime = time(NULL);
//printf("#1 Client send currentFrameCount = %d\n",currentFrameCount );
if(lastSentFrameCount < currentFrameCount || networkMessageCommandList.getCommandCount() > 0) {
//printf("#1 Client send currentFrameCount = %d lastSentFrameCount = %d\n",currentFrameCount,lastSentFrameCount );
sendMessage(&networkMessageCommandList);
lastSentFrameCount = currentFrameCount;
sendMessage(&networkMessageCommandList);
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 1) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
}

View File

@ -54,6 +54,7 @@ private:
int port;
int currentFrameCount;
int lastSentFrameCount;
time_t lastNetworkCommandListSendTime;
time_t clientSimulationLagStartTime;

View File

@ -637,6 +637,9 @@ void ConnectionSlot::update(bool checkForNewClients,int lockedSlotIndex) {
for(;waitForLaggingClient == true ||
(this->hasDataToRead() == true &&
(gotTextMsg == true || gotCellMarkerMsg == true));) {
//printf("Server slot checking for waitForLaggingClient = %d this->hasDataToRead() = %d gotTextMsg = %d gotCellMarkerMsg = %d\n",waitForLaggingClient,this->hasDataToRead(),gotTextMsg,gotCellMarkerMsg);
waitForLaggingClient = false;
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] polling for networkMessageType...\n",__FILE__,__FUNCTION__,__LINE__);
@ -803,6 +806,9 @@ void ConnectionSlot::update(bool checkForNewClients,int lockedSlotIndex) {
if(receiveMessage(&networkMessageCommandList)) {
currentFrameCount = networkMessageCommandList.getFrameCount();
lastReceiveCommandListTime = time(NULL);
//printf("#1 Server slot got currentFrameCount = %d\n",currentFrameCount);
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] currentFrameCount = %d\n",__FILE__,__FUNCTION__,__LINE__,currentFrameCount);
MutexSafeWrapper safeMutexSlot(mutexPendingNetworkCommandList,CODE_AT_LINE);
@ -810,6 +816,8 @@ void ConnectionSlot::update(bool checkForNewClients,int lockedSlotIndex) {
vctPendingNetworkCommandList.push_back(*networkMessageCommandList.getCommand(i));
}
safeMutexSlot.ReleaseLock();
//printf("#2 Server slot got currentFrameCount = %d\n",currentFrameCount);
}
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled) SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d]\nInvalid message type before intro handshake [%d]\nDisconnecting socket for slot: %d [%s].\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,networkMessageType,this->playerIndex,this->getIpAddress().c_str());
@ -1289,6 +1297,8 @@ void ConnectionSlot::update(bool checkForNewClients,int lockedSlotIndex) {
this->sendMessage(&networkMessageReady);
this->currentFrameCount = serverInterface->getCurrentFrameCount();
//printf("#2 Server slot got currentFrameCount = %d\n",currentFrameCount);
this->currentLagCount = 0;
this->lastReceiveCommandListTime = time(NULL);
@ -1326,11 +1336,15 @@ void ConnectionSlot::update(bool checkForNewClients,int lockedSlotIndex) {
}
}
//printf("#3 Server slot got currentFrameCount = %d\n",currentFrameCount);
// This may end up continuously lagging and not disconnecting players who have
// just the 'wrong' amount of lag (but not enough to be horrible for a disconnect)
if(Config::getInstance().getBool("AutoClientLagCorrection","true") == true) {
double LAG_CHECK_GRACE_PERIOD = 15;
//printf("#4 Server slot got currentFrameCount = %d\n",currentFrameCount);
if(this->serverInterface->getGameStartTime() > 0 &&
difftime((long int)time(NULL),this->serverInterface->getGameStartTime()) >= LAG_CHECK_GRACE_PERIOD &&
difftime((long int)time(NULL),this->getConnectedTime()) >= LAG_CHECK_GRACE_PERIOD) {
@ -1354,9 +1368,14 @@ void ConnectionSlot::update(bool checkForNewClients,int lockedSlotIndex) {
}
}
}
//printf("#5 Server slot got currentFrameCount = %d\n",currentFrameCount);
}
//printf("#5a Server slot got currentFrameCount = %d\n",currentFrameCount);
}
//printf("#6 Server slot got currentFrameCount = %d\n",currentFrameCount);
if(waitedForLaggingClient == true) {
printf("*TESTING*: FINISHED Waiting for lagging client playerIndex = %d [%s]\n",playerIndex,name.c_str());
}
@ -1365,6 +1384,8 @@ void ConnectionSlot::update(bool checkForNewClients,int lockedSlotIndex) {
validateConnection();
//printf("#7 Server slot got currentFrameCount = %d\n",currentFrameCount);
//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
}
else {
@ -1389,6 +1410,7 @@ void ConnectionSlot::update(bool checkForNewClients,int lockedSlotIndex) {
//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
}
//printf("#8 Server slot got currentFrameCount = %d\n",currentFrameCount);
//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
}
@ -1586,11 +1608,19 @@ void ConnectionSlot::deleteSocket() {
bool ConnectionSlot::hasDataToRead() {
bool result = false;
//printf("==> #1 Slot hasDataToRead()\n");
MutexSafeWrapper safeMutexSlot(mutexSocket,CODE_AT_LINE);
//printf("==> #2 Slot hasDataToRead()\n");
if(socket != NULL && socket->hasDataToRead() == true) {
result = true;
}
//printf("==> #3 Slot hasDataToRead()\n");
return result;
}

View File

@ -954,7 +954,7 @@ void ServerInterface::checkForCompletedClients(std::map<int,bool> & mapSlotSigna
//printf("===> IN slot %d - About to checkForCompletedClients\n",i);
ConnectionSlot* connectionSlot = slots[i];
if(connectionSlot != NULL && connectionSlot->isConnected() == true &&
if(connectionSlot != NULL && connectionSlot->hasValidSocketId() == true &&
mapSlotSignalledList[i] == true &&
connectionSlot->getJoinGameInProgress() == false &&
slotsCompleted.find(i) == slotsCompleted.end()) {
@ -1016,7 +1016,7 @@ void ServerInterface::checkForLaggingClients(std::map<int,bool> &mapSlotSignalle
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(slotAccessorMutexes[i],CODE_AT_LINE_X(i));
ConnectionSlot* connectionSlot = slots[i];
if(connectionSlot != NULL && connectionSlot->isConnected() == true &&
if(connectionSlot != NULL && connectionSlot->hasValidSocketId() == true &&
mapSlotSignalledList[i] == true &&
slotsCompleted.find(i) == slotsCompleted.end()) {
try {
@ -1345,6 +1345,8 @@ void ServerInterface::update() {
socketTriggeredList.empty() == false) {
//printf("\nServerInterface::update -- E\n");
//printf("START Server update #1\n");
std::map<int,ConnectionSlotEvent> eventList;
bool hasData = Socket::hasDataToRead(socketTriggeredList);
@ -1360,6 +1362,8 @@ void ServerInterface::update() {
//if(gameHasBeenInitiated == false || hasData == true || this->getAllowInGameConnections() == true) {
if(gameHasBeenInitiated == false || hasData == true) {
//printf("START Server update #2\n");
std::map<int,bool> mapSlotSignalledList;
// Step #1 tell all connection slot worker threads to receive socket data
@ -1369,7 +1373,12 @@ void ServerInterface::update() {
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
if(miniDebugPerf && chrono.getMillis() > 10) printf("In [%s::%s Line: %d] took " MG_I64_SPECIFIER " msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
//printf("START Server update #2\n");
if(gameHasBeenInitiated == false || hasData == true) {
//printf("START Server update #3\n");
// Step #2 check all connection slot worker threads for completed status
checkForCompletedClients(mapSlotSignalledList,errorMsgList, eventList);
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ============ Step #3\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
@ -1377,6 +1386,8 @@ void ServerInterface::update() {
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
if(miniDebugPerf && chrono.getMillis() > 10) printf("In [%s::%s Line: %d] took " MG_I64_SPECIFIER " msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
//printf("START Server update #4\n");
//printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
// Step #3 check clients for any lagging scenarios and try to deal with them
checkForLaggingClients(mapSlotSignalledList, eventList, socketTriggeredList,errorMsgList);
@ -1385,6 +1396,8 @@ void ServerInterface::update() {
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
if(miniDebugPerf && chrono.getMillis() > 10) printf("In [%s::%s Line: %d] took " MG_I64_SPECIFIER " msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
//printf("START Server update #5\n");
//printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
// Step #4 dispatch network commands to the pending list so that they are done in proper order
executeNetworkCommandsFromClients();
@ -1393,6 +1406,8 @@ void ServerInterface::update() {
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
if(miniDebugPerf && chrono.getMillis() > 10) printf("In [%s::%s Line: %d] took " MG_I64_SPECIFIER " msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
//printf("START Server update #6\n");
//printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
// Step #5 dispatch pending chat messages
dispatchPendingChatMessages(errorMsgList);
@ -1402,25 +1417,34 @@ void ServerInterface::update() {
dispatchPendingUnMarkCellMessages(errorMsgList);
dispatchPendingHighlightCellMessages(errorMsgList);
//printf("START Server update #7\n");
}
else if(gameHasBeenInitiated == true &&
difftime((long int)time(NULL),lastGlobalLagCheckTime) >= LAG_CHECK_GRACE_PERIOD) {
//printf("Skip network data process because hasData == false\n");
//printf("START Server update #8\n");
std::map<int,bool> mapSlotSignalledList;
checkForLaggingClients(mapSlotSignalledList, eventList, socketTriggeredList,errorMsgList);
}
//printf("START Server update #9\n");
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
if(miniDebugPerf && chrono.getMillis() > 10) printf("In [%s::%s Line: %d] took " MG_I64_SPECIFIER " msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
}
else if(gameHasBeenInitiated == true &&
difftime((long int)time(NULL),lastGlobalLagCheckTime) >= LAG_CHECK_GRACE_PERIOD) {
//printf("\nServerInterface::update -- E1\n");
//printf("START Server update #10\n");
std::map<int,bool> mapSlotSignalledList;
checkForLaggingClients(mapSlotSignalledList, eventList, socketTriggeredList,errorMsgList);
}
//printf("START Server update #11\n");
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
if(miniDebugPerf && chrono.getMillis() > 10) printf("In [%s::%s Line: %d] took " MG_I64_SPECIFIER " msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
}
@ -1428,12 +1452,16 @@ void ServerInterface::update() {
difftime((long int)time(NULL),lastGlobalLagCheckTime) >= LAG_CHECK_GRACE_PERIOD) {
//printf("\nServerInterface::update -- F\n");
//printf("START Server update #12\n");
std::map<int,ConnectionSlotEvent> eventList;
std::map<int,bool> mapSlotSignalledList;
checkForLaggingClients(mapSlotSignalledList, eventList, socketTriggeredList,errorMsgList);
}
//printf("START Server update #13\n");
if(miniDebugPerf && chrono.getMillis() > 10) printf("In [%s::%s Line: %d] took " MG_I64_SPECIFIER " msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
// Check if we need to switch masterserver admin to a new player because original admin disconnected
@ -1474,9 +1502,13 @@ void ServerInterface::update() {
}
//printf("\nServerInterface::update -- G\n");
//printf("START Server update #14\n");
if(miniDebugPerf && chrono.getMillis() > 10) printf("In [%s::%s Line: %d] took " MG_I64_SPECIFIER " msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
checkListenerSlots();
//printf("START Server update #15\n");
if(miniDebugPerf && chrono.getMillis() > 10) printf("In [%s::%s Line: %d] took " MG_I64_SPECIFIER " msecs\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
}
catch(const exception &ex) {
@ -1531,7 +1563,11 @@ void ServerInterface::updateKeyframe(int frameCount) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] build command list took %lld msecs, networkMessageCommandList.getCommandCount() = %d, frameCount = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis(),networkMessageCommandList.getCommandCount(),frameCount);
//broadcast commands
//printf("START Server send currentFrameCount = %d\n",currentFrameCount);
broadcastMessage(&networkMessageCommandList);
//printf("END Server send currentFrameCount = %d\n",currentFrameCount);
}
catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());

View File

@ -36,6 +36,10 @@ using namespace std;
using namespace Shared::PlatformCommon;
#endif
namespace Shared { namespace PlatformCommon {
class Chrono;
}};
namespace Shared { namespace Platform {
class Mutex;
@ -86,6 +90,9 @@ private:
string deleteownerId;
SDL_mutex* mutexAccessor;
string lastownerId;
Shared::PlatformCommon::Chrono *chronoPerf;
public:
Mutex(string ownerId="");
@ -139,6 +146,9 @@ public:
#endif
this->mutex->p();
if(this->mutex != NULL) {
this->mutex->setOwnerId(ownerId);
}
#ifdef DEBUG_PERFORMANCE_MUTEXES
if(chrono.getMillis() > 5) printf("In [%s::%s Line: %d] MUTEX LOCK took msecs: %lld, this->mutex->getRefCount() = %d ownerId [%s]\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis(),this->mutex->getRefCount(),ownerId.c_str());

View File

@ -141,6 +141,7 @@ Mutex::Mutex(string ownerId) {
SDLMutexSafeWrapper safeMutex(&mutexAccessor);
refCount=0;
this->ownerId = ownerId;
this->lastownerId = "";
mutex = SDL_CreateMutex();
assert(mutex != NULL);
if(mutex == NULL) {
@ -149,6 +150,8 @@ Mutex::Mutex(string ownerId) {
throw megaglest_runtime_error(szBuf);
}
deleteownerId = "";
//chronoPerf = new Chrono();
}
Mutex::~Mutex() {
@ -165,6 +168,9 @@ Mutex::~Mutex() {
throw megaglest_runtime_error(szBuf);
}
//delete chronoPerf;
//chronoPerf = NULL;
if(mutex != NULL) {
deleteownerId = ownerId;
SDL_DestroyMutex(mutex);
@ -178,8 +184,16 @@ void Mutex::p() {
snprintf(szBuf,1023,"In [%s::%s Line: %d] mutex == NULL refCount = %d owner [%s] deleteownerId [%s]",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,refCount,ownerId.c_str(),deleteownerId.c_str());
throw megaglest_runtime_error(szBuf);
}
//Chrono chrono;
//chrono.start();
SDL_mutexP(mutex);
refCount++;
//if(chrono.getMillis() > 2000) {
// printf("Last ownerid: [%s]\n",lastownerId.c_str());
//}
//chronoPerf->start();
}
void Mutex::v() {
@ -189,6 +203,11 @@ void Mutex::v() {
throw megaglest_runtime_error(szBuf);
}
refCount--;
lastownerId = ownerId;
//if(chronoPerf->getMillis() > 2000) {
// lastownerId = PlatformExceptionHandler::getStackTrace();
//}
SDL_mutexV(mutex);
}