[Plugin] MultiThread
#1

Description:
This is MultiThread plugin. And I don't know what to write here . Examples speak for themselves.
http://en.wikipedia.org/wiki/Multith...rchitecture%29
Attention:
Quote:

PAWN is not designed to be multi-threaded and there are no guarantees AT ALL on your data the moment you introduce threads.

Wrong using this plugin can significantly corrupt your gamemode.
How to use:
pawn Код:
#include <thread>
Log:
  • 0.1.6
    - Added new native CreateThreadEx( const pubname[ ] );
  • 0.1.5
    - First release.
Natives:
pawn Код:
native CreateThread( const pubname[ ] );
native CreateThreadEx( const pubname[ ] );
native DestroyThread( threadid );
native SleepThread( milliseconds ); // Use in thread (public)
native LockThread( threadid ); // Synchronize will return the id lock
native UnLockThread( lockid );
Example:
With CreateThread
pawn Код:
new tickid;

public OnGameModeInit()
{
    tickid = CreateThread( "MyFunction" );
}

public OnGameModeExit()
{
    DestroyThread( tickid );
}

public MyFunction( threadid )
{
    printf( "tick(%d)...", threadid  );
       
    SleepThread( 1000 );
}
With CreateThreadEx
pawn Код:
new bool:active;
new tickid;

public OnGameModeInit()
{
    tickid = CreateThreadEx( "MyFunction" );
}

public OnGameModeExit()
{
    active = false;
}

public MyFunction( threadid )
{
    active = true;
   
    while ( active )
    {
        printf( "tick(%d)...", threadid  );
       
        SleepThread( 1000 );
    }
}
Download:
Reply
#2

I'm confused about what this dose, is it just a different way to call a function?
Reply
#3

Quote:
Originally Posted by linuxthefish
Посмотреть сообщение
I'm confused about what this dose, is it just a different way to call a function?
http://en.wikipedia.org/wiki/Multith...rchitecture%29

If you speak Russian, i can explain it to you =)))
Reply
#4

Quote:
Originally Posted by Fro1sha
Посмотреть сообщение
http://en.wikipedia.org/wiki/Multith...rchitecture%29

If you speak Russian, i can explain it to you =)))
I didn't think it was to do with actual threads! I'm definitely going to be using this.
Reply
#5

will get in handy for ....pro scripter.....not a beginner like me.....
Reply
#6

Can't this corrupt your computer?
Reply
#7

Quote:
Originally Posted by ronaldoraul
Посмотреть сообщение
will get in handy for ....pro scripter.....not a beginner like me.....
No this is very simple.

Quote:
Originally Posted by Rysoku
Посмотреть сообщение
Can't this corrupt your computer?
What?
Reply
#8

I was actually wondering why there didn't seem to be a threading plugin yet, based on the source, the parameter known as 'pubname' defines a function to be executed by the thread. Also, I'm guessing the function loops until the thread is destroyed? If so, you should change that so that threads can die naturally without being told to, it is much easier to implement a loop than to perform logic to assume when would be a good time to call DestroyThread. That way you could also implement a OnThreadDeath callback.

That way something like this would work.
Код:
new bool:active;
new tickid;

public OnGameModeInit()
{
	tickid = ThreadCreate( "MyFunction" );
}

public OnGameModeExit()
{
	active = false;
}

public MyFunction()
{
	active = true;
	
	while ( active )
	{
		printf( "tick..." );
		
		SleepThread( 1000 );
	}
}

public onThreadDeath( threadid )
{
	if ( threadid = tickid )
		printf( "The tick thread has died naturally." );
}
Other than that, nice work!
Reply
#9

Quote:
Originally Posted by langricr
Посмотреть сообщение
I was actually wondering why there didn't seem to be a threading plugin yet, based on the source, the parameter known as 'pubname' defines a function to be executed by the thread. Also, I'm guessing the function loops until the thread is destroyed? If so, you should change that so that threads can die naturally without being told to, it is much easier to implement a loop than to perform logic to assume when would be a good time to call DestroyThread. That way you could also implement a OnThreadDeath callback.

That way something like this would work.
Код:
new bool:active;
new tickid;

public OnGameModeInit()
{
	tickid = ThreadCreate( "MyFunction" );
}

