Skip to main content

Module mainthread

Module mainthread 

Source
Expand description

Handing work back to the server’s main thread.

Both servers are single-threaded: every native, callback and tick runs on one thread, and the AMX VM must only ever be touched from it. A plugin that does I/O — HTTP, a database, SMTP — has to do that work elsewhere and bring the result back, because blocking the main thread freezes the server for every player.

This module is that return path. A worker thread calls post with a closure; the closure runs on the main thread on the next tick.

use samp::exec_public;
use samp::prelude::*;
std::thread::spawn(move || {
    let answer = 42; // ... the slow work ...

    samp::mainthread::post(move || {
        // Back on the main thread: safe to touch the VM.
        if let Some(amx) = samp::amx::get(amx_ident) {
            let _ = exec_public!(amx, "OnWorkDone", answer);
        }
    });
});

An AmxIdent is a plain address wrapper, so it crosses thread boundaries; the &Amx it resolves to does not, which is why the job looks it up again after arriving. samp::amx::get returns None if the script was unloaded meanwhile — the case this pattern makes easy to handle instead of dangling.

§Draining

Jobs run from the same place as SampPlugin::on_tick, so the plugin needs samp::plugin::enable_tick() in initialize_plugin!. Without it nothing drains the queue and jobs pile up; the SDK logs a warning once the backlog is large enough to be a mistake rather than a burst. A plugin that does not want the tick can call run_pending from wherever it prefers, such as inside a native.

A job posted while the queue is draining runs on the next tick, not the current one. That keeps a job that re-posts itself from spinning forever inside one tick.

Functions§

budget
The limit set_budget set, if any.
pending
Number of jobs waiting to run.
post
Queues job to run on the main thread at the next tick.
post_with
Queues job to run on the main thread with the plugin instance.
post_with_amx
Queues job to run on the main thread with the plugin and a resolved [Amx], in that order.
run_pending
Runs the queued jobs and returns how many ran: all of them, or as many as fit in the budget when one is set.
set_budget
Limits how long one drain spends running jobs; None (the default) runs every queued job.