SRL Archive - Research & Development Lounge

My ~~Multithreading thingy


bg5

2013-12-19 18:59:32

    Step 1 Download my plugin, which is needed to share memory between Simba's tabs (and don't forget to put it in plugins folder) [ATTACH]22589[/ATTACH] <- dll + sorce [*]Step 2
    Open Simba, open 3 new tabs in it. Copy each 1 of 3 scripts to different tab:
    program MainTab;
    {$loadlib tabShareMem}
    var bmp,w,h,w2,h2:integer;
    var TPA,snake,tail :TPointArray;
    var P:Pointer;
    begin
    ShareBool(false,'tab2start');
    ShareBool(false,'tab3start');
    while not (GetSharedBool('tab2start')and GetSharedBool('tab3start')) do
    wait(100);
    w := 300;
    h := 200;
    bmp := CreateBitmap(w,h);
    RectangleBitmap(bmp,IntToBox(150,1,151,199),$FFFFFF);
    RectangleBitmap(bmp,IntToBox(1,20,299,20),$FFFFFF);
    TPAFromTextWrap('Time Running :','LoginChars',w2,h2,TPA);
    OffsetTPA(TPA,Point(160,45));
    DrawTPABitmap(bmp,TPA,$FF00FF);

    TPAFromTextWrap('tab 3','LoginChars',w2,h2,TPA);
    OffsetTPA(TPA,Point(50,2));
    DrawTPABitmap(bmp,TPA,$00FF00);

    TPAFromTextWrap('tab 2','LoginChars',w2,h2,TPA);
    OffsetTPA(TPA,Point(200,2));
    DrawTPABitmap(bmp,TPA,$00FF00);


    wait(1000);

    ShareBool(false,'CritSec1');
    ShareBool(false,'CritSecSnake');
    while(true) do
    begin
    wait(50);
    RectangleBitmap(bmp,IntToBox(220,80,299,95),0);

    if (GetSharedBool('CritSec1')) then
    begin
    TPA := TPointArray(GetSharedPointer('Tab2TPA'));
    DrawTPABitmap(bmp,TPA,$FF00FF);
    ShareBool(false,'CritSec1');
    end;

    if (GetSharedBool('CritSecSnake')) then
    begin
    snake := TPointArray(GetSharedPointer('snakeTPA'));
    tail := TPointArray(GetSharedPointer('tailTPA'));
    DrawTPABitmap(bmp,tail,0);
    DrawTPABitmap(bmp,snake,$F0FF00);
    ShareBool(false,'CritSecSnake');
    end;

    DisplayDebugImgWindow(w+1,h+1);
    DrawBitmapDebugImg(bmp);

    end;
    end.
    program Tab2;
    {$loadlib tabShareMem}
    var TPA:TPointArray;
    var w,h:integer;

    begin
    ShareBool(true,'tab2start');
    while not( GetSharedBool('tab3start')) do
    wait(100);
    while(true) do
    begin
    if not(GetSharedBool('CritSec1')) then
    begin
    TPAFromTextWrap(tostr(GetTimeRunning),'LoginChars',w,h,TPA);
    OffsetTPA(TPA,Point(220,80));
    SharePointer(Pointer(TPA),'Tab2TPA');
    ShareBool(true,'CritSec1');
    end;

    end;

    end.
    program Tab3;
    {$loadlib tabShareMem}
    var Snake,toRemove :TPointArray;
    sLen,w,h :integer;
    dir :char;
    procedure createSnake();
    var i:integer;
    begin
    w := 150;
    h := 199;
    slen := 50;
    SetLength(Snake,slen);
    for i := 0 to slen-1 do
    snake[i] := Point(round(w/2),round(h/2)+i);
    dir := 'd';
    end;

    function WaitForKey(var dir :char;time:integer) : boolean;
    var
    t : LongWord;
    dir2 : char;
    begin
    t := GetTimeRunning;
    dir2 := dir;
    repeat
    if IsKeyDown(37)and(dir2<>'r') then dir := 'l' ;
    if IsKeyDown(39)and(dir2<>'l') then dir := 'r' ;
    if IsKeyDown(38)and(dir2<>'d') then dir := 'u' ;
    if IsKeyDown(40)and(dir2<>'u') then dir := 'd' ;
    until (GetTimeRunning - t) > time
    end;

    function NoClipControl(var nextPoint : TPoint) : boolean;
    begin
    if nextPoint.x > w then nextPoint.x := 0;
    if nextPoint.x < 0 then nextPoint.x := w;
    if nextPoint.y > h then nextPoint.y := 21;
    if nextPoint.y < 21 then nextPoint.y := h;
    end;
    procedure DeleteValueInTPA(var Arr: TPointArray; ValuePosition: Integer); // by EvilChicken! & Coh3n
    var
    ArrLen, I: Integer;
    begin
    ArrLen := High(Arr);
    for I := ValuePosition to ArrLen - 1 do
    tSwap(Arr[I], Arr[I + 1]);
    SetArrayLength(Arr, ArrLen);
    end;
    procedure MoveSnake(dir : char ); //input dir: 1 - left ,2 - rigth ,3 - up ,4 - down
    var //output TRUE on crash
    dx,dy,head : integer;
    newHead,removeTail : TPoint;
    t:integer;

    begin
    case dir of
    'l': dx := -1;
    'r': dx := 1;
    'u': dy := -1;
    'd': dy := 1;
    end;

    head := slen-1;
    newHead := Point(snake[head].x + dx , snake[head].y + dy );
    NoClipControl(newHead); // Noclip control

    removeTail := Point(snake[0].x,snake[0].y);
    toRemove:=[removeTail];

    DeleteValueInTPA(snake,0);
    setlength(snake,slen);
    snake[head] := newHead;
    end;
    procedure SafeShare;
    begin
    while(GetSharedBool('CritSecSnake')) do
    wait(5);
    MoveSnake(dir);
    SharePointer(Pointer(snake),'snakeTPA');
    SharePointer(Pointer(toRemove),'tailTPA');
    ShareBool(TRUE,'CritSecSnake');
    end;
    procedure MainLoop;
    begin
    while(true) do
    begin
    WaitForKey(dir,30);
    SafeShare;
    end;
    end;


    begin
    ShareBool(true,'tab3start');
    createSnake();
    MainLoop;
    end.
    [*]Step 3
    Run 3 tabs in sequence: tab1(MainTab) ,tab2 ,tab3. Don't need to hurry, start is synchronized. [*]Step 4
    Watch the magic.