public OnGameModeExit()
{
	active = false;
}

public MyFunction()
{
	active = true;
	
	while ( active )
	{
		printf( "tick..." );
		
		SleepThread( 1000 );
	}
}

public onThreadDeath( threadid )
{
	if ( threadid = tickid )
		printf( "The tick thread has died naturally." );
}
Other than that, nice work!
This is variant not good. Very hard for pawn scripters and DestroyThread and not actual onThreadDeath( threadid ).
Reply
#10

Quote:
Originally Posted by Fro1sha
Посмотреть сообщение
This is variant not good. Very hard for pawn scripters and DestroyThread and not actual onThreadDeath( threadid ).
I suppose people could just call DestroyThread at the end of the function, but it seems dangerous outside of that, what happens if you try to destroy a thread while its halfway through the function?

I recommend having a look at this, while its Java, it does give some insight as to the dangers of stopping a thread.

Quote:

Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior. Many uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running.

Reply
#11

Quote:
Originally Posted by langricr
Посмотреть сообщение
I suppose people could just call DestroyThread at the end of the function, but it seems dangerous outside of that, what happens if you try to destroy a thread while its halfway through the function?

I recommend having a look at this, while its Java, it does give some insight as to the dangers of stopping a thread.
Ok don't stop thread in thread . I add CreateThreadEx soon
Reply
#12

Sounds like much fun with race conditions
Nice plugin.
Reply
#13

New version... Read the first post please.
Reply
#14

Код:
new tickid;

public OnGameModeInit()
{
    tickid = CreateThread( "MyFunction" );
}

public OnGameModeExit()
{
    DestroyThread( tickid );
}

public MyFunction( threadid )
{
    printf( "tick(%d)...", threadid  );
        
    SleepThread( 1000 );
}
I like that you found my example helpful

But how does the CreateThread know what parameters to pass to the function?
Reply
#15

I wanted to add that the AMX functions you are calling from outside the main thread have no concept of thread safety. It's very likely that a crash or some kind of undefined behavior will eventually occur when more than one thread attempts to modify the state of the virtual machine at the same time. This has been documented, and it is precisely why most multithreaded plugins now pass their shared data in a queue to the main loop (I've noticed that most people don't protect the queues with locking mechanisms, though, which can lead to just as many problems). Unfortunately, what you are trying to do just isn't possible without creating race conditions.
Reply
#16

I tried using this plugin but I can't get it working stable.

This is the pawn code that I'm using (guided by the example):
pawn Код:
public TimFunc2()
{
    #if defined _use_threading
    thTruckerCheck = CreateThread("TruckerCheck");
    #else
    SetTimer("TruckerCheck", 1000, 1);
    #endif
    return 1;
}

// in onplayerconnect
stock AdaugaPThread(playerid)
{
    new lock2 = LockThread(thTruckerCheck);
    Itter_Add(Player, playerid);
    UnLockThread(lock2);
}

// in onplayerdisconnect
stock StergePThread(playerid)
{
    new lock2 = LockThread(thTruckerCheck);
    Itter_Remove(Player, playerid);
    UnLockThread(lock2);
}
#endif

