Multithreading not Crashing? How come? -
Gamer_Z - 29.01.2012
Well I was interested in optimizing various things in my plugins, and the best way to save time is .. mulithreading in this world.. However as we know SA-MP doesn't 'support' multithreading..
Anyways as I'm an complete idiot and don't listen to things like "This won't work blablabla", I always need to see it myself.. Now I am very surprised by the actual results of my test...
I wrote a simple plugin which does something in a thread, far away from sa-mp's main loop..
And I excpected it to crash my server soon or late; No it did not - I am asking now WHY?
If this is possible I will start using this to optimize my driftpointscounter plugin and GPS OnPlayerClosestNodeIDChange lol!
Anyway here is some code:
pawn Code:
//filterscript
native Float:GetSpeed(playerid);//our plugin function
public OnPlayerUpdate(playerid)
{
new Float:spd[3];
if(IsPlayerInAnyVehicle(playerid))
{
GetVehicleVelocity(GetPlayerVehicleID(playerid),spd[0],spd[1],spd[2]);//we make sure we use the functions here too, AND in the plugin thread which is not sychronized to sa-mp, just to make it more 'crashable'
}
else
{
GetPlayerVelocity(playerid,spd[0],spd[1],spd[2]);
}
new Float:SPEED = GetSpeed(playerid);
SendClientMessage(playerid,-1,sprintf("Your speed: %.2f | %.2f",SPEED,floatsqroot((spd[0]*spd[0])+(spd[1]*spd[1])+(spd[2]*spd[2]))));
return 1;
}
the plugin code can be downloaded here:
http://gpb.googlecode.com/files/ThreadTest_R100.zip
(If you don't want to download the package or are too lazy to open it, here I give the code too)
pawn Code:
#ifdef OS_WINDOWS
void Thread::BackgroundCalculator( void *unused )
#else
void *Thread::BackgroundCalculator( void *unused )
#endif
{
float X;
float Y;
float Z;
while( true )
{
if(ENABLED == false)
{
continue;
}
for(int i = 0; i < MAX_PLAYERS; ++i)
{
if(IsPlayerConnected(i) == false)
{
speed[i] = -1.0f;
continue;
}
if(IsPlayerInAnyVehicle(i) == true)
{
GetVehicleVelocity(GetPlayerVehicleID(i),&X,&Y,&Z);
}
else
{
GetPlayerVelocity(i,&X,&Y,&Z);
}
speed[i] = sqrt(X*X+Y*Y+Z*Z);
}
SLEEP(30);
}
EXIT_THREAD();//should be never reached..
}
static cell AMX_NATIVE_CALL n_GetSpeed( AMX* amx, cell* params )
{
return amx_ftoc(speed[params[1]]);
}
try to compile it yourself and run, It really works lol.
I know SET's could have crashed, and probably would but I see GET's work totally fine in threads.
It would be really fine if anyone can explain why, and if it is really safe to thread GET's?
Edit:
Ah forgot to give the sprintf code, it can be found in the usefull snippets thread. Credits go to their respective authors and copyrights holders.
pawn Code:
/*
sprintf()
PAWNO:
native sprintf(const format[], {Float,_}:...);
*/
#if !defined ____sprintf
#define ____sprintf
#if !defined SPRINTF_MAX_STRING
#define SPRINTF_MAX_STRING 4092
#endif
#if !defined SPRINTF_DEBUG_STRING
#define SPRINTF_DEBUG_STRING "[sprintf debug] '%s'[%d]"
#endif
#assert SPRINTF_MAX_STRING > 2
new
_s@T[SPRINTF_MAX_STRING];
#if defined SPRINTF_DEBUG
new const _s@V[] = SPRINTF_DEBUG_STRING;
#define sprintf(%1) (format(_s@T, SPRINTF_MAX_STRING, %1), printf(_s@V, _s@T, strlen(_s@T)), _s@T)
#else
#define sprintf(%1) (format(_s@T, SPRINTF_MAX_STRING, %1), _s@T)
#endif
#endif