SRL Archive - Lape

Can lape Muilti-thread?


rj

2013-02-06 21:41:39

Figuring no, but just wondering.

Flight

2013-02-06 21:51:27

I may be wrong about this, but from what I remember nearing is it's possible but not yet added? Check out this post for more info:

http://villavu.com/forum/showthread.php?t=68613&page=2&p=904549#post904549

Olly

2013-02-06 22:55:22

Currently not no, and in all honestly i really don't see the point in multithreading in runescape really… sure proggys would be nice but you really don't need exact timing of every function.

Echo_

2013-02-07 00:26:38

It would be a cool feature. You could run multiple color searches simultaneously, progress reports and file IO wouldn't need to take execution time away from the script itself, etc. The only problem I see with it is that multithreading is kinda messy using an imperative programming style with mutable state. Plus there would be a lot of issues with people not using it correctly, ex. deadlock

Mark

2013-02-07 05:29:33

Multiple threading is amazing if managed correctly and will greatly improve speed which meens these slower but more accurate methods of abject detection and for example finding npc that constantly move around screen time is wasted with failed clicks due to the npc moving position constantly so realtime detection is required.

Personal I think every programmer should learn and master the use of threads tho not really needed for mnay application I think here is a very much suited situation where a lot of people here are about speed and performance this will be a great help to achieve perfection where speed/accuracy is a must.

Also the amount human like antiban procedure that could be made with threads really cries out to me would really love to finally see threads hit simba.

DannyRS

2013-02-07 06:29:23

From: Ollybest
Currently not no, and in all honestly i really don't see the point in multithreading in runescape really… sure proggys would be nice but you really don't need exact timing of every function.


It's useless for actual tasks, but for anti-ban and creating human like behaviours, it would be awesome, for example monitoring colors while moving the mouse about or whatever, just isn't very possible in procedural

rj

2013-02-07 19:29:05

Lol, I would just use it for real time proggies if it were to be added

Brandon

2013-02-09 12:03:39

From: DannyRS
It's useless for actual tasks, but for anti-ban and creating human like behaviours, it would be awesome, for example monitoring colors while moving the mouse about or whatever, just isn't very possible in procedural



Cpp is procedural. It has multithreading.

That brings up a question in my mind. Since Lape has pointers, wouldn't it be possible to just make a DLL that accepts a function pointer and runs that in a thread?


EDIT:

:S For some reason I cannot get Simba to load my DLL so I can't test it in Simba.. Did Simba's Plugin ABI change? I think I'm getting Rusty. Been inactive too long lol. If it doesn't work in Lape then oh well.. Free Thread class below.