#if defined _use_threading
function TruckerCheck(threadid)
{
    static dTruckerCheck;
    if (!dTruckerCheck)
    {
        dTruckerCheck = true;
        SleepThread(5000);
    } else SleepThread(1020);
    new lock = LockThread(threadid);
#else
function TruckerCheck()
{
#endif
    static s_tmpST;
    s_tmpST = GetTickCount();
    foreach(Player, playerid)
    {
        if(gSofer[playerid])
        {
            if(PlayerIsStreamed(s_tmpST,playerid))
            {
                static s_stringTRK[128], Float:s_cHealth, tmpcar;
                tmpcar = GetPlayerVehicleID(playerid);
                if(tmpcar)
                {
                    GetVehicleHealth(tmpcar, s_cHealth);
                    VehHealthBar(playerid,s_cHealth);
                    if(CarInfo[tmpcar][cModel] == 456 || CarInfo[tmpcar][cModel] == 440)
                    {
                        for(new i=0; i<=NumarBizuri; i++)
                        {
                            if(IsPlayerInRangeOfPoint(playerid, 10.0, BizzInfo[i][bEntranceX], BizzInfo[i][bEntranceY], BizzInfo[i][bEntranceZ]))
                            {
                                format(s_stringTRK, sizeof(s_stringTRK), "~w~%s~n~~r~Products Required~w~: %d~n~~y~Price per Product: ~w~: $%d~n~~g~Funds: ~w~: $%d",BizzInfo[i][bMessage],(BizzInfo[i][bMaxProducts]-BizzInfo[i][bProducts]),BizzInfo[i][bPriceProd],BizzInfo[i][bTill]);
                                GameTextForPlayer(playerid, s_stringTRK, 5000, 3);
                            }
                        }
                    }
                }
            }
        }
    }
    #if defined _use_threading
    UnLockThread(lock);
    #endif
    return 1;
}

This is the backtrace log:
Код:
Thread 10 (Thread 0xb23fbb90 (LWP 14012)):
#0  0xb7fe37f2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
No symbol table info available.
#1  0xb7fc6ef2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib/libpthread.so.0
No symbol table info available.
#2  0xb63965f5 in boost::condition_variable::timed_wait (this=0xb4c4ddc8, m=..., wait_until=...) at ../../../boost/thread/pthread/condition_variable.hpp:64
        guard = {m = 0xb23fb224}
        check_for_interruption = {thread_info = 0xb4c4dd38, m = 0xb4c4ddc8, set = true}
        timeout = {tv_sec = 1309003835, tv_nsec = 153699000}
        cond_res = -1237759302
        __PRETTY_FUNCTION__ = "bool boost::condition_variable::timed_wait(boost::unique_lock<boost::mutex>&, const boost::system_time&)"
#3  0xb638fb0c in boost::this_thread::sleep (st=...) at ../src/pthread/thread.cpp:327
        lk = {m = 0xb4c4ddb0, is_locked = false}
        thread_info = 0xb4c4dd38
#4  0xb6389e46 in Natives::n_SleepThread(tagAMX*, int*) () from plugins/Thread.so

#25 0xb6394afc in boost::pthread::pthread_mutex_scoped_lock::pthread_mutex_scoped_lock(._12 *) (this=0x8934cd8, m_=0xa5)
    at ../../../boost/thread/pthread/pthread_mutex_scoped_lock.hpp:26
No locals.
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
Could this be because I'm also using a mysql plugin with threading and there are conflicts? because I also get this:
Код:
Thread 3 (Thread 0xb6ebfb90 (LWP 13960)):
#0  0xb7fe37f2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
No symbol table info available.
#1  0xb7dd7d26 in nanosleep () from /lib/libc.so.6
No symbol table info available.
#2  0xb7e1188c in usleep () from /lib/libc.so.6
No symbol table info available.
#3  0xb7bfd4b7 in ProcessQueryThread (lpParam=0x0) at main.cpp:189
and "ProcessQueryThread" is a function from BlueG's mysql plugin.
Reply
#17

Quote:
Originally Posted by ******
Посмотреть сообщение
There is a reason there is no threading plugins already, especially not ones which actually run PAWN functions in a mode! PAWN is not designed to be multi-threaded and there are no guarantees AT ALL on your data the moment you introduce threads.

You might want to make it VERY clear in the first post that using this can significantly corrupt your gamemode before people who don't know what they're doing try and use it...
I don't get it with this plugin... could I make a thread for creating cars and a second thread for creating objects so the code will be executed at the same time? I don't really get it in pawn because as you already said it is single-threaded, so how can you actually run another public function in another thread? :S

Any examples of what I wnt to achieve?

would be a great way to make a pawn based streamer.

and could you also make with this an threat for every player to ex stream player textdraws with their info instead of looping all players?
Reply
#18

Well, I tried making some of my functions that are currently called by timers running into separate threads. But seems like is not stable.
Reply
#19

The only safe use for this, that comes in mind, is saving data in background.
Reply
#20

Even if the multi-threading was supported by Pawn language, there would be still all kinds of weird bugs because there are A LOT of problems with it and by the way, Pawn is supposed to be 'light' by design(i.e. used in embedded systems and games) so multi-threading does not make sense very much.
Reply


Forum Jump:


Users browsing this thread: 11 Guest(s)