Multithreading
There are some utilities for using AngelScript in the multithreading environment.
Note
AngelScript does not support multithreading on all platforms.
-
inline bool asbind20::has_threads(const char *options = asGetLibraryOptions())
Check if
asGetLibraryOptions()doesn’t return"AS_NO_THREADS"
Initializing and Cleaning the Multithreading Environment
According to the official document, AngelScript needs some additional efforts to work in the multithreading environment.
The following functions are provided by the external header concurrent/threading.hpp.
-
inline void asbind20::concurrent::auto_thread_cleanup() noexcept
Mark this thread needs to clean up AngelScript data before terminating.
It’s safe to call this function for the second time in the same thread.
Note
Remember to call this function in any thread other than main thread to prevent memory leak.
-
inline void asbind20::concurrent::prepare_multithread(asIThreadManager *external_mgr = nullptr)
Call this function in the main thread to prepare for multithreading.
Warning
Call this function before any script engine is created, and make sure global variables don’t contain any script engine that may be released after
asUnprepareMultithreadbeing called.
Example code:
#include <thread>
#include <asbind20/asbind.hpp>
#include <asbind20/concurrent/threading.hpp>
int main()
{
if(!asbind20::has_threads())
{
std::cerr << "AS_NO_THREADS" << std::endl;
return 1;
}
using namespace asbind20;
concurrent::prepare_multithread();
auto engine = make_script_engine();
auto* m = engine->GetModule(
"script_multithreading", asGM_ALWAYS_CREATE
);
m->AddScriptSection(
"script_multithreading",
"int fn(int arg) { return arg * 2; }"
);
m->Build();
auto* f = m->GetFunctionByName("fn");
std::condition_variable cv;
std::mutex mx;
int result = -1;
auto helper = [&, f](int arg)
{
concurrent::auto_thread_cleanup();
{
using namespace std::chrono_literals;
request_context ctx(engine);
std::this_thread::sleep_for(3ms); // Emulates running a complex script
auto r = script_invoke<int>(ctx, f, arg);
std::unique_lock lock(mx);
result = r.value();
}
cv.notify_all();
};
std::thread thr(helper, 10);
thr.detach();
{
std::unique_lock lock(mx);
cv.wait(lock);
}
assert(result == 20);
return 0;
}
Locks
The weak reference flag (asILockableSharedBool*) is lockable.
The lockable_shared_bool class (documented in RAII Helpers) wraps the weak reference flag for use with std::lock_guard.
The AngelScript library provides global exclusive and shared locks.
The wrappers for them are provided by the header <asbind20/concurrent/mutex.hpp>.
-
constexpr script_lock_t asbind20::script_lock = {}
Global lock of AngelScript library.
-
class script_lock_t
Wrapper for global lock of AngelScript library.
Example code:
{
std::unique_lock lk(asbind20::script_lock);
// Writing
}
{
std::shared_lock lk(asbind20::script_lock);
// Reading
}
Atomic Reference Counting
-
class atomic_counter
Atomic counter for multithreading.
This wraps the
asAtomicIncandasAtomicDec.Note
Its initial value will be 1.
Increment and decrement operators
Even the prefix increment / decrement will return
intvalue directly, which is similar to how thestd::atomic<T>does.-
inline int operator++() noexcept
-
inline int operator--() noexcept
Public Types
-
using value_type = int
Public Functions
-
inline atomic_counter() noexcept
Construct a new atomic counter and set the counter value to 1.
-
atomic_counter(const atomic_counter&) = default
-
inline atomic_counter(int val) noexcept
-
~atomic_counter() = default
-
atomic_counter &operator=(const atomic_counter&) noexcept = default
-
inline atomic_counter &operator=(int val) noexcept
-
bool operator==(const atomic_counter&) const = default
-
inline int inc() noexcept
-
inline int dec() noexcept
-
inline operator int() const noexcept
-
inline int operator++() noexcept
For garbage collected types, please read the official document about thread safety and GC.