|
Edit: Actually, I just looked at the code to see what LockThread does and the simple answer is nothing! In fact worse than nothing - pointless loops I can't find the use of wasting time... If the code did what you think it does (which it doesn't) then it would create a mutex, but not actually turn it on, which makes the whole process pointless.
|
boost::mutex::scoped_lock * lock = new boost::mutex::scoped_lock( (* i).second->mutex ) ;
|
well we can't do much about the choice of the sa-mp devs, they've chosen pawn as the scripting lang and you can't do much about it so I think we have to improve it on our own, and multi architecture is a big improvement if we get it to work because nowadays gamemodes ARE NOT 'light'! many code is processed each second , and in most scenarios the code can be processed safely in threads (like updating player textdraw information, instead of looping throu all players and then go on with our gamemode!).
But can anyone give me some examples? and does this really improve the speed ? :P my question still remains: how the heck can you run a callback in a separate thread ? :O |
|
sure knew about the dangers of var locks etc but for example to stream data to a website whle the server is running? would be great to not lag the server with data sending/recieving to/from the website. But okay so this plugin doesn't work or what?
|
|
sure knew about the dangers of var locks etc but for example to stream data to a website whle the server is running? would be great to not lag the server with data sending/recieving to/from the website. But okay so this plugin doesn't work or what?
|
|
You do realize we have multiple mysql plugins that offer (safe) threading features? I strongly advise you look into them instead.
|
|
The issue is if you are trying to GET and SET at the same time - and I mean EXACTLY the same time. You can end up reading data in a corrupt state because it isn't all correctly written yet.
|
|
If the threads never communicate ever then that should be OK. But don't forget that the PAWN natives aren't thread safe either. If you are using a text draw for your cursor for example, and your main thread is creating TDs too, you could end up creating two at the same time and, due to the way empty slots are found and assigned, you could get two with the same ID, and then I'm not sure what would happen (which is the main problem with threading).
|
|
No, it's not that simple - I'm not even sure if the raknet library compiled in SA:MP is thread-safe (it CAN be, but you can compile it without thread safety for speed). This means that even if you do use entirely separate textdraws in separate threads, if raknet tries to send the data for the two textdraws (or indeed tries to send any data for anything at the same time as any data for anything else) it will entirely screw up (of course, the SA:MP server MAY be compiled with that one part multi-threaded - only Kye could answer that).
The bottom line is multi-threaded programming is HARD, not just a little tricky as you seem to be thinking, but VERY VERY HARD. Add to this the fact that, despite me telling the author several times, the lock thread function does nothing and you have serious issues. It is possible to write PAWN-based critical section locks using, for example: http://en.wikipedia.org/wiki/Dekker%27s_algorithm or: http://en.wikipedia.org/wiki/Peterson%27s_algorithm However these only work for two threads, not many, and as most PAWN natives are not thread safe you may need to put critical sections around almost everything, making threads actually WORSE than no threads. |
#if defined USE_MULTI_THREAD
enum gTpos
{
Float:X,
Float:Y,
Float:Z,
Float:Angle1,
Float:Angle2,
Points,
Timer
}
new GlobalPos[MAX_PLAYERS][gTpos];// USED ONLY IN THE THREAD except Timer and Points!
forward DriftingUpdate(threadid);
public DriftingUpdate(threadid)
{
for(new playerid; playerid < MAX_PLAYERS; playerid++)
{
if(IsPlayerConnected(playerid) && GetPlayerState(playerid) == PLAYER_STATE_DRIVER)
{
new PlayerVehicleID = GetPlayerVehicleID(playerid);
new PlayerVehicleModelID = GetVehicleModel(PlayerVehicleID);
new Float:floatdata[11];
//switch(PlayerVehicleModelID)
//{
// case 443,448,461 .. 463,521 .. 523,581,586,481,509,510,430,446,452 .. 454,472,473,484,493,595,417,425,447,465,469,487,488,497,501,548,563,406,444,556,557,573,460,464,476,511 .. 513,519,520,539,553,577,592,593,471:
// {
new Float:SpeedX, Float:SpeedY, Float:SpeedZ;
GetVehicleVelocity(PlayerVehicleID, SpeedX, SpeedY, SpeedZ);
floatdata[10] = floatmul(floatsqroot((floatpower(SpeedX, 2.0)+floatpower(SpeedY, 2.0)+floatpower(SpeedZ, 2.0))), 274.0);
GetVehicleZAngle(PlayerVehicleID, GlobalPos[playerid][Angle1]);
GetPlayerPos(playerid,floatdata[4],floatdata[5],floatdata[6]);
floatdata[1] = floatsqroot(floatpower(floatsub(floatdata[4],GlobalPos[playerid][X]),2)+floatpower(floatsub(floatdata[5],GlobalPos[playerid][Y]),2));
GetVehicleZAngle(PlayerVehicleID, floatdata[3]);
if(floatdata[4]>GlobalPos[playerid][X]){floatdata[7]=floatdata[4]-GlobalPos[playerid][X];}else{floatdata[7]=GlobalPos[playerid][X]-floatdata[4];}
if(floatdata[5]>GlobalPos[playerid][Y]){floatdata[8]=floatdata[5]-GlobalPos[playerid][Y];}else{floatdata[8]=GlobalPos[playerid][Y]-floatdata[5];}
if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //1
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = floatsub(floatsub(floatadd(floatdata[0], 90), floatmul(floatdata[0], 2)), -90.0);
}
if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //2
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = floatsub(floatadd(floatdata[0], 180), 180.0);
}
if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //3
floatdata[0] = acos(floatdata[8]/floatdata[1]);
floatdata[9] = floatsub(floatadd(floatdata[0], 360), floatmul(floatdata[0], 2));
}
if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //4
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = floatadd(floatdata[0], 180);
}
if(floatdata[9] == 0.0)
{
GlobalPos[playerid][Angle2] = floatdata[3];
} else {
GlobalPos[playerid][Angle2] = floatdata[9];
}
new Float:angle = floatabs(GlobalPos[playerid][Angle1]-GlobalPos[playerid][Angle2]);
if(90.0 > angle > 12.5 && floatdata[10] > 10.0)
{
if(GlobalPos[playerid][Timer] != -1)KillTimer(GlobalPos[playerid][Timer]);
GlobalPos[playerid][Timer] = -1;
GlobalPos[playerid][Points] += floatround(angle * floatdata[10] / 3);
GlobalPos[playerid][Timer] = SetTimerEx("DriftCancel", 2000, 0, "d", playerid);
}
//}
//}
GetPlayerPos(playerid,GlobalPos[playerid][X],GlobalPos[playerid][Y],GlobalPos[playerid][Z]);
}
}
SleepThread(100);
}
forward DriftCancel(playerid);
public DriftCancel(playerid)
{
//do something with the points
GameTextFormatForPlayer(playerid, "Drift ended with %d points!", 1500, 1, GlobalPos[playerid][Points]);
//
GlobalPos[playerid][Timer] = (-1);
GlobalPos[playerid][Points] = 0;
return 1;
}
#endif
#if defined USE_MULTI_THREAD
enum gTpos
{
Float:X,
Float:Y,
Float:Z,
Float:Angle1,
Float:Angle2,
Points,
Timer
}
new Text:PlayerTextDraw[MAX_PLAYERS];
forward DU_OnGameModeInit();
public DU_OnGameModeInit()
{
for(new x=0;x<MAX_PLAYERS;x++)
{
PlayerTextDraw[x] = Text:TextDrawCreate(7.0, 300.0, " ");
TextDrawColor(PlayerTextDraw[x], 0x3355FFFF);
TextDrawFont(PlayerTextDraw[x], 1);
TextDrawSetShadow(PlayerTextDraw[x], 0);
TextDrawSetOutline(PlayerTextDraw[x], 1);
TextDrawAlignment(PlayerTextDraw[x], 0);
TextDrawLetterSize(PlayerTextDraw[x], 0.4, 0.8);
}
return 1;
}
new GlobalPos[MAX_PLAYERS][gTpos];// USED ONLY IN THE THREAD , no exceptions!
forward DriftingUpdate(threadid);
public DriftingUpdate(threadid)
{
for(new playerid; playerid < MAX_PLAYERS; playerid++)
{
if(IsPlayerConnected(playerid) && GetPlayerState(playerid) == PLAYER_STATE_DRIVER)
{
new PlayerVehicleID = GetPlayerVehicleID(playerid);
//new PlayerVehicleModelID = GetVehicleModel(PlayerVehicleID);
new Float:floatdata[11];
//switch(PlayerVehicleModelID)
//{
// case 443,448,461 .. 463,521 .. 523,581,586,481,509,510,430,446,452 .. 454,472,473,484,493,595,417,425,447,465,469,487,488,497,501,548,563,406,444,556,557,573,460,464,476,511 .. 513,519,520,539,553,577,592,593,471:
// {
new Float:SpeedX, Float:SpeedY, Float:SpeedZ;
GetVehicleVelocity(PlayerVehicleID, SpeedX, SpeedY, SpeedZ);
floatdata[10] = floatmul(floatsqroot((floatpower(SpeedX, 2.0)+floatpower(SpeedY, 2.0)+floatpower(SpeedZ, 2.0))), 274.0);
GetVehicleZAngle(PlayerVehicleID, GlobalPos[playerid][Angle1]);
GetPlayerPos(playerid,floatdata[4],floatdata[5],floatdata[6]);
floatdata[1] = floatsqroot(floatpower(floatsub(floatdata[4],GlobalPos[playerid][X]),2)+floatpower(floatsub(floatdata[5],GlobalPos[playerid][Y]),2));
GetVehicleZAngle(PlayerVehicleID, floatdata[3]);
if(floatdata[4]>GlobalPos[playerid][X]){floatdata[7]=floatdata[4]-GlobalPos[playerid][X];}else{floatdata[7]=GlobalPos[playerid][X]-floatdata[4];}
if(floatdata[5]>GlobalPos[playerid][Y]){floatdata[8]=floatdata[5]-GlobalPos[playerid][Y];}else{floatdata[8]=GlobalPos[playerid][Y]-floatdata[5];}
if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //1
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = floatsub(floatsub(floatadd(floatdata[0], 90), floatmul(floatdata[0], 2)), -90.0);
}
if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //2
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = floatsub(floatadd(floatdata[0], 180), 180.0);
}
if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //3
floatdata[0] = acos(floatdata[8]/floatdata[1]);
floatdata[9] = floatsub(floatadd(floatdata[0], 360), floatmul(floatdata[0], 2));
}
if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //4
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = floatadd(floatdata[0], 180);
}
if(floatdata[9] == 0.0)
{
GlobalPos[playerid][Angle2] = floatdata[3];
} else {
GlobalPos[playerid][Angle2] = floatdata[9];
}
new Float:angle = floatabs(GlobalPos[playerid][Angle1]-GlobalPos[playerid][Angle2]);
if(90.0 > angle > 12.5 && floatdata[10] > 10.0)
{
if(GlobalPos[playerid][Timer] != -1)
{
new s[256];
format(s, 256, "~n~~n~~n~~w~_________________Drift!~n~___________________~p~Points: %d", GlobalPos[playerid][Points]);
TextDrawSetString(PlayerTextDraw[playerid], s);
}
else
{
TextDrawShowForPlayer(playerid,PlayerTextDraw[playerid]);
GameTextForPlayer(playerid, "Drift started!", 500, 1);
}
GlobalPos[playerid][Points] += floatround(angle * floatdata[10] / 3);
GlobalPos[playerid][Timer] = 20;
}
else
{
if(GlobalPos[playerid][Timer] != -1)
{
GlobalPos[playerid][Timer]--;
if(GlobalPos[playerid][Timer] == -1)
{
TextDrawHideForPlayer(playerid,PlayerTextDraw[playerid]);
GameTextFormatForPlayer(playerid, "Drift ended with %d points!", 750, 1, GlobalPos[playerid][Points]);
GlobalPos[playerid][Points] = 0;
}
}
}
//}
//}
GetPlayerPos(playerid,GlobalPos[playerid][X],GlobalPos[playerid][Y],GlobalPos[playerid][Z]);
}
}
SleepThread(100);
}
#endif
forward DriftingUpdate(threadid);
public DriftingUpdate(threadid)
{
for(new playerid; playerid < MAX_PLAYERS; playerid++)
{
if(IsPlayerConnected(playerid) && GetPlayerState(playerid) == PLAYER_STATE_DRIVER)
{
new PlayerVehicleID = GetPlayerVehicleID(playerid);
//new PlayerVehicleModelID = GetVehicleModel(PlayerVehicleID);
new Float:floatdata[11];
//switch(PlayerVehicleModelID)
//{
// case 443,448,461 .. 463,521 .. 523,581,586,481,509,510,430,446,452 .. 454,472,473,484,493,595,417,425,447,465,469,487,488,497,501,548,563,406,444,556,557,573,460,464,476,511 .. 513,519,520,539,553,577,592,593,471:
// {
new Float:SpeedX, Float:SpeedY, Float:SpeedZ;
GetVehicleVelocity(PlayerVehicleID, SpeedX, SpeedY, SpeedZ);
floatdata[10] = floatmul(floatsqroot((floatpower(SpeedX, 2.0)+floatpower(SpeedY, 2.0)+floatpower(SpeedZ, 2.0))), 274.0);
GetVehicleZAngle(PlayerVehicleID, GlobalPos[playerid][Angle1]);
GetPlayerPos(playerid,floatdata[4],floatdata[5],floatdata[6]);
floatdata[1] = floatsqroot(floatpower(floatsub(floatdata[4],GlobalPos[playerid][X]),2)+floatpower(floatsub(floatdata[5],GlobalPos[playerid][Y]),2));
GetVehicleZAngle(PlayerVehicleID, floatdata[3]);
if(floatdata[4]>GlobalPos[playerid][X]){floatdata[7]=floatdata[4]-GlobalPos[playerid][X];}else{floatdata[7]=GlobalPos[playerid][X]-floatdata[4];}
if(floatdata[5]>GlobalPos[playerid][Y]){floatdata[8]=floatdata[5]-GlobalPos[playerid][Y];}else{floatdata[8]=GlobalPos[playerid][Y]-floatdata[5];}
if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //1
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = floatsub(floatsub(floatadd(floatdata[0], 90), floatmul(floatdata[0], 2)), -90.0);
}
if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //2
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = floatsub(floatadd(floatdata[0], 180), 180.0);
}
if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //3
floatdata[0] = acos(floatdata[8]/floatdata[1]);
floatdata[9] = floatsub(floatadd(floatdata[0], 360), floatmul(floatdata[0], 2));
}
if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //4
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = floatadd(floatdata[0], 180);
}
if(floatdata[9] == 0.0)
{
GlobalPos[playerid][Angle2] = floatdata[3];
} else {
GlobalPos[playerid][Angle2] = floatdata[9];
}
new Float:angle = floatabs(GlobalPos[playerid][Angle1]-GlobalPos[playerid][Angle2]);
if(90.0 > angle > 12.5 && floatdata[10] > 10.0)
{
if(GlobalPos[playerid][Timer] != -1)KillTimer(GlobalPos[playerid][Timer]);
else CallLocalFunction("OnDriftStart","i",playerid);
GlobalPos[playerid][Timer] = -1;
GlobalPos[playerid][Points] += floatround(angle * floatdata[10] / 3);
GlobalPos[playerid][Timer] = SetTimerEx("OnDriftEnd", 2000, 0, "d", playerid);
}
//}
//}
GetPlayerPos(playerid,GlobalPos[playerid][X],GlobalPos[playerid][Y],GlobalPos[playerid][Z]);
}
}
SleepThread(100);
}
forward OnDriftStart(playerid);
public OnDriftStart(playerid)
{
GameTextForPlayer(playerid, "Drift started!", 750, 1);
return 1;
}
forward OnDriftEnd(playerid);
public OnDriftEnd(playerid)
{
//do something with the points
GameTextFormatForPlayer(playerid, "Drift ended with %d points!", 750, 1, GlobalPos[playerid][Points]);
//
GlobalPos[playerid][Timer] = (-1);
GlobalPos[playerid][Points] = 0;
return 1;
}
forward DriftingUpdate(threadid);
public DriftingUpdate(threadid)
{
for(new playerid; playerid < MAX_PLAYERS; playerid++)
{
if(IsPlayerConnected(playerid) && GetPlayerState(playerid) == PLAYER_STATE_DRIVER)
{
new PlayerVehicleID = GetPlayerVehicleID(playerid);
//new PlayerVehicleModelID = GetVehicleModel(PlayerVehicleID);
new Float:floatdata[11];
//switch(PlayerVehicleModelID)
//{
// case 443,448,461 .. 463,521 .. 523,581,586,481,509,510,430,446,452 .. 454,472,473,484,493,595,417,425,447,465,469,487,488,497,501,548,563,406,444,556,557,573,460,464,476,511 .. 513,519,520,539,553,577,592,593,471:
// {
new Float:SpeedX, Float:SpeedY, Float:SpeedZ;
GetVehicleVelocity(PlayerVehicleID, SpeedX, SpeedY, SpeedZ);
floatdata[10] = floatmul(floatsqroot((floatpower(SpeedX, 2.0)+floatpower(SpeedY, 2.0)+floatpower(SpeedZ, 2.0))), 274.0);
GetVehicleZAngle(PlayerVehicleID, GlobalPos[playerid][Angle1]);
GetPlayerPos(playerid,floatdata[4],floatdata[5],floatdata[6]);
floatdata[1] = floatsqroot(floatpower(floatsub(floatdata[4],GlobalPos[playerid][X]),2)+floatpower(floatsub(floatdata[5],GlobalPos[playerid][Y]),2));
GetVehicleZAngle(PlayerVehicleID, floatdata[3]);
if(floatdata[4]>GlobalPos[playerid][X]){floatdata[7]=floatdata[4]-GlobalPos[playerid][X];}else{floatdata[7]=GlobalPos[playerid][X]-floatdata[4];}
if(floatdata[5]>GlobalPos[playerid][Y]){floatdata[8]=floatdata[5]-GlobalPos[playerid][Y];}else{floatdata[8]=GlobalPos[playerid][Y]-floatdata[5];}
if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //1
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = floatsub(floatsub(floatadd(floatdata[0], 90), floatmul(floatdata[0], 2)), -90.0);
}
if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]>floatdata[4]){ //2
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = floatsub(floatadd(floatdata[0], 180), 180.0);
}
if(GlobalPos[playerid][Y]<floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //3
floatdata[0] = acos(floatdata[8]/floatdata[1]);
floatdata[9] = floatsub(floatadd(floatdata[0], 360), floatmul(floatdata[0], 2));
}
if(GlobalPos[playerid][Y]>floatdata[5] && GlobalPos[playerid][X]<floatdata[4]){ //4
floatdata[0] = asin(floatdata[7]/floatdata[1]);
floatdata[9] = floatadd(floatdata[0], 180);
}
if(floatdata[9] == 0.0)
{
GlobalPos[playerid][Angle2] = floatdata[3];
} else {
GlobalPos[playerid][Angle2] = floatdata[9];
}
new Float:angle = floatabs(GlobalPos[playerid][Angle1]-GlobalPos[playerid][Angle2]);
if(90.0 > angle > 17.5 && floatdata[10] > 23.5)
{
GlobalPos[playerid][Points] += floatround(angle * floatdata[10] / 83);
if(GlobalPos[playerid][Timer] != -1)
{
GlobalPos[playerid][Combo] += 1;
new s[256];
format(s, 256, "~n~~n~~n~~w~_________________Drift!~n~___________________~r~Points:~w~_%d~n~___________________~r~Combo:~w~_x%d!",GlobalPos[playerid][Points],floatround(GlobalPos[playerid][Combo]/30,floatround_floor)+1);
TextDrawSetString(PlayerTextDraw[playerid], s);
}
else
{
TextDrawShowForPlayer(playerid,PlayerTextDraw[playerid]);
//GameTextForPlayer(playerid, "Drift started!", 500, 1);
}
GlobalPos[playerid][Timer] = 20;
}
else
{
if(GlobalPos[playerid][Timer] != -1)
{
GlobalPos[playerid][Timer]--;
if(GlobalPos[playerid][Timer] == -1)
{
TextDrawHideForPlayer(playerid,PlayerTextDraw[playerid]);
//GameTextFormatForPlayer(playerid, "Drift ended with %d points!", 750, 1, GlobalPos[playerid][Points]);
GlobalPos[playerid][Combo] = 0;
GlobalPos[playerid][Points] = 0;
}
}
}
//}
//}
GetPlayerPos(playerid,GlobalPos[playerid][X],GlobalPos[playerid][Y],GlobalPos[playerid][Z]);
}
}
SleepThread(100);
}
SleepThread(100);
)|
Hmm Frosha , I'm Polish, I don't speak or read Russian but maybe if I get you vodka we won't have any communication issues, can sit down and talk a bit ^^
|