Anyway, what I think is that you should be able to do (Theoretical code since I cannot test :( ):


{$loadlib Threading.dll}

var
ThreadIDs: TIntegerArray;

Procedure FunctionToPass();
begin
writeln("TEST");
end;

begin
SetLength(ThreadIDs, 1); //Amount of threads we want to spawn..
ThreadIDs[0] := ThreadFunction(@FunctionToPass); //This is how you pass function address in lape right?
StopThreadFunction(ThreadIDs[0]);
end.



Works in C++ though:

Export.hpp:

#ifndef EXPORT_HPP_INCLUDED
#define EXPORT_HPP_INCLUDED

#include <windows.h>
#include <iostream>

#ifdef SIMBA_EXPORTS
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif

#ifdef __cplusplus
#define SIMBA_EXTERN extern "C"
#define SIMBA_EXPORT extern "C" DLL_EXPORT
#endif

#define NumberOfExports 2

extern HINSTANCE hInstance;
extern char* Exports[];

SIMBA_EXPORT int GetPluginABIVersion();
SIMBA_EXPORT int GetFunctionCount();
SIMBA_EXPORT int GetFunctionInfo(int Index, void*& Address, char*& Definition);

#endif // EXPORT_HPP_INCLUDED

Threading.hpp:

#ifndef THREADING_HPP_INCLUDED
#define THREADING_HPP_INCLUDED

#include <iostream>
#include <fstream>
#include <thread>
#include <atomic>
#include <system_error>
#include <map>

class Threading
{
private:
std::map<std::uint32_t, std::thread> ThreadPool;
std::map<std::uint32_t, std::atomic<bool>> ThreadIDs;

public:
Threading() {};

template<class Function, class... Args>
std::uint32_t StartThread(Function&& FunctionToPass, Args&&... args);

std::uint32_t StartThread(std::function<void()>& FunctionToPass);

void StopThread(std::uint32_t ThreadID);
};

template<class Function, class... Args>
std::uint32_t Threading::StartThread(Function&& FunctionToPass, Args&&... args)
{
ThreadPool.insert(std::pair<std::uint32_t, std::thread>(ThreadPool.size() + 1, std::thread(FunctionToPass, args...)));
return ThreadPool.size();
}

#endif // THREADING_HPP_INCLUDED

Threading.cpp:

#include "Threading.hpp"

std::uint32_t Threading::StartThread(std::function<void()>& FunctionToPass)
{
ThreadPool.insert(std::pair<std::uint32_t, std::thread>(ThreadPool.size() + 1, std::thread(FunctionToPass)));
return ThreadPool.size();
}

void Threading::StopThread(std::uint32_t ThreadID)
{
try
{
std::map<std::uint32_t, std::atomic<bool>>::iterator TID = this->ThreadIDs.find(ThreadID);

if (TID != this->ThreadIDs.end() && TID->second)
{
std::map<std::uint32_t, std::thread>::iterator it = this->ThreadPool.find(ThreadID);
if (it != this->ThreadPool.end())
{
it->second.detach();
ThreadPool.erase(it);
}
}
else
{
std::map<std::uint32_t, std::thread>::iterator it = this->ThreadPool.find(ThreadID);
if (it != this->ThreadPool.end())
{
it->second.join();
ThreadPool.erase(it);
}
}
}
catch (...){}
}

Main.cpp:

#include "Export.hpp"
#include "Threading.hpp"

HINSTANCE hInstance = NULL;
Threading ThreadPool;

char* Exports[] = {
(char*)"ThreadFunction", (char*)"Function ThreadFunction(FunctionToPass: Pointer): Integer",
(char*)"StopThreadFunction", (char*)"Procedure StopThreadFunction(ThreadID: Integer);"
};

SIMBA_EXPORT int GetPluginABIVersion()
{
return 2;
}

SIMBA_EXPORT int GetFunctionCount()
{
return NumberOfExports;
}

SIMBA_EXPORT int GetFunctionInfo(int Index, void*& Address, char*& Definition)
{
if (Index < NumberOfExports)
{
Address = (void*)GetProcAddress(hInstance, Exports[Index * 2]);
#ifdef _MSC_VER
#pragma warning(disable: 4996)
strcpy(Definition, Exports[Index * 2 + 1]);
//strcpy_s(Definition, Exports[Index * 2 + 1]);
#else
strcpy(Definition, Exports[Index * 2 + 1]);
#endif
return Index;
}
return -1;
}

SIMBA_EXPORT std::uint32_t ThreadFunction(std::function<void()> &FunctionToPass) //Can just make this take parameter: void (*FunctionToPass)() still works. Even just an address works.
{
return ThreadPool.StartThread(FunctionToPass);
}

SIMBA_EXPORT void StopThreadFunction(std::uint32_t ThreadID)
{
ThreadPool.StopThread(ThreadID);
}

SIMBA_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
{
hInstance = hinstDLL;
std::cout<<"Threading Loaded.."<<std::endl;
return true;
}
break;

case DLL_PROCESS_DETACH:
{
return true;
}
break;
}
return TRUE; // succesful
}



Test Console Main.cpp:

#include <iostream>
#include <windows.h>
#include <functional>

using namespace std;

//typedef void (*Func_Ptr)(void);
//typedef void (*CallFunc)(Func_Ptr);

typedef std::uint32_t (*StartFunc)(std::function<void()>&);
typedef void (*StopFunc)(std::uint32_t);

