std::thread test([]()
{
//code
};
test.detach();
Разработчики, только перешедшие с клео\луа на C++ негодуют из-за необходимости использовать разного рода таймеры и лапшу из GetTickCount'ов вместо полюбившихся функций wait. Но особо ярых фанатов клео это не устраивает, отчего они начинают использовать потоки ради функций вроде Sleep для того чтобы не блокировать цикл игры. Однако это не безопасно. Функции ни GTA ни SAMP'а абсолютно не предназначены для использования в разных потоках и их использование может привести к рандомным крашам.
Выход есть!
Example:#include <string>...
std::thread test([]()
{
//code
};
test.detach();
Разработчики, только перешедшие с клео\луа на C++ негодуют из-за необходимости использовать разного рода таймеры и лапшу из GetTickCount'ов вместо полюбившихся функций wait. Но особо ярых фанатов клео это не устраивает, отчего они начинают использовать потоки ради функций вроде Sleep для того чтобы не блокировать цикл игры. Однако это не безопасно. Функции ни GTA ни SAMP'а абсолютно не предназначены для использования в разных потоках и их использование может привести к рандомным крашам.
Выход есть!
Example:#include <string> #include <chrono> #include "Yet-another-hook-library/hook.h" #include "sampapi/CChat.h" #include "coro_wait/coro_wait.h" using namespace sampapi::v037r1; void foo() { using namespace std::chrono_literals; CChat *&pChat = RefChat(); while (!pChat) { this_coro::wait(100ms); } unsigned int counter = 0; while (true) { pChat->AddMessage(-1, (std::string("Hello ") + std::to_string(counter)).c_str()); counter++; this_coro::wait(1s); } } void CGame_Process_hk() { static coro_wait instance{ foo }; instance.process(); } class coro_wait_example { public: coro_wait_example() { using CGame_Process_t = void(__cdecl*)(); CGame_Process_t CGame_Process = reinterpret_cast<CGame_Process_t>(0x53BEE0); static hook CGame_Process_hook(CGame_Process, CGame_Process_hk); } } coro_wait_example;
Выполнение функции foo приостанавливается на время, переданное функции this_coro::wait, и продолжается с того же места. Все это работает в одном потоке, благодаря чему можно не переживать за потокобезопасность вызываемых внутри функций.
В бесконечных или очень больших циклах требуется вызывать wait(0), все по канонам клео.
Функция coro_wait::process должна вызываться в потоке игры (перехваченном как в примере, либо в функции mainloop для SF API).
Требуется библиотека Boost.Context!
Исходный код:
GitHub - allwanttokissme/coro_wait: Suspending coroutines by time
Suspending coroutines by time. Contribute to allwanttokissme/coro_wait development by creating an account on GitHub.github.com
хуки
sampapi
буду использовать первый вариант, пасиба, работаетstd::this_thread::sleep_for(std::chrono::milliseconds(100)); // 100 миллисекунд
но перед этим создай поток что бы не зафризило игру:
Код:std::thread test([]() { //code }; test.detach();
или же:
Можно подробнее насчёт таймеров? Я использую функцию CreateThread, с ней вроде нет никаких проблем по части производительности даже когда таких потоков очень много.@Smeruxa
первый вариант хуета, а второй заебись. потоки лучше юзать в крайне редких случаях, когда действия в главном цикле игры могут так нихуево грузить систему в момент исполнения кода, если этот код не прям нужный, то можно юзать их. Для всех остальных случаев лучше использовать таймеры.
Потоки зло. Они тебя сожрут, а так без кода ничего и не скажешь.Можно подробнее насчёт таймеров? Я использую функцию CreateThread, с ней вроде нет никаких проблем по части производительности даже когда таких потоков очень много.
Для каких задач мы используем потоки: когда надо сделать бесконечный цикл, и когда нужно сделать функцию с задержками, не прерывая выполнение всей программы. Как советуете решать эти задачи?Потоки зло. Они тебя сожрут, а так без кода ничего и не скажешь.
Код правильно писать. Задержки вообще плохая практика.Для каких задач мы используем потоки: когда надо сделать бесконечный цикл, и когда нужно сделать функцию с задержками, не прерывая выполнение всей программы. Как советуете решать эти задачи?
Так себе совет, если честно. Придётся дальше на потоках сидеть.Код правильно писать. Задержки вообще плохая практика.
@Dark_Knight, наверное, говорит про написание DLL библиотек, где создание потоков и взаимодействие с памятью приложения может вызвать UB, к примеру из-за одновременного изменения того же участка памяти, так как это будет довольно сложно предотвратить. В создание самостоятельной программы, в использование потоков я не вижу ничего плохого, но надо уметь с ними работать чтобы не происходили возможные проблемы с ними.Для каких задач мы используем потоки: когда надо сделать бесконечный цикл, и когда нужно сделать функцию с задержками, не прерывая выполнение всей программы. Как советуете решать эти задачи?
Dark Knight просто немножко чепуху задвигает, потому что это не программист решает, что ему нужна задержка, а в основном так просто стоит задача. Часто сталкиваюсь с UB, например вот артефакты и странные зависания при эмуляции входящих RPC в потоке:@Dark_Knight, наверное, говорит про написание DLL библиотек, где создание потоков и взаимодействие с памятью приложения может вызвать UB, к примеру из-за одновременного изменения того же участка памяти, так как это будет довольно сложно предотвратить. В создание самостоятельной программы, в использование потоков я не вижу ничего плохого, но надо уметь с ними работать чтобы не происходили возможные проблемы с ними.
Либо что-то типа такогоКорутины
static bool Process = false;
static unsigned long dwStartTick{ GetTickCount() };
if (Process && GetTickCount() - dwStartTick > 5000) {
//Код который должен срабатывать через 5 секунд
Process = false;
}
if (NeedToSendMessage) {
Process = true;
dwStartTick = GetTickCount();
NeedToSendMessage = false
}
Корутины выглядят непонятно, но многообещающе. Функция, которую можно приостановить — это то, что надо. Надеюсь оно заработает в ГТА и СФ.Либо что-то типа такого
Вместо GetTickCount можно использовать std::chrono::steady_clock()C++:static bool Process = false; static unsigned long dwStartTick{ GetTickCount() }; if (Process && GetTickCount() - dwStartTick > 5000) { //Код который должен срабатывать через 5 секунд Process = false; } if (NeedToSendMessage) { Process = true; dwStartTick = GetTickCount(); NeedToSendMessage = false }
upd: сейчас подумал, и понял что корутины будут использовать такой же принцип работы
А вот про первое ты как раз вообще не прав. Как программист решает, как решить задачу, а не задача решает, как код программисту решить.потому что это не программист решает, что ему нужна задержка, а в основном так просто стоит задача.
На видео эмуляция различных RPC для установки позиции и направления камеры, их всего пять примерно, когда-то задавал вопрос по этой теме и ответа так и не нашлось, поэтому сделал через RakNet. Что касается задержек, то программист, к сожалению, время выворачивать не может, если задача требует паузы между действиями (а таких задач 50% на практике), то никуда тут не деться, потоками, таймерами или колбэками всё равно придётся добиваться задержки.А вот про первое ты как раз вообще не прав. Как программист решает, как решить задачу, а не задача решает, как код программисту решить.
и что же за РПЦ ты там эмулируешь, что ловишь такие артефакты?)
Тебе вон выше дали хорошую либу для таймеров. Ты в ГТА вообще забудь про слово поток. Это крайне плохая практика в этом сегменте.
Вот тебе еще одна
GitHub - skyformat99/TimerManager: Crossplatform library for simple working with timers
Crossplatform library for simple working with timers - skyformat99/TimerManagergithub.com
По поводу таймера. Правильно ли я понял, что вот эта функция в timer_manager::add_timer сработает как надо только если цикл будет постоянно бегать по ней? Допустим есть основной цикл с !timer_manager::process() и есть функция (допустим ввод команды в игре), которая отрабатывает один раз, в этой функции будет timer_manager::add_timer, оно сработает в таком случае или add_timer нужно вызывать каждую миллисекунду?А вот про первое ты как раз вообще не прав. Как программист решает, как решить задачу, а не задача решает, как код программисту решить.
и что же за РПЦ ты там эмулируешь, что ловишь такие артефакты?)
Тебе вон выше дали хорошую либу для таймеров. Ты в ГТА вообще забудь про слово поток. Это крайне плохая практика в этом сегменте.
Вот тебе еще одна
GitHub - skyformat99/TimerManager: Crossplatform library for simple working with timers
Crossplatform library for simple working with timers - skyformat99/TimerManagergithub.com