03.12.2014, 22:26
(
Последний раз редактировалось Jay_; 08.12.2014 в 10:43.
)
Introduction
Multi-threaded programming is an extremely difficult pattern that a lot of developers in the Software Engineering world struggle with.
Whilst PAWN doesn't introduce a lot of the complexities present in most other languages out there, it's still difficult to keep your code neat and organised when threading your MySQL queries as you have to break your code up into separate functions and callbacks.
This is a basic tutorial on how you can improve your code structure by using y_inline, a third-party YSI library that's supported by the MySQL plugin.
I'm writing this because I haven't seen any scripts that use this so I'm assuming not many people know about it.
Prerequisites
MySQL plugin version R33 onwards and y_inline.
The Tutorial
Here's an example of how a threaded query might look using the standard syntax of the MySQL plugins API:
This isn't ideal - we're sending the query request from one function and receiving the data from another!
This is messy and horrible to work with. Given, it doesn't look too bad in this example but when dealing with complex systems it can become really hacky and ugly.
In an ideal world, we want to be able to deal with the data returned from the threaded query in the same function - directly under the mysql_query call.
Unfortunately, that's not possible to do. But what we can do is embed our OnAccountDataReceived callback into the construct function using y_inline, so that our mysql_tquery function call and data received callback are all in the same function!
1. Tell the MySQL plugin that we're going to be using y_inline
First of all we need to tell the plugins include script that we are going to be using y_inline. This is really easy to do - simply add an include statement for YSI before you include your MySQL inc. You can do this like so:
2. Implement the code!
The following piece of code is a threaded MySQL query which makes use of y_inline - the query is called within the same (parent) function in which the threaded callback returns the data.
And that's it! Simple eh, and it looks much better.
The call to mysql_tquery has changed. The function is called mysql_tquery_inline, and the third argument for the callback no longer accepts a string - the syntax is:
Note:
The inline child function must be defined before the call to mysql_tquery, as in the above code. In an ideal world it would be the other way round but this is just the way y_inline works unfortunately.
More information: https://sampforum.blast.hk/showthread.php?tid=295049
Multi-threaded programming is an extremely difficult pattern that a lot of developers in the Software Engineering world struggle with.
Whilst PAWN doesn't introduce a lot of the complexities present in most other languages out there, it's still difficult to keep your code neat and organised when threading your MySQL queries as you have to break your code up into separate functions and callbacks.
This is a basic tutorial on how you can improve your code structure by using y_inline, a third-party YSI library that's supported by the MySQL plugin.
I'm writing this because I haven't seen any scripts that use this so I'm assuming not many people know about it.
Prerequisites
MySQL plugin version R33 onwards and y_inline.
The Tutorial
Here's an example of how a threaded query might look using the standard syntax of the MySQL plugins API:
pawn Код:
// Initiaited when the player connects to the server.
construct(playerid) {
new query[256];
mysql_format(getMySQLHandle(), query, sizeof(query), "SELECT * FROM %s WHERE PlayerName = '%e' LIMIT 1",
getMySQLTableName(), ReturnPlayerName(playerid));
mysql_tquery(getMySQLHandle(), query, "OnAccountDataReceived", "i", playerid);
}
forward OnAccountDataReceived(playerid);
public OnAccountDataReceived(playerid) {
new
rows,
fields,
fieldString[128];
cache_get_data(rows, fields, getMySQLHandle());
if(rows > 0) {
isThisPlayerRegistered[playerid] = true;
// retrieve the primary key for the user id
setUserID(playerid, cache_get_field_content_int(0, "ID"));
// Retrieve the encrypted password for validation later
cache_get_field_content(0, "Password", fieldString);
setEncryptedPassword(playerid, fieldString);
} else {
isThisPlayerRegistered[playerid] = false;
}
}
This is messy and horrible to work with. Given, it doesn't look too bad in this example but when dealing with complex systems it can become really hacky and ugly.
In an ideal world, we want to be able to deal with the data returned from the threaded query in the same function - directly under the mysql_query call.
Unfortunately, that's not possible to do. But what we can do is embed our OnAccountDataReceived callback into the construct function using y_inline, so that our mysql_tquery function call and data received callback are all in the same function!
1. Tell the MySQL plugin that we're going to be using y_inline
First of all we need to tell the plugins include script that we are going to be using y_inline. This is really easy to do - simply add an include statement for YSI before you include your MySQL inc. You can do this like so:
pawn Код:
#include "YSI/y_inline.inc"
The following piece of code is a threaded MySQL query which makes use of y_inline - the query is called within the same (parent) function in which the threaded callback returns the data.
pawn Код:
// Initiaited when the player connects to the server.
construct(playerid)
{
new query[256];
mysql_format(getMySQLHandle(), query, sizeof(query), "SELECT * FROM %s WHERE PlayerName = '%e' LIMIT 1",
getMySQLTableName(), ReturnPlayerName(playerid));
inline OnAccountDataReceived()
{
new
rows,
fields,
fieldString[128],
fieldInt;
cache_get_data(rows, fields, getMySQLHandle());
if(rows > 0) {
isPlayerRegistered[playerid] = true;
// Set the user ID, i.e. the primary key
setUserID(playerid, cache_get_field_content_int(0, "ID"));
// Set the encrypted password
cache_get_field_content(0, "Password", fieldString);
setEncryptedPassword(playerid, fieldString);
}
else {
isPlayerRegistered[playerid] = false;
}
}
mysql_tquery_inline(getMySQLHandle(), query, using inline OnAccountDataReceived);
}
The call to mysql_tquery has changed. The function is called mysql_tquery_inline, and the third argument for the callback no longer accepts a string - the syntax is:
Код:
using inline [function name]
The inline child function must be defined before the call to mysql_tquery, as in the above code. In an ideal world it would be the other way round but this is just the way y_inline works unfortunately.
More information: https://sampforum.blast.hk/showthread.php?tid=295049