diff --git a/.efrocachemap b/.efrocachemap
index 5ba23826..d082ff3c 100644
--- a/.efrocachemap
+++ b/.efrocachemap
@@ -3995,50 +3995,50 @@
"assets/src/ba_data/python/ba/_generated/__init__.py": "https://files.ballistica.net/cache/ba1/ee/e8/cad05aa531c7faf7ff7b96db7f6e",
"assets/src/ba_data/python/ba/_generated/enums.py": "https://files.ballistica.net/cache/ba1/b2/e5/0ee0561e16257a32830645239f34",
"ballisticacore-windows/Generic/BallisticaCore.ico": "https://files.ballistica.net/cache/ba1/89/c0/e32c7d2a35dc9aef57cc73b0911a",
- "build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/cb/30/c0e7d89b368751cf26b1cef50664",
- "build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/67/14/230fd06e06cb9040a03f6e74c1d7",
- "build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b6/59/c8badf86a08fa213610edbcfedac",
- "build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/f0/13/399ce592b72284029a6291b89a0e",
- "build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/ae/4c/84fcfbec817118d204402be28de8",
- "build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/46/c0/9f10a2154b3ccb59a9710492c1c8",
- "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/68/9b/b68e52f40fbab1c3a8cf3a26c596",
- "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/2e/f4/ab1229ec3bda80f8f47c3cf8bc62",
- "build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/9d/3b/3bd29560197990be6a4da17604b8",
- "build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/d1/4f/9fb5889baf79de40ced767a75f47",
- "build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/4b/b0/7854b4f01fd1516fdb2aaabe74af",
- "build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/5d/4d/70ee88bd453725a3af8469b832a9",
- "build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/bd/df/b2fdbba76d96d5d64ae222a9cb5f",
- "build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/4b/d5/01958f073d57e11b8a7af71c88b2",
- "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/38/f0/9f544b99cd379536e7b776e726ab",
- "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ff/7f/96e6a7b76cf6c5a2b2cd381e4700",
- "build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/10/58/8dea7e5b6987346f9116d3758a6b",
- "build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/7f/cd/93c54dc256e1b3c3575d44efb730",
- "build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/d0/d0/8d9ae932ed95175a9aae1310de96",
- "build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/d9/30/7b9bf572809afa6102afb5c396c4",
- "build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/4f/62/10fba4712bc7c1649de95f6d435a",
- "build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7f/74/101f9c7cdbea3924a3eb753372b8",
- "build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/3d/10/0213350b34d61574be888f434776",
- "build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/2f/69/3195bc2ac8ab95a072deb6328383",
- "build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/fb/b8/1d53882382e1bdffea589b8abd52",
- "build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/66/7d/4cf7e08113052eae664b714bdc64",
- "build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0a/3e/0e759cd0a7a1e098e3c1daff0827",
- "build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8a/a0/eb48807010d1e7fa6a4956d0967e",
- "build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/45/1b/cd3972f7bb9cb4a7d4bfeb0977fb",
- "build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b2/c1/92b3546f4ea454e3813062e7c2a0",
- "build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d8/7f/694dfd1b8580077fd1d3ab585611",
- "build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8c/ea/38c4415b9582016f40ecb9c371f6",
- "build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/2d/54/3f42d8cbbabb633fe47dc9e63f8b",
- "build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e0/9c/78bc9f3658e495238a9ae7095ad0",
- "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/3e/60/48c02923c5c7e7b8a3a705cdbe49",
- "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7b/cb/93116682d10e6f868ec9215c0ab2",
- "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/98/9b/43700428b53a552af3f32aa2577c",
- "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/37/e2/b6da8c9dd13e91ebb705da51c653",
- "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/f5/93/774197e1f445c4dee88ed2910006",
- "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/2e/7c/139654fe813f9254ed5de42c7ef7",
- "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/ef/ea/8ccb18f593d003984a1f56cf0c78",
- "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/99/f6/7e56f9dd76d97493a53ebe755fba",
- "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/cf/d5/2d58578076ced4f6e2b218b18d11",
- "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/a2/07/d85112deb0bf08aa01d18f098b94",
+ "build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/30/30/76f78a5f222c39ea755b5098b51f",
+ "build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/34/fd/2d0510b7da8899c78378296e38d3",
+ "build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/5b/49/356d0f8f7fee022b778ba14d6612",
+ "build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/bb/ee/7d33058363bb336fa9c52eb87207",
+ "build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/b4/88/1574d641b1ea03e7f6e388f614f9",
+ "build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/bb/09/a68b6c70115f316fc5c044286e53",
+ "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/44/47/02f87d28d4b3129f32e6233c34f5",
+ "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/09/4f/fea5a0cd8b43fd4bfa91238c584e",
+ "build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/c8/4a/769908c66c6d1eb74c8103ff5c30",
+ "build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/c8/33/2067e22417e6546ebc62623a9186",
+ "build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/d1/62/eb550f8507ff920da54219ff195b",
+ "build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/2d/91/3b78ced38a1060fc6fe85438792c",
+ "build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/84/eb/9de1b6c883311cbd8729341599b9",
+ "build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/d3/3b/86294ecdabdce129672784085280",
+ "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/51/07/0037ac9ef4cea6bc3bfdb3682729",
+ "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/29/e2/f84c711e2c7cc601dd5847cc60c1",
+ "build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/99/17/17a739a9a1e2f19449a5756a5c19",
+ "build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/71/bc/e74bae5930032177abc44078e056",
+ "build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/1e/6c/5b7173be93adfc9c0e1d007cf65e",
+ "build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/bc/07/b08c86874771ee922da097fb0b06",
+ "build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8f/63/9dc4b8c56eaf6ee5259e4b60bc46",
+ "build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e3/25/692a46a2437c11055c58d95f0a10",
+ "build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/06/8f/1f7fcebee0a16c8f843cabebba1c",
+ "build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ec/c2/51a05d1066c208b3a17e8828238e",
+ "build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a8/e3/88791ad2fbd654a60e6652e64554",
+ "build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/6b/06/86d995f8ea1b6e27ac3b9818e267",
+ "build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f3/7d/b632f966f8ae8c39dc9015fb8eee",
+ "build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e9/9e/39dd389564d0a14f01bdb54b82ce",
+ "build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/cb/7e/e865aa9e850350deefa7a826b89e",
+ "build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/9d/1f/20ea75eb2a38a5aa740aebf68893",
+ "build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/35/87/49cc3fb53218a2c19633551d0f38",
+ "build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ac/38/4fc5345b0bbc0cc6965d510b2074",
+ "build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b3/b0/c4f8ff30c9b62d2d0dbc926095fa",
+ "build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ec/96/b22889b59ba3279627d8de232a23",
+ "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0e/6b/3b6758dd4b6b63ab9f666af9396a",
+ "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/65/8c/6fa15f798f6ca73d753571f8cd4b",
+ "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/2d/af/9cc4b56883bcd72f65b9a814c401",
+ "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/5a/18/c0ff4809d4550c794a516a320ed1",
+ "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/27/25/4b3bd86f0ad71b2ad29ea8a9837d",
+ "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/2f/1a/29105b0e71173826d2ea404982b6",
+ "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/b7/8a/3f0476b3981a630cc6ef8f1ec364",
+ "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/4d/32/9ffcdc35d17ac6c9e3bb2bfd0e3c",
+ "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/be/f0/8901dcd613fec9e58d02b08dce4b",
+ "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/e3/c1/f79676f11b4f4778e26933ba42d7",
"src/ballistica/generated/python_embedded/binding.inc": "https://files.ballistica.net/cache/ba1/7d/3e/229a581cb2454ed856f1d8b564a7",
"src/ballistica/generated/python_embedded/bootstrap.inc": "https://files.ballistica.net/cache/ba1/98/12/571b2160d69d42580e8f31fa6a8d"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ada6f6c1..42844b2f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-### 1.7.7 (build 20778, api 7, 2022-09-06)
+### 1.7.7 (build 20794, api 7, 2022-09-09)
- Added `ba.app.meta.load_exported_classes()` for loading classes discovered by the meta subsystem cleanly in a background thread.
- Improved logging of missing playlist game types.
- Some ba.Lstr functionality can now be used in background threads.
diff --git a/assets/src/ba_data/python/._bainternal_sources_hash b/assets/src/ba_data/python/._bainternal_sources_hash
index 21679383..26863289 100644
--- a/assets/src/ba_data/python/._bainternal_sources_hash
+++ b/assets/src/ba_data/python/._bainternal_sources_hash
@@ -1 +1 @@
-161826047581351482927423840323346436406
\ No newline at end of file
+265405600297036989512577170988205019181
\ No newline at end of file
diff --git a/assets/src/ba_data/python/ba/_bootstrap.py b/assets/src/ba_data/python/ba/_bootstrap.py
index e1a87446..da44550e 100644
--- a/assets/src/ba_data/python/ba/_bootstrap.py
+++ b/assets/src/ba_data/python/ba/_bootstrap.py
@@ -3,6 +3,9 @@
"""Bootstrapping."""
from __future__ import annotations
+import os
+import sys
+import signal
import threading
from typing import TYPE_CHECKING
@@ -11,6 +14,8 @@ import _ba
if TYPE_CHECKING:
from typing import Any, TextIO, Callable
+_g_did_bootstrap = False # pylint: disable=invalid-name
+
def bootstrap() -> None:
"""Run bootstrapping logic.
@@ -18,9 +23,10 @@ def bootstrap() -> None:
This is the very first userland code that runs.
It sets up low level environment bits and creates the app instance.
"""
- import os
- import sys
- import signal
+ global _g_did_bootstrap # pylint: disable=global-statement, invalid-name
+ if _g_did_bootstrap:
+ raise RuntimeError('Bootstrap has already been called.')
+ _g_did_bootstrap = True
# The first thing we set up is capturing/redirecting Python
# stdout/stderr so we can at least debug problems on systems where
@@ -32,7 +38,7 @@ def bootstrap() -> None:
# Give a soft warning if we're being used with a different binary
# version than we expect.
- expected_build = 20778
+ expected_build = 20794
running_build: int = env['build_number']
if running_build != expected_build:
print(
diff --git a/ballisticacore-cmake/CMakeLists.txt b/ballisticacore-cmake/CMakeLists.txt
index e2732f5e..010064e4 100644
--- a/ballisticacore-cmake/CMakeLists.txt
+++ b/ballisticacore-cmake/CMakeLists.txt
@@ -241,8 +241,6 @@ add_executable(ballisticacore
${BA_SRC_ROOT}/ballistica/core/logging.h
${BA_SRC_ROOT}/ballistica/core/macros.cc
${BA_SRC_ROOT}/ballistica/core/macros.h
- ${BA_SRC_ROOT}/ballistica/core/module.cc
- ${BA_SRC_ROOT}/ballistica/core/module.h
${BA_SRC_ROOT}/ballistica/core/object.cc
${BA_SRC_ROOT}/ballistica/core/object.h
${BA_SRC_ROOT}/ballistica/core/thread.cc
diff --git a/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj b/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj
index d5eb5a98..e262bb74 100644
--- a/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj
+++ b/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj
@@ -232,8 +232,6 @@
-
-
diff --git a/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj.filters b/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj.filters
index 7f4a0667..72b42275 100644
--- a/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj.filters
+++ b/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj.filters
@@ -130,12 +130,6 @@
ballistica\core
-
- ballistica\core
-
-
- ballistica\core
-
ballistica\core
diff --git a/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj b/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj
index d17d70c4..e1c85303 100644
--- a/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj
+++ b/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj
@@ -227,8 +227,6 @@
-
-
diff --git a/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj.filters b/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj.filters
index 7f4a0667..72b42275 100644
--- a/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj.filters
+++ b/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj.filters
@@ -130,12 +130,6 @@
ballistica\core
-
- ballistica\core
-
-
- ballistica\core
-
ballistica\core
diff --git a/src/ballistica/app/app.cc b/src/ballistica/app/app.cc
index c0996f34..7c2843e1 100644
--- a/src/ballistica/app/app.cc
+++ b/src/ballistica/app/app.cc
@@ -17,7 +17,7 @@
namespace ballistica {
App::App(Thread* thread)
- : Module("app", thread), stress_test_(std::make_unique()) {
+ : thread_(thread), stress_test_(std::make_unique()) {
assert(g_app == nullptr);
g_app = this;
@@ -37,8 +37,6 @@ void App::PostInit() {
g_platform->SetHardwareCursorVisible(g_buildconfig.hardware_cursor());
}
-App::~App() = default;
-
auto App::ManagesEventLoop() const -> bool {
// We have 2 redundant values for essentially the same thing;
// should get rid of IsEventPushMode() once we've created
@@ -104,7 +102,7 @@ void App::SetScreenResolution(float width, float height) {
}
void App::PushShutdownCompleteCall() {
- PushCall([this] { ShutdownComplete(); });
+ thread()->PushCall([this] { ShutdownComplete(); });
}
void App::ShutdownComplete() {
@@ -154,8 +152,9 @@ void App::OnPause() {
g_graphics->SetGyroEnabled(false);
// IMPORTANT: Any on-pause related stuff that threads need to do must
- // be done from their HandleThreadPause(). If we push runnables to them,
- // they may or may not be called before the thread is actually paused.
+ // be done from registered pause-callbacks. If we instead push runnables
+ // to them from here they may or may not be called before the thread
+ // is actually paused.
Thread::SetThreadsPaused(true);
@@ -210,7 +209,7 @@ void App::OnResume() {
}
auto App::GetProductPrice(const std::string& product) -> std::string {
- std::lock_guard lock(product_prices_mutex_);
+ std::scoped_lock lock(product_prices_mutex_);
auto i = product_prices_.find(product);
if (i == product_prices_.end()) {
return "";
@@ -221,7 +220,7 @@ auto App::GetProductPrice(const std::string& product) -> std::string {
void App::SetProductPrice(const std::string& product,
const std::string& price) {
- std::lock_guard lock(product_prices_mutex_);
+ std::scoped_lock lock(product_prices_mutex_);
product_prices_[product] = price;
}
@@ -261,7 +260,7 @@ void App::PrimeEventPump() {
void App::PushShowOnlineScoreUICall(const std::string& show,
const std::string& game,
const std::string& game_version) {
- PushCall([show, game, game_version] {
+ thread()->PushCall([show, game, game_version] {
assert(InMainThread());
g_platform->ShowOnlineScoreUI(show, game, game_version);
});
@@ -269,7 +268,7 @@ void App::PushShowOnlineScoreUICall(const std::string& show,
void App::PushNetworkSetupCall(int port, int telnet_port, bool enable_telnet,
const std::string& telnet_password) {
- PushCall([port, telnet_port, enable_telnet, telnet_password] {
+ thread()->PushCall([port, telnet_port, enable_telnet, telnet_password] {
assert(InMainThread());
// Kick these off if they don't exist.
// (do we want to support changing ports on existing ones?)
@@ -290,58 +289,59 @@ void App::PushNetworkSetupCall(int port, int telnet_port, bool enable_telnet,
void App::PushPurchaseAckCall(const std::string& purchase,
const std::string& order_id) {
- PushCall(
+ thread()->PushCall(
[purchase, order_id] { g_platform->PurchaseAck(purchase, order_id); });
}
void App::PushGetScoresToBeatCall(const std::string& level,
const std::string& config,
void* py_callback) {
- PushCall([level, config, py_callback] {
+ thread()->PushCall([level, config, py_callback] {
assert(InMainThread());
g_platform->GetScoresToBeat(level, config, py_callback);
});
}
void App::PushPurchaseCall(const std::string& item) {
- PushCall([item] {
+ thread()->PushCall([item] {
assert(InMainThread());
g_platform->Purchase(item);
});
}
void App::PushRestorePurchasesCall() {
- PushCall([] {
+ thread()->PushCall([] {
assert(InMainThread());
g_platform->RestorePurchases();
});
}
void App::PushOpenURLCall(const std::string& url) {
- PushCall([url] { g_platform->OpenURL(url); });
+ thread()->PushCall([url] { g_platform->OpenURL(url); });
}
void App::PushGetFriendScoresCall(const std::string& game,
const std::string& game_version, void* data) {
- PushCall([game, game_version, data] {
+ thread()->PushCall([game, game_version, data] {
g_platform->GetFriendScores(game, game_version, data);
});
}
void App::PushSubmitScoreCall(const std::string& game,
const std::string& game_version, int64_t score) {
- PushCall([game, game_version, score] {
+ thread()->PushCall([game, game_version, score] {
g_platform->SubmitScore(game, game_version, score);
});
}
void App::PushAchievementReportCall(const std::string& achievement) {
- PushCall([achievement] { g_platform->ReportAchievement(achievement); });
+ thread()->PushCall(
+ [achievement] { g_platform->ReportAchievement(achievement); });
}
void App::PushStringEditCall(const std::string& name, const std::string& value,
int max_chars) {
- PushCall([name, value, max_chars] {
+ thread()->PushCall([name, value, max_chars] {
static millisecs_t last_edit_time = 0;
millisecs_t t = GetRealTime();
@@ -357,13 +357,13 @@ void App::PushStringEditCall(const std::string& name, const std::string& value,
}
void App::PushSetStressTestingCall(bool enable, int player_count) {
- PushCall([this, enable, player_count] {
+ thread()->PushCall([this, enable, player_count] {
stress_test_->SetStressTesting(enable, player_count);
});
}
void App::PushResetAchievementsCall() {
- PushCall([] { g_platform->ResetAchievements(); });
+ thread()->PushCall([] { g_platform->ResetAchievements(); });
}
void App::OnBootstrapComplete() {
@@ -386,7 +386,7 @@ void App::OnBootstrapComplete() {
}
void App::PushCursorUpdate(bool vis) {
- PushCall([vis] {
+ thread()->PushCall([vis] {
assert(InMainThread());
g_platform->SetHardwareCursorVisible(vis);
});
diff --git a/src/ballistica/app/app.h b/src/ballistica/app/app.h
index 3bfa0878..2f6052af 100644
--- a/src/ballistica/app/app.h
+++ b/src/ballistica/app/app.h
@@ -8,17 +8,17 @@
#include
#include
-#include "ballistica/core/module.h"
+#include "ballistica/app/stress_test.h"
+#include "ballistica/ballistica.h"
namespace ballistica {
/// Our high level app interface module.
/// It runs in the main thread and is what platform wrappers
/// should primarily interact with.
-class App : public Module {
+class App {
public:
explicit App(Thread* thread);
- ~App() override;
/// This gets run after the constructor completes.
/// Any setup that may trigger a virtual method/etc. should go here.
@@ -124,12 +124,14 @@ class App : public Module {
auto PushNetworkSetupCall(int port, int telnet_port, bool enable_telnet,
const std::string& telnet_password) -> void;
auto PushShutdownCompleteCall() -> void;
+ auto thread() const -> Thread* { return thread_; }
private:
auto UpdatePauseResume() -> void;
auto OnPause() -> void;
auto OnResume() -> void;
auto ShutdownComplete() -> void;
+ Thread* thread_{};
bool done_{};
bool server_wrapper_managed_{};
bool sys_paused_app_{};
diff --git a/src/ballistica/app/app_globals.h b/src/ballistica/app/app_globals.h
index b0813107..e65d510a 100644
--- a/src/ballistica/app/app_globals.h
+++ b/src/ballistica/app/app_globals.h
@@ -31,6 +31,7 @@ class AppGlobals {
/// Program argument values (on applicable platforms).
char** argv{};
+ bool threads_paused{};
std::unordered_map node_types;
std::unordered_map node_types_by_id;
std::unordered_map node_message_types;
diff --git a/src/ballistica/app/headless_app.cc b/src/ballistica/app/headless_app.cc
index 817fef47..4da24f9e 100644
--- a/src/ballistica/app/headless_app.cc
+++ b/src/ballistica/app/headless_app.cc
@@ -13,10 +13,10 @@ HeadlessApp::HeadlessApp(Thread* thread) : App(thread) {
// Handle a few misc things like stress-test updates.
// (SDL builds set up a similar timer so we need to also).
// This can probably go away at some point.
- NewThreadTimer(10, true, NewLambdaRunnable([this] {
- assert(g_app);
- g_app->RunEvents();
- }));
+ this->thread()->NewTimer(10, true, NewLambdaRunnable([this] {
+ assert(g_app);
+ g_app->RunEvents();
+ }));
}
} // namespace ballistica
diff --git a/src/ballistica/app/vr_app.cc b/src/ballistica/app/vr_app.cc
index 25de8698..2fa3569f 100644
--- a/src/ballistica/app/vr_app.cc
+++ b/src/ballistica/app/vr_app.cc
@@ -3,6 +3,7 @@
#include "ballistica/app/vr_app.h"
+#include "ballistica/core/thread.h"
#include "ballistica/game/game.h"
#include "ballistica/graphics/graphics_server.h"
#include "ballistica/graphics/renderer.h"
@@ -13,7 +14,7 @@ VRApp::VRApp(Thread* thread) : App(thread) {}
auto VRApp::PushVRSimpleRemoteStateCall(const VRSimpleRemoteState& state)
-> void {
- PushCall([this, state] {
+ thread()->PushCall([this, state] {
// Convert this to a full hands state, adding in some simple elbow
// positioning of our own and left/right.
VRHandsState s;
diff --git a/src/ballistica/audio/audio.cc b/src/ballistica/audio/audio.cc
index ee2f2fa3..95238edc 100644
--- a/src/ballistica/audio/audio.cc
+++ b/src/ballistica/audio/audio.cc
@@ -4,6 +4,7 @@
#include "ballistica/audio/audio_server.h"
#include "ballistica/audio/audio_source.h"
+#include "ballistica/core/thread.h"
#include "ballistica/media/data/sound_data.h"
namespace ballistica {
@@ -40,11 +41,12 @@ void Audio::SetListenerOrientation(const Vector3f& forward,
// This stops a particular sound play ID only.
void Audio::PushSourceStopSoundCall(uint32_t play_id) {
- g_audio_server->PushCall([play_id] { g_audio_server->StopSound(play_id); });
+ g_audio_server->thread()->PushCall(
+ [play_id] { g_audio_server->StopSound(play_id); });
}
void Audio::PushSourceFadeOutCall(uint32_t play_id, uint32_t time) {
- g_audio_server->PushCall(
+ g_audio_server->thread()->PushCall(
[play_id, time] { g_audio_server->FadeSoundOut(play_id, time); });
}
@@ -60,7 +62,7 @@ auto Audio::SourceBeginNew() -> AudioSource* {
// Got to make sure to hold this until we've locked the source.
// Otherwise, theoretically, the audio thread could make our source
// available again before we can use it.
- std::lock_guard lock(available_sources_mutex_);
+ std::lock_guard lock(available_sources_mutex_);
// If there's an available source, reserve and return it.
auto i = available_sources_.begin();
diff --git a/src/ballistica/audio/audio.h b/src/ballistica/audio/audio.h
index 4185d5b6..3a0b40d0 100644
--- a/src/ballistica/audio/audio.h
+++ b/src/ballistica/audio/audio.h
@@ -7,7 +7,6 @@
#include
#include
-#include "ballistica/core/module.h"
#include "ballistica/core/object.h"
namespace ballistica {
diff --git a/src/ballistica/audio/audio_server.cc b/src/ballistica/audio/audio_server.cc
index fec5d497..598bbc2e 100644
--- a/src/ballistica/audio/audio_server.cc
+++ b/src/ballistica/audio/audio_server.cc
@@ -8,6 +8,7 @@
#include "ballistica/audio/audio_source.h"
#include "ballistica/audio/audio_streamer.h"
#include "ballistica/audio/ogg_stream.h"
+#include "ballistica/core/thread.h"
#include "ballistica/game/game.h"
#include "ballistica/generic/timer.h"
#include "ballistica/math/vector3f.h"
@@ -195,7 +196,7 @@ void AudioServer::SetPaused(bool pause) {
}
void AudioServer::PushSourceSetIsMusicCall(uint32_t play_id, bool val) {
- PushCall([this, play_id, val] {
+ thread()->PushCall([this, play_id, val] {
ThreadSource* s = GetPlayingSound(play_id);
if (s) {
s->SetIsMusic(val);
@@ -204,7 +205,7 @@ void AudioServer::PushSourceSetIsMusicCall(uint32_t play_id, bool val) {
}
void AudioServer::PushSourceSetPositionalCall(uint32_t play_id, bool val) {
- PushCall([this, play_id, val] {
+ thread()->PushCall([this, play_id, val] {
ThreadSource* s = GetPlayingSound(play_id);
if (s) {
s->SetPositional(val);
@@ -214,7 +215,7 @@ void AudioServer::PushSourceSetPositionalCall(uint32_t play_id, bool val) {
void AudioServer::PushSourceSetPositionCall(uint32_t play_id,
const Vector3f& p) {
- PushCall([this, play_id, p] {
+ thread()->PushCall([this, play_id, p] {
ThreadSource* s = GetPlayingSound(play_id);
if (s) {
s->SetPosition(p.x, p.y, p.z);
@@ -223,7 +224,7 @@ void AudioServer::PushSourceSetPositionCall(uint32_t play_id,
}
void AudioServer::PushSourceSetGainCall(uint32_t play_id, float val) {
- PushCall([this, play_id, val] {
+ thread()->PushCall([this, play_id, val] {
ThreadSource* s = GetPlayingSound(play_id);
if (s) {
s->SetGain(val);
@@ -232,7 +233,7 @@ void AudioServer::PushSourceSetGainCall(uint32_t play_id, float val) {
}
void AudioServer::PushSourceSetFadeCall(uint32_t play_id, float val) {
- PushCall([this, play_id, val] {
+ thread()->PushCall([this, play_id, val] {
ThreadSource* s = GetPlayingSound(play_id);
if (s) {
s->SetFade(val);
@@ -241,7 +242,7 @@ void AudioServer::PushSourceSetFadeCall(uint32_t play_id, float val) {
}
void AudioServer::PushSourceSetLoopingCall(uint32_t play_id, bool val) {
- PushCall([this, play_id, val] {
+ thread()->PushCall([this, play_id, val] {
ThreadSource* s = GetPlayingSound(play_id);
if (s) {
s->SetLooping(val);
@@ -251,7 +252,7 @@ void AudioServer::PushSourceSetLoopingCall(uint32_t play_id, bool val) {
void AudioServer::PushSourcePlayCall(uint32_t play_id,
Object::Ref* sound) {
- PushCall([this, play_id, sound] {
+ thread()->PushCall([this, play_id, sound] {
ThreadSource* s = GetPlayingSound(play_id);
// If this play command is valid, pass it along.
@@ -271,7 +272,7 @@ void AudioServer::PushSourcePlayCall(uint32_t play_id,
}
void AudioServer::PushSourceStopCall(uint32_t play_id) {
- PushCall([this, play_id] {
+ thread()->PushCall([this, play_id] {
ThreadSource* s = GetPlayingSound(play_id);
if (s) {
s->Stop();
@@ -280,7 +281,7 @@ void AudioServer::PushSourceStopCall(uint32_t play_id) {
}
void AudioServer::PushSourceEndCall(uint32_t play_id) {
- PushCall([this, play_id] {
+ thread()->PushCall([this, play_id] {
ThreadSource* s = GetPlayingSound(play_id);
assert(s);
s->client_source()->Lock(5);
@@ -292,11 +293,11 @@ void AudioServer::PushSourceEndCall(uint32_t play_id) {
}
void AudioServer::PushResetCall() {
- PushCall([this] { Reset(); });
+ thread()->PushCall([this] { Reset(); });
}
void AudioServer::PushSetListenerPositionCall(const Vector3f& p) {
- PushCall([this, p] {
+ thread()->PushCall([this, p] {
#if BA_ENABLE_AUDIO
if (!paused_) {
ALfloat lpos[3] = {p.x, p.y, p.z};
@@ -309,7 +310,7 @@ void AudioServer::PushSetListenerPositionCall(const Vector3f& p) {
void AudioServer::PushSetListenerOrientationCall(const Vector3f& forward,
const Vector3f& up) {
- PushCall([this, forward, up] {
+ thread()->PushCall([this, forward, up] {
#if BA_ENABLE_AUDIO
if (!paused_) {
ALfloat lorient[6] = {forward.x, forward.y, forward.z, up.x, up.y, up.z};
@@ -321,17 +322,17 @@ void AudioServer::PushSetListenerOrientationCall(const Vector3f& forward,
}
AudioServer::AudioServer(Thread* thread)
- : Module("audio", thread),
- impl_{new AudioServer::Impl()}
-// impl_{std::make_unique()}
-{
+ : thread_(thread), impl_{new AudioServer::Impl()} {
// we're a singleton...
assert(g_audio_server == nullptr);
g_audio_server = this;
+ thread->AddPauseCallback(NewLambdaRunnableRaw([this] { OnThreadPause(); }));
+ thread->AddResumeCallback(NewLambdaRunnableRaw([this] { OnThreadResume(); }));
+
// Get our thread to give us periodic processing time.
- process_timer_ = NewThreadTimer(kAudioProcessIntervalNormal, true,
- NewLambdaRunnable([this] { Process(); }));
+ process_timer_ = thread->NewTimer(kAudioProcessIntervalNormal, true,
+ NewLambdaRunnable([this] { Process(); }));
#if BA_ENABLE_AUDIO
@@ -782,8 +783,7 @@ void AudioServer::ThreadSource::UpdateAvailability() {
if (!busy) {
if (g_audio->available_sources_mutex().try_lock()) {
- std::lock_guard lock(g_audio->available_sources_mutex(),
- std::adopt_lock);
+ std::lock_guard lock(g_audio->available_sources_mutex(), std::adopt_lock);
Stop();
Reset();
#if BA_DEBUG_BUILD
@@ -1074,18 +1074,18 @@ void AudioServer::ThreadSource::UpdatePitch() {
}
void AudioServer::PushSetVolumesCall(float music_volume, float sound_volume) {
- PushCall([this, music_volume, sound_volume] {
+ thread()->PushCall([this, music_volume, sound_volume] {
SetSoundVolume(sound_volume);
SetMusicVolume(music_volume);
});
}
void AudioServer::PushSetSoundPitchCall(float val) {
- PushCall([this, val] { SetSoundPitch(val); });
+ thread()->PushCall([this, val] { SetSoundPitch(val); });
}
void AudioServer::PushSetPausedCall(bool pause) {
- PushCall([this, pause] {
+ thread()->PushCall([this, pause] {
if (g_buildconfig.ostype_android()) {
Log("Error: Shouldn't be getting SetPausedCall on android.");
}
@@ -1095,7 +1095,7 @@ void AudioServer::PushSetPausedCall(bool pause) {
void AudioServer::PushComponentUnloadCall(
const std::vector*>& components) {
- PushCall([this, components] {
+ thread()->PushCall([this, components] {
// Unload all components we were passed...
for (auto&& i : components) {
(**i).Unload();
@@ -1107,7 +1107,7 @@ void AudioServer::PushComponentUnloadCall(
}
void AudioServer::PushHavePendingLoadsCall() {
- PushCall([this] {
+ thread()->PushCall([this] {
have_pending_loads_ = true;
UpdateTimerInterval();
});
@@ -1115,16 +1115,16 @@ void AudioServer::PushHavePendingLoadsCall() {
void AudioServer::AddSoundRefDelete(const Object::Ref* c) {
{
- std::lock_guard lock(sound_ref_delete_list_mutex_);
+ std::scoped_lock lock(sound_ref_delete_list_mutex_);
sound_ref_delete_list_.push_back(c);
}
// Now push a call to the game thread to do the deletes.
- g_game->PushCall([] { g_audio_server->ClearSoundRefDeleteList(); });
+ g_game->thread()->PushCall([] { g_audio_server->ClearSoundRefDeleteList(); });
}
void AudioServer::ClearSoundRefDeleteList() {
assert(InLogicThread());
- std::lock_guard lock(sound_ref_delete_list_mutex_);
+ std::scoped_lock lock(sound_ref_delete_list_mutex_);
for (const Object::Ref* i : sound_ref_delete_list_) {
delete i;
}
@@ -1149,9 +1149,9 @@ void AudioServer::BeginInterruption() {
}
}
-void AudioServer::HandleThreadPause() { SetPaused(true); }
+auto AudioServer::OnThreadPause() -> void { SetPaused(true); }
-void AudioServer::HandleThreadResume() { SetPaused(false); }
+auto AudioServer::OnThreadResume() -> void { SetPaused(false); }
void AudioServer::EndInterruption() {
assert(!InAudioThread());
diff --git a/src/ballistica/audio/audio_server.h b/src/ballistica/audio/audio_server.h
index 53a5f00e..d747b98e 100644
--- a/src/ballistica/audio/audio_server.h
+++ b/src/ballistica/audio/audio_server.h
@@ -4,14 +4,15 @@
#define BALLISTICA_AUDIO_AUDIO_SERVER_H_
#include