void LOL(int X, int Y)
{
std::cout<<"Testing DLL Function: X="<<X<<" Y="<<Y<<std::endl;
}

int main()
{
HMODULE L = LoadLibrary("C:/Users/Brandon/Desktop/Thread/bin/Release/Thread.dll");

StartFunc ThreadFunction = (StartFunc)GetProcAddress(L, "ThreadFunction");
StopFunc StopThreadFunction = (StopFunc)(GetProcAddress(L, "StopThreadFunction"));

std::function<void()> FunctionToPass = std::bind(LOL, 1, 2); //Binding some arguments to our Thread Function.. Can bind any amount of arguments.. Can also use funcptr instead of std::function/std::bind.
std::uint32_t ID = ThreadFunction(FunctionToPass);
std::cout<<"\nThread ID: "<< ID <<std::endl;
StopThreadFunction(ID);

FreeLibrary(L);
return 0;
}


So you pass a function or function pointer with any amount of arguments and std::function will unbind it and run that function without knowing any information about it. Can also pass an array of arguments and a function pointer via std::bind and it will also unwrap when the thread starts. Using std::atomic<ReturnType>, you can pass the returned value if any to any thread.

That brings the question.. Does Lape have function pointers? I thought it does :S
Just a theory though.. I don't see why it shouldn't work.

DannyRS

2013-02-09 12:12:40

From: Brandon

That brings the question.. Does Lape have function pointers? I thought it does :S
Just a theory though.. I don't see why it shouldn't work.


I remember someone made a dll to run a timer that would trigger an event in simba, but I think it was buggy and caused crashes or something, can't remember :p

Richard

2013-02-09 12:19:56

From: DannyRS
It's useless for actual tasks, but for anti-ban and creating human like behaviours, it would be awesome, for example monitoring colors while moving the mouse about or whatever, just isn't very possible in procedural


A really good use would be for dynamic mouse splines. Although it would be possible without multithreading.

Another example: being able to read chat text whilst waiting for an inventory of items to be finished.

It general, it just makes scripts more versatile.

DannyRS

2013-02-09 12:24:26

From: Richard
A really good use would be for dynamic mouse splines. Although it would be possible without multithreading.

Another example: being able to read chat text whilst waiting for an inventory of items to be finished.

It general, it just makes scripts more versatile.


It's possible to write a function into a mouse function, but that takes forever and if the code executed takes more than like 5ms the mouse can stutter quite bad :/

Would just be nice to be able to do it more easily and with better results, I agree with the chat thing :p just several little things you could do while doing something else, without having to pause your current loop, or have to spend ages writing it into the loop with a workaround ;)

Echo_

2013-02-09 13:48:11

It would be cool if we had some sort of system to make concurrency less error prone, like software transactional memory:

http://en.wikipedia.org/wiki/Software_transactional_memory

rj

2013-02-09 13:54:00

Looks like all this talk about muilti threading is getting people excited.

Echo_

2013-02-09 17:51:19

From: rjj95
Looks like all this talk about muilti threading is getting people excited.


It's been talked about for years, there's even a tutorial for emulating concurrency using TTimer:
http://villavu.com/forum/showthread.php?t=51578

Richard

2013-02-10 08:02:44

From: Echo_
It's been talked about for years, there's even a tutorial for emulating concurrency using TTimer:
http://villavu.com/forum/showthread.php?t=51578


Wasn't that awfully glitchey though? And only worked in SCAR?

Echo_

2013-02-10 22:58:15

From: Richard
Wasn't that awfully glitchey though? And only worked in SCAR?


Yes, but it's the closest we ever got to multithreading :p

Mark

2013-02-11 04:20:43

From: Richard
Wasn't that awfully glitchey though? And only worked in SCAR?


Yes that's right but same really stands for threads if not used correctly can cause a stack overflow to occur threads need to be synchronize to avoid corrupting shared memory but all this is very easy to learn and adapt to and will overall improve users knowledge and abilities just like anything else we have introduced like ACA SPS ObjectDTM Lape OpenGL was all new to us and we adapted wrote tutorials to share our knowledge to help others.