SA-MP Forums Archive
Multithreading not Crashing? How come? - Printable Version

+- SA-MP Forums Archive (https://sampforum.blast.hk)
+-- Forum: SA-MP Scripting and Plugins (https://sampforum.blast.hk/forumdisplay.php?fid=8)
+--- Forum: Plugin Development (https://sampforum.blast.hk/forumdisplay.php?fid=18)
+--- Thread: Multithreading not Crashing? How come? (/showthread.php?tid=314452)



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