29.01.2012, 20:46
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:
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)
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.
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;
}
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]]);
}
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