Description
This *thing* is using 3 threads working simultaneous. Tab2 is showing TimeRunning and Tab3 is hosting snake. This snake is very thin, because he doesn't have anything to eat there. Tab1 - MainTab is rendering TPAs received from tab2 and tab3 on it's debug window.
As you see I've used boolean as a switch between tab1 and other tabs. Thats because we don't want to work on TPA in the same time when tab1 is printing it, it would be bad. So when flag is TRUE only tab1 can access it, when flag is FALSE only it's native tab can access it.


Pseudo-multithreading?

Sharing memory plugin is only half of my concept of ~~multithreading I've described here:
http://villavu.com/forum/showthread.php?t=103201&page=3&p=1274526#post1274526
and here:
http://villavu.com/forum/showthread.php?t=103201&page=4&p=1275825#post1275825 @Zyt3x

The second half are 4 functions:
function PauseScript(TabNumber: byte) : boolean;
function ResumeScript(TabNumber: byte) : boolean;
function StopScript(TabNumber: byte) : boolean;
function RunScript(TabNumber: byte) : boolean;

Those would let us use the whole power of multithreading with minimal effort and changes in source, because they are already there: assigned to buttons. But it doesn't depend on me…
I understand that it's maybe not too elegant solution, as I can't image how SRL devs can write include in few different tabs. However if we can run few scriptthreads simultaneous already, isn't it possible to do this without a GUI, all inside the one tab ?

Kyle

2013-12-19 19:53:32

Dang man! I really like this. Not sure how feasible it will be to utilize but definitely neat!

Kevin

2013-12-20 13:56:56

Hey… This would allow us to bring back interactive GUIs that can be changed mid-runtime.

While at a base that's not ultra useful… It can allow someone to type to another player while still botting or even change some settings during the run.

Brandon

2013-12-20 15:13:15

From: Kevin
Hey… This would allow us to bring back interactive GUIs that can be changed mid-runtime.

While at a base that's not ultra useful… It can allow someone to type to another player while still botting or even change some settings during the run.


Was already done using an extension: http://villavu.com/forum/showthread.php?t=65657 Don't know if it still works but yeah, that would be cool.
Forms can be shown Non-Modally. That's why it is already possible.

I must admit though, this pseudo threading thing looks pretty neat. Especially if it can incorporate the pause/play/stop buttons.

Kevin

2013-12-20 15:19:58

From: Brandon
Was already done using an extension: http://villavu.com/forum/showthread.php?t=65657 Don't know if it still works but yeah, that would be cool.
Forms can be shown Non-Modally. That's why it is already possible.

I must admit though, this pseudo threading thing looks pretty neat. Especially if it can incorporate the pause/play/stop buttons.

Yeah, I think yours stopped working at some point with the LAPE update, but I was commenting on how this could allow it to work again. Maybe yours didn't break I guess… Thought it did though. Nonetheless, both are nice projects.

Brandon

2013-12-20 15:43:04

@OffTopic.

From: Kevin
Yeah, I think yours stopped working at some point with the LAPE update, but I was commenting on how this could allow it to work again. Maybe yours didn't break I guess… Thought it did though. Nonetheless, both are nice projects.


Never mind the project I linked. I was referring to the concept in that link. Aka Non-Modal forms. I'm pretty sure Non-Modal forms in itself is possible in Simba without an extension or plugin or anything.

Example:


var
Frm: TForm;

procedure Init;
begin
Frm := CreateForm(nil);
with Frm do
begin
//add controls to Frm.
end;
end;

procedure FSafeInit;
var
v: TVariantArray;
begin
SetLength(v, 0);
ThreadSafeCall('Init', v);
end;

function FDisplay: Boolean;
begin
//Result := Frm.ShowModal = mrOk;
Frm.SHOW;
Result:= Frm.Showing;
end;

function FSafeDisplay: Boolean;
var
v: TVariantArray;
begin
SetLength(v, 0);
Result := ThreadSafeCall('FDisplay', v);
end;

Procedure FreeFrm;
begin
FreeForm(Frm);
end;

begin
SetupSRL;

FSafeInit;
FSafeDisplay;
AddOnTerminate('FreeFrm');

This allows a form to NOT block the main thread while being displayed.