How to make a callback?
#1

Hi,

I'm wondering, how to make a callback. No, i don't want a fake callback called by a timer in a Pawn script, i mean a real callback, that my plugin calls in a Pawn script.

Thanks already.
Reply
#2

Go Download the source to the my Plugin, it has 2 callbacks which arent threaded or used much in ScriptPlayer.
Reply
#3

Thanks, this worked:
Код:
int idx;
	
if (amx_FindPublic(amx, "OnSomething", &idx) == AMX_ERR_NONE)
  amx_Exec(amx, NULL, idx);
Reply
#4

Those are not "fake" callbacks. Polling the plugin on a timer in PAWN is the safest way to execute any AMX functions from the main thread. If you put that code in a thread of your own, it will simply crash the server.
Reply
#5

No it works fine i just tested.
Reply
#6

Quote:
Originally Posted by Incognito
Those are not "fake" callbacks. Polling the plugin on a timer in PAWN is the safest way to execute any AMX functions from the main thread. If you put that code in a thread of your own, it will simply crash the server.
As my mate said, we have tested (on Windows) in a thread created with pthread_create, from the pthread library. When the thread finish its work, it calls the the "OnSomething" callback in a Pawn script, and it works without any crashes or bugs, yet.

Could you please explain more how to crash it? I'm interested because you said "it WILL crash" and not "it MAY crash".
Reply
#7

It will not crash every time, of course, but since the threads are not synchronized, it will at random.
Reply
#8

Ok, so if i understand correctly, it will not crash as long as i don't use/modify global variables in the threaded function?
Reply
#9

No, only the AMX functions included in the SDK.
Reply
#10

In my tests, it is not processor-intensive as long as the polling function is light. Realistically, it is not the preferred option, but it is the only working method I have come across. Interesting that you mention message queues, but I do not see how they can be opened since PAWN is single-threaded (how can PAWN be informed of their creation?). They also seem to be limited as to what they can copy (e.g., only raw bytes and not objects). Do you think you could you expand on their implementation or perhaps give an example?
Reply
#11

Okay, the message queue is created in the main thread and messages are sent to it from another thread. Simple enough, but perhaps I am still misunderstanding something—how can these messages be received without blocking the main thread?
Reply
#12

y_less, I beg you, make a small tutorial about that please Interesting, but i don't quite understand.
Reply
#13

http://files.uploadffs.com/81fac0_simplified_plugin.zip


Next time, SEARCH !
Reply
#14

Quote:
Originally Posted by fastblast
y_less, I beg you, make a small tutorial about that please Interesting, but i don't quite understand.
I do not fully understand either. Boost.Interprocess offers this kind of functionality (information here), but when the receiving function is put in the main thread (for testing purposes, I put it in Load), it expectedly blocks the thread until a message has been received. I am not sure if I am doing this correctly. A working example would be nice.

I think the only real way to resolve the thread issue is to put mutex locks on amx_Exec (and maybe similar functions), but I do not think this is even possible to do in the plugin. Until then, only workarounds like polling the plugin are feasible.
Reply
#15

Quote:
Originally Posted by ssǝן‾ʎ
Locks won't help.
Sure they will. It is fairly obvious that the reason for these crashes is because multiple threads are trying to modify the state of PAWN at the same time (which is why it is only safe to call functions like amx_Exec from a single thread), but locks are more of a theoretical approach than a practical one, because, as I said, it is most likely impossible to do in the plugin. It might also be counter-intuitive in some cases, because the main thread would simply be interrupted in the scenario I just described.

Quote:
Originally Posted by ssǝן‾ʎ
And clearly you are waiting for a message, which will block, instead of polling for a message each server tick, which won't block.
Polling for a message as in calling a native? This is actually the part I do not understand. Could you elaborate further on how to remain within the main thread on "each server tick?"

Quote:
Originally Posted by ssǝן‾ʎ
And Boost may be simple but it's horribly bloated.
Agreed that some parts of it might be bloated, but in my opinion, that is a small trade-off for nice portable code. Plus, some libraries are just incredibly useful to have in any project (and they are not bloated at all)—string algorithms, lexical_cast, shared_ptr, et cetera.
Reply
#16

COLL I LIVKE!
Reply
#17

Quote:
Originally Posted by XCultz
COLL I LIVKE!
I've deleted a bunch of spam posts from you. Keep it up and I'll remove you instead.

And don't reply to this post. That would be spam.
Reply
#18

Quote:
Originally Posted by ssǝן‾ʎ
No, polling by calling a native is what I was saying not to do in the first place, just poll the message queue from the main thread. Most threads have main loops, that's how programs work, by looping through code repeatedly, like a timer does but better (you can actually do this in the main() PAWN function too as it's such a fundamental coding technique. From this main loop you poll the message queue, and if a message is present then call the callbackk.
Yes, that is how programs work, but the plugin is not a program. It is a dynamic library that loads subroutines into the server application at runtime, and I am fairly confident it has no main loop. Why would it need one for this purpose? That is all done in the program itself, not the library that runs alongside it.
Reply
#19

If you could provide me with the value whenever you have access to your machine, it would be great.
Reply
#20

Once that is established a small SDK should be made to use callbacks the correct way, would be very usefull for future plugin development.
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)