moved more python init to main thread and public sources

This commit is contained in:
Eric 2022-09-13 10:24:56 -07:00
parent 53ccc66ca8
commit d9a1ab52e5
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
19 changed files with 318 additions and 240 deletions

View File

@ -3995,50 +3995,51 @@
"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/4c/c8/30631d3154a8c450b105da4fba36",
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/81/c8/19c1a99a50a074027e85485b48ef",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/5f/5f/93f8a60c6f6d58352a83540792ba",
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b5/1c/c0fe6d5570d238872bfc839b46ac",
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/b6/92/91c7675daecf9f2c01672f45b420",
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/f5/49/7fff46b30c288ffc7e94c9fd4182",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/e9/f3/99c96b36694274aab5f44f0a8c78",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/30/19/031ab0138f689d0fc7698c55f514",
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/78/9b/6613bcdbd99cba2abd8994da47e9",
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/85/83/8be76939bf30ad8d43d189099b4c",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/a5/bc/374eaeb09819570ba9b9c30707e0",
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/37/40/306b6050cc2ab7ce40b8a1935989",
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/03/6b/3bdea294966f3d6b5f86ab3f15f1",
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/e9/8f/86486943a8e2de808deb812cfdc6",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/33/72/b886fb6fdb0c36066da3a6d72f40",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/bb/e5/425b5f16ffaae0ade584872e6b1c",
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/a3/c9/44b771f906edf3d63943acd535a8",
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/17/b5/95fc75d8b8ee7dc24e2897309ff1",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/93/06/3ff8db73b443613e342010b8d26f",
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/60/09/d6e216de302ff8dfbb5966b08f90",
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/81/60/37044e17e52ca125c1d48af83d03",
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/fb/47/d505c3feea40888985dd335dc8c4",
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/4f/3d/20c78e744ac26a13b7418166d675",
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e3/77/67a1fafff2c1918b1661b71ecaa0",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/9b/00/f11d8f7f79c9b692b84f6dbd54dc",
"build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f8/3a/0cd5030cbe13f99bf23d05ee6cfb",
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/5b/2a/3be2a55cbd63f9c42618c4013c87",
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/09/ef/8fbfc6032e6a6089215c3dc365a1",
"build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f8/79/31ecc50de3e52c55a1569b8b9438",
"build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8a/a0/3ef54e3c6c3c777f8a221da16c14",
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ee/a8/07c5e78d027bfc1acc88a25932b4",
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ec/f5/a161f6c194a64f371e35e31bbfca",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/56/45/b6b9259f447f19ef0643b972bc64",
"build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/3b/79/592c41691e94807d23a783723861",
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/13/d9/36f4cf8527494f419db74ae6c78f",
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ee/e5/7f0677e6fb8d7cfa169930579712",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/69/c1/1694e8c7f55ac1c07277a2b5d7c2",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/73/5d/e1960323b7229bf34dd88a4b7a72",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/2c/13/30518d52dfa93a303ba6033f13d4",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/dc/41/911fb9a80bbe2e8234d8610b0cf3",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/be/e0/9c48a3fc8c3a0caf8a5c2c88ddf4",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/02/bd/6e08bef172191198f82e61f714f6",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/f2/3e/5fbbe38fa5047ac11b10f214ecd9",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/4f/cf/09c154037d8f597fcac94fcf5723",
"build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/ca/c4/9784ffa7a202da7e851c447dc69a",
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/f0/15/1ffcc9804e84eaa6a652be53cbbd",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ac/45/ff0681bcf7d1c5ac2c191d288434",
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/7f/27/4a4158050c3d77a7021e12bb9d20",
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/f1/c9/048c9c9267b456ff7e5610624fbd",
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/ad/fe/6afe3275a46a1384c348ee3917bc",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/de/e3/69d0a6f6cbfba5a6e0d74c0442ba",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/06/b6/824ee73b255e99093aeae719e2e4",
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/c7/0e/3dd207020a393e2fff196918e986",
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/7b/d3/3698352ea276344dd12e969da09e",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ff/b3/5e9acbef286f6738de3023011556",
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ab/ab/50ea4865929b418bf25dac3f475d",
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/e2/9f/aae9e3204175fce33a75d486008a",
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/98/89/63eec19c696e364e349b0d200e91",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/5b/75/bc745b50536aade78db0150d9d9e",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/94/06/ba7c0d3e3d3e9d02594871687ec9",
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/a2/ea/87883b1f4063980a1a40a112f9ce",
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/da/0b/16a433cafa1e2a7f87caf83409bf",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/3a/4c/8aa877e66c3a7ad25dbd0e075ef8",
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/83/07/b36ff25c01d4790b4758e0c86e68",
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/4b/02/e1d6afd343ce32d53c134c5fc4e7",
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ed/18/45e61446f5f7e02624fb87fb8c97",
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/cf/46/393131611fa1395fd9c173d8426f",
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/2d/2e/d4a8ba6f7c46da387394f4542d02",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/df/6c/cafe5794323f445392e63114f14b",
"build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/00/ba/5c85c98957ac9f0832a01ea83168",
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/35/0c/c85a8d0a8b43dac24a94417297fb",
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f1/ca/c78a414c9d6ec0ffb647585c3e33",
"build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0f/6a/83518a680d4917e3356d21d3650d",
"build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/6a/39/2e1794bf48cbc4c67c63b9527a68",
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/3b/64/48be465941f4f1aa3332a1d32f6a",
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/63/03/d9a332d36a337086b639c4240674",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ea/ca/533d54af50f2b5750f7c407dcbd5",
"build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/17/d6/e9af602218f3dd14a5bedb6c7eb2",
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a6/cc/2ee87bb2ead38a3bf7d8b2588f39",
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e5/ef/91bb1dfff04d62899cbe363b0d23",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/a2/7a/faf4c2744e2762e58d0119dafa72",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/7d/66/d3aafe52f5d44a23aa426bc8e602",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/63/5b/a3d3b19e7583a72cbdeefbd00f7e",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/60/14/3a28abc1b1b87b14f05d86a2e900",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/6c/a3/ded8df37d31c54c4ab66e224015a",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/2b/c6/a8701e03471178983957c33026ff",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/7e/16/307bb68c0561181ba701d0bcd350",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/09/b3/2fd1934cb6f0d2454e222c60ef3b",
"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"
"src/ballistica/generated/python_embedded/bootstrap.inc": "https://files.ballistica.net/cache/ba1/2d/4f/f4fe67827f36cd59cd5193333a02",
"src/ballistica/generated/python_embedded/bootstrap_monolithic.inc": "https://files.ballistica.net/cache/ba1/ef/c1/aa5f1aa10af89f5c0b1e616355fd"
}

View File

@ -234,6 +234,7 @@
<w>benning</w>
<w>bfiledir</w>
<w>bfiles</w>
<w>bgdynamics</w>
<w>bgmodel</w>
<w>bgrn</w>
<w>bgterrain</w>
@ -415,6 +416,7 @@
<w>cleanlist</w>
<w>cleanupcheck</w>
<w>cleanupchecks</w>
<w>clearsign</w>
<w>clientid</w>
<w>clientlist</w>
<w>clienttobasn</w>
@ -1648,6 +1650,7 @@
<w>nettest</w>
<w>nettesting</w>
<w>netutils</w>
<w>networkwrite</w>
<w>nevermind</w>
<w>newactivity</w>
<w>newdamage</w>

View File

@ -1,4 +1,4 @@
### 1.7.7 (build 20837, api 7, 2022-09-12)
### 1.7.7 (build 20840, api 7, 2022-09-13)
- 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.
@ -24,7 +24,9 @@
- Renamed C++ Media to Assets.
- Removed 'scores to beat' list in coop which was only ever functional in limited cases on the Mac version. Perhaps that feature can reappear in a cross-platform way sometime.
- Simplified C++ bootstrapping to allocate all globals in one place.
- Renamed C++ Game class to Logic.
- Renamed C++ Game classes to Logic.
- The app now bootstraps Python in the main thread instead of the logic thread. This will keep things more consistent later when we are able to run under an already-existing Python interpreter.
- Python and _ba are now completely initialized in public source code. Now we just need to enable the app to survive without _bainternal and it'll be possible to build a 100% open source app.
### 1.7.6 (build 20687, api 7, 2022-08-11)
- Cleaned up da MetaSubsystem code.

View File

@ -1 +1 @@
304827393730630459319623179535089986346
222094078620857897443553282652634355523

View File

@ -5,7 +5,6 @@ from __future__ import annotations
import os
import sys
import signal
import threading
from typing import TYPE_CHECKING
@ -38,7 +37,7 @@ def bootstrap() -> None:
# Give a soft warning if we're being used with a different binary
# version than we expect.
expected_build = 20837
expected_build = 20840
running_build: int = env['build_number']
if running_build != expected_build:
print(
@ -48,16 +47,11 @@ def bootstrap() -> None:
f' This might cause the app to error or misbehave.',
file=sys.stderr)
# Tell Python to not handle SIGINT itself (it normally generates
# KeyboardInterrupts which make a mess; we want to intercept them
# for simple clean exit). We capture interrupts per-platform in
# the C++ layer.
# Note: I tried creating a handler in Python but it seemed to often have
# a delay of up to a second before getting called. (not a huge deal
# but I'm picky).
signal.signal(signal.SIGINT, signal.SIG_DFL) # Do default handling.
# In bootstrap_monolithic.py we told Python not to handle SIGINT itself
# (because that must be done in the main thread). Now we finish the
# job by adding our own handler to replace it.
# ..though it turns out we need to set up our C signal handling AFTER
# Note: I've found we need to set up our C signal handling AFTER
# we've told Python to disable its own; otherwise (on Mac at least) it
# wipes out our existing C handler.
_ba.setup_sigint()

View File

@ -119,6 +119,7 @@
<w>bdea</w>
<w>benning</w>
<w>bezanson</w>
<w>bgdynamics</w>
<w>bgra</w>
<w>bigendian</w>
<w>bilinear</w>
@ -226,6 +227,7 @@
<w>classdict</w>
<w>classline</w>
<w>cleanupcheck</w>
<w>clearsign</w>
<w>clientid</w>
<w>clientinfo</w>
<w>clienttobasn</w>
@ -849,6 +851,7 @@
<w>netcode</w>
<w>netplay</w>
<w>nettest</w>
<w>networkwrite</w>
<w>newactivity</w>
<w>newchild</w>
<w>newimg</w>

View File

@ -58,6 +58,7 @@
<inspection_tool class="NotAssignable" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="NotImplementedFunctions" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="NotSuperclass" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="NullDereference" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="OCDFA" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="OCLoopDoesntUseConditionVariable" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="OCUnusedGlobalDeclaration" enabled="false" level="WARNING" enabled_by_default="false" />

View File

@ -86,7 +86,7 @@ class AudioServer::ThreadSource : public Object {
auto play_id() const -> uint32_t {
return (play_count_ << 16u) | (static_cast<uint32_t>(id_) & 0xFFFFu);
}
void UpdateAvailability();
auto UpdateAvailability() -> void;
auto GetDefaultOwnerThread() const -> ThreadTag override;
auto client_source() const -> AudioSource* { return client_source_.get(); }
auto source_sound() const -> SoundData* {

View File

@ -32,7 +32,7 @@
namespace ballistica {
// These are set automatically via script; don't modify them here.
const int kAppBuildNumber = 20837;
const int kAppBuildNumber = 20840;
const char* kAppVersion = "1.7.7";
// Our standalone globals.
@ -88,9 +88,10 @@ auto BallisticaMain(int argc, char** argv) -> int {
g_platform = Platform::Create();
g_app = new App(argc, argv);
g_app_internal = CreateAppInternal();
g_main_thread = new Thread(ThreadTag::kMain, ThreadSource::kWrapMain);
g_python = new Python();
g_app_flavor = g_platform->CreateAppFlavor();
g_python = Python::Create();
g_graphics = g_platform->CreateGraphics();
g_graphics_server = new GraphicsServer();
g_audio = new Audio();
@ -107,7 +108,6 @@ auto BallisticaMain(int argc, char** argv) -> int {
g_network_reader = new NetworkReader();
g_network_writer = new NetworkWriter();
g_input = new Input();
g_app_internal = CreateAppInternal();
g_logic = new Logic();
g_scene_v1 = new SceneV1();
if (!HeadlessMode()) {
@ -220,7 +220,7 @@ auto FatalError(const std::string& message) -> void {
FatalError::ReportFatalError(message, false);
bool exit_cleanly = !IsUnmodifiedBlessedBuild();
bool handled = FatalError::HandleFatalError(exit_cleanly, false);
assert(handled);
BA_PRECONDITION(handled);
}
auto GetAppInstanceUUID() -> const std::string& {

View File

@ -16,7 +16,7 @@ class AppInternal {
public:
virtual ~AppInternal() {}
virtual auto PyInitialize(void* pyconfig) -> void = 0;
virtual auto DefineInternalModule() -> void = 0;
virtual auto PythonPostInit() -> void = 0;
virtual auto HasBlessingHash() -> bool = 0;
virtual auto PutLog(bool fatal) -> bool = 0;

View File

@ -83,10 +83,20 @@ auto Logic::OnAppStart() -> void {
auto Logic::OnAppStartInThread() -> void {
try {
// Our thread should hold the Python GIL any time it is running.
// TODO(ericf): It could be better to have each individual Python call
// we make acquire the GIL. Then we're not holding it during long
// bits of C++ logic.
// Our thread should not be holding the GIL here at the start (and
// probably not have any Python state at all). So here we set both
// of those up.
assert(!PyGILState_Check());
PyGILState_Ensure();
// Tell our thread that it should grab the Python GIL any time it
// is running something and release it when done.
// TODO(ericf): It could be good to explore the idea of having
// individual runnables grab the GIL instead of doing it here at the
// thread level. Though its a bit freeing to know that we can run
// Python code at any time in the logic thread without worry. We can
// also consider explicitly releasing the GIL in the logic thread
// during long operations where we know no Python will occur.
thread_->SetAcquiresPythonGIL();
// We want to be informed when our thread is pausing.
@ -98,7 +108,7 @@ auto Logic::OnAppStartInThread() -> void {
// Init python and apply our settings immediately.
// This way we can get started loading stuff in the background
// and it'll come in with the correct texture quality etc.
g_python->Reset(true);
g_python->InitBallisticaPython();
} catch (const std::exception& e) {
// If anything went wrong, trigger a deferred error.
// This way it is more likely we can show a fatal error dialog

View File

@ -701,6 +701,7 @@ auto PyCommitConfig(PyObject* self, PyObject* args, PyObject* keywds)
auto PyEnv(PyObject* self) -> PyObject* {
BA_PYTHON_TRY;
assert(g_app->is_bootstrapped);
static PyObject* env_obj = nullptr;

View File

@ -853,6 +853,19 @@ auto Python::GetPyVector3f(PyObject* o) -> Vector3f {
Python::Python() = default;
auto Python::Create() -> Python* {
assert(InMainThread());
Python* python = new Python();
python->InitCorePython();
// After we bootstrap Python here in the main thread we release the GIL.
// We'll explicitly reacquire it anytime we need it (mainly in the logic
// thread once that comes up later).
PyEval_SaveThread();
return python;
}
static struct PyModuleDef ba_module_def = {PyModuleDef_HEAD_INIT};
static auto ba_exec(PyObject* module) -> int {
@ -885,161 +898,183 @@ static auto PyInit__ba() -> PyObject* {
return module;
}
void Python::Reset(bool do_init) {
auto Python::InitCorePython() -> void {
assert(!inited_);
assert(InMainThread());
// Flip on some extra runtime debugging options in debug builds.
// https://docs.python.org/3/library/devmode.html#devmode
int dev_mode{g_buildconfig.debug_build()};
// Pre-config as isolated if we include our own Python and as standard
// otherwise.
PyPreConfig preconfig;
if (g_platform->ContainsPythonDist()) {
PyPreConfig_InitIsolatedConfig(&preconfig);
} else {
PyPreConfig_InitPythonConfig(&preconfig);
}
preconfig.dev_mode = dev_mode;
// We want consistent utf-8 everywhere (Python used to default to
// windows-specific file encodings, etc.)
preconfig.utf8_mode = 1;
PyStatus status = Py_PreInitialize(&preconfig);
BA_PRECONDITION(!PyStatus_Exception(status));
// Configure as isolated if we include our own Python and as standard
// otherwise.
PyConfig config;
if (g_platform->ContainsPythonDist()) {
PyConfig_InitIsolatedConfig(&config);
} else {
PyConfig_InitPythonConfig(&config);
}
config.dev_mode = dev_mode;
if (!g_buildconfig.debug_build()) {
config.optimization_level = 1;
}
// In cases where we bundle Python, set up all paths explicitly.
// https://docs.python.org/3/c-api/init_config.html#path-configuration
if (g_platform->ContainsPythonDist()) {
PyConfig_SetBytesString(&config, &config.base_exec_prefix, "");
PyConfig_SetBytesString(&config, &config.base_executable, "");
PyConfig_SetBytesString(&config, &config.base_prefix, "");
PyConfig_SetBytesString(&config, &config.exec_prefix, "");
PyConfig_SetBytesString(&config, &config.executable, "");
PyConfig_SetBytesString(&config, &config.prefix, "");
// Interesting note: it seems we can pass relative paths here but
// they wind up in sys.path as absolute paths (unlike entries we add
// to sys.path after things are up and running).
if (g_buildconfig.ostype_windows()) {
// Windows Python looks for Lib and DLLs dirs by default, along with
// some others, but we want to be more explicit in limiting to these. It
// also seems that windows Python's paths can be incorrect if we're in
// strange dirs such as \\wsl$\Ubuntu-18.04\ that we get with WSL build
// setups.
// NOTE: Python for windows actually comes with 'Lib', not 'lib', but
// it seems the interpreter defaults point to ./lib (as of 3.8.5).
// Normally this doesn't matter since windows is case-insensitive but
// under WSL it does.
// So we currently bundle the dir as 'lib' and use that in our path so
// that everything is happy (both with us and with python.exe).
PyWideStringList_Append(&config.module_search_paths,
Py_DecodeLocale("lib", nullptr));
PyWideStringList_Append(&config.module_search_paths,
Py_DecodeLocale("DLLs", nullptr));
} else {
PyWideStringList_Append(&config.module_search_paths,
Py_DecodeLocale("pylib", nullptr));
}
config.module_search_paths_set = 1;
}
// Let Python know how to spin up our _ba module.
PyImport_AppendInittab("_ba", &PyInit__ba);
// Let Python know how to spin up the _bainternal module.
g_app_internal->DefineInternalModule();
// Init Python.
status = Py_InitializeFromConfig(&config);
BA_PRECONDITION(!PyStatus_Exception(status));
// Create a dict for execing just this bootstrap code in so
// we don't pollute the __main__ namespace.
auto bootstrap_context{PythonRef(PyDict_New(), PythonRef::kSteal)};
// Do a bit of basic bootstrapping here in the main thread.
#include "ballistica/generated/python_embedded/bootstrap_monolithic.inc"
PyObject* result =
PyRun_String(bootstrap_monolithic_code, Py_file_input,
bootstrap_context.get(), bootstrap_context.get());
if (result == nullptr) {
PyErr_PrintEx(0);
// Throw a simple exception so we don't get a stack trace.
throw std::logic_error(
"Error in ba Python bootstrapping. See log for details.");
}
Py_DECREF(result);
// Grab __main__ in case we need to use it later.
// FIXME: put this in objs_ with everything else.
PyObject* m;
BA_PRECONDITION(m = PyImport_AddModule("__main__"));
BA_PRECONDITION(main_dict_ = PyModule_GetDict(m));
// Make sure we're running the Python version we require.
const char* ver = Py_GetVersion();
if (strncmp(ver, "3.10", 4) != 0) {
FatalError("We require Python 3.10.x; instead found " + std::string(ver));
}
}
auto Python::InitBallisticaPython() -> void {
assert(InLogicThread());
// Create a dict for execing just this bootstrap code in so
// we don't pollute the __main__ namespace.
auto bootstrap_context{PythonRef(PyDict_New(), PythonRef::kSteal)};
// Get the app up and running.
// Run a few core bootstrappy things first:
// - get stdout/stderr redirection up so we can intercept python output
// - add our user and system script dirs to python path
// - create the ba.app instance.
#include "ballistica/generated/python_embedded/bootstrap.inc"
PyObject* result =
PyRun_String(bootstrap_code, Py_file_input, bootstrap_context.get(),
bootstrap_context.get());
if (result == nullptr) {
PyErr_PrintEx(0);
// Throw a simple exception so we don't get a stack trace.
throw std::logic_error(
"Error in ba Python bootstrapping. See log for details.");
}
Py_DECREF(result);
// Import and grab all the Python stuff we use from C++.
#include "ballistica/generated/python_embedded/binding.inc"
g_app_internal->PythonPostInit();
// Alright I guess let's pull ba in to main, since pretty
// much all interactive commands will be using it.
// If we ever build the game as a pure python module we should
// of course not do this.
BA_PRECONDITION(PyRun_SimpleString("import ba") == 0);
// Read the config file and store the config dict for easy access.
obj(ObjID::kReadConfigCall).Call();
StoreObj(ObjID::kConfig, obj(ObjID::kApp).GetAttr("config").get());
assert(PyDict_Check(obj(ObjID::kConfig).get()));
// Turn off fancy-pants cyclic garbage-collection.
// We run it only at explicit times to avoid random hitches and keep
// things more deterministic.
// Non-reference-looped objects will still get cleaned up
// immediately, so we should try to structure things to avoid
// reference loops (just like Swift, ObjC, etc).
// FIXME - move this to Python code.
g_python->obj(Python::ObjID::kGCDisableCall).Call();
inited_ = true;
}
auto Python::Reset() -> void {
assert(InLogicThread());
assert(g_python);
assert(g_platform);
assert(inited_);
bool was_inited = inited_;
if (inited_) {
ReleaseGamePadInput();
ReleaseKeyboardInput();
g_graphics->ReleaseFadeEndCommand();
inited_ = false;
}
if (!was_inited && do_init) {
// Flip on some extra runtime debugging options in debug builds.
// https://docs.python.org/3.10/library/devmode.html#devmode
int dev_mode{g_buildconfig.debug_build()};
// Pre-config as isolated if we include our own Python and as standard
// otherwise.
PyPreConfig preconfig;
if (g_platform->ContainsPythonDist()) {
PyPreConfig_InitIsolatedConfig(&preconfig);
} else {
PyPreConfig_InitPythonConfig(&preconfig);
}
preconfig.dev_mode = dev_mode;
// We want consistent utf-8 everywhere (Python used to default to
// windows-specific file encodings, etc.)
preconfig.utf8_mode = 1;
PyStatus status = Py_PreInitialize(&preconfig);
BA_PRECONDITION(!PyStatus_Exception(status));
// Configure as isolated if we include our own Python and as standard
// otherwise.
PyConfig config;
if (g_platform->ContainsPythonDist()) {
PyConfig_InitIsolatedConfig(&config);
} else {
PyConfig_InitPythonConfig(&config);
}
config.dev_mode = dev_mode;
if (!g_buildconfig.debug_build()) {
config.optimization_level = 1;
}
// In cases where we bundle Python, set up all paths explicitly.
// see https://docs.python.org/3.8/
// c-api/init_config.html#path-configuration
if (g_platform->ContainsPythonDist()) {
PyConfig_SetBytesString(&config, &config.base_exec_prefix, "");
PyConfig_SetBytesString(&config, &config.base_executable, "");
PyConfig_SetBytesString(&config, &config.base_prefix, "");
PyConfig_SetBytesString(&config, &config.exec_prefix, "");
PyConfig_SetBytesString(&config, &config.executable, "");
PyConfig_SetBytesString(&config, &config.prefix, "");
// Interesting note: it seems we can pass relative paths here but
// they wind up in sys.path as absolute paths (unlike entries we add
// to sys.path after things are up and running).
if (g_buildconfig.ostype_windows()) {
// Windows Python looks for Lib and DLLs dirs by default, along with
// some others, but we want to be more explicit in limiting to these. It
// also seems that windows Python's paths can be incorrect if we're in
// strange dirs such as \\wsl$\Ubuntu-18.04\ that we get with WSL build
// setups.
// NOTE: Python for windows actually comes with 'Lib', not 'lib', but
// it seems the interpreter defaults point to ./lib (as of 3.8.5).
// Normally this doesn't matter since windows is case-insensitive but
// under WSL it does.
// So we currently bundle the dir as 'lib' and use that in our path so
// that everything is happy (both with us and with python.exe).
PyWideStringList_Append(&config.module_search_paths,
Py_DecodeLocale("lib", nullptr));
PyWideStringList_Append(&config.module_search_paths,
Py_DecodeLocale("DLLs", nullptr));
} else {
PyWideStringList_Append(&config.module_search_paths,
Py_DecodeLocale("pylib", nullptr));
}
config.module_search_paths_set = 1;
}
// Let Python know how to spin up our _ba module.
PyImport_AppendInittab("_ba", &PyInit__ba);
// Inits our _ba module and runs Py_Initialize().
g_app_internal->PyInitialize(&config);
// Grab __main__ in case we need to use it later.
PyObject* m;
BA_PRECONDITION(m = PyImport_AddModule("__main__"));
BA_PRECONDITION(main_dict_ = PyModule_GetDict(m));
// Make sure we're running the Python version we require.
const char* ver = Py_GetVersion();
if (strncmp(ver, "3.10", 4) != 0) {
throw Exception("We require Python 3.10.x; instead found "
+ std::string(ver));
}
// Create a dict for execing our bootstrap code in so
// we don't pollute the __main__ namespace.
auto bootstrap_context{PythonRef(PyDict_New(), PythonRef::kSteal)};
// Get the app up and running.
// Run a few core bootstrappy things first:
// - get stdout/stderr redirection up so we can intercept python output
// - add our user and system script dirs to python path
// - create the ba.app instance.
#include "ballistica/generated/python_embedded/bootstrap.inc"
PyObject* result =
PyRun_String(bootstrap_code, Py_file_input, bootstrap_context.get(),
bootstrap_context.get());
if (result == nullptr) {
PyErr_PrintEx(0);
// Throw a simple exception so we don't get a stack trace.
throw std::logic_error(
"Error in ba Python bootstrapping. See log for details.");
}
Py_DECREF(result);
// Import and grab all the Python stuff we use from C++.
#include "ballistica/generated/python_embedded/binding.inc"
g_app_internal->PythonPostInit();
// Alright I guess let's pull ba in to main, since pretty
// much all interactive commands will be using it.
// If we ever build the game as a pure python module we should
// of course not do this.
BA_PRECONDITION(PyRun_SimpleString("import ba") == 0);
// Read the config file and store the config dict for easy access.
obj(ObjID::kReadConfigCall).Call();
StoreObj(ObjID::kConfig, obj(ObjID::kApp).GetAttr("config").get());
assert(PyDict_Check(obj(ObjID::kConfig).get()));
// Turn off fancy-pants cyclic garbage-collection.
// We run it only at explicit times to avoid random hitches and keep
// things more deterministic.
// Non-reference-looped objects will still get cleaned up
// immediately, so we should try to structure things to avoid
// reference loops (just like Swift, ObjC, etc).
g_python->obj(Python::ObjID::kGCDisableCall).Call();
}
if (do_init) {
inited_ = true;
}
ReleaseGamePadInput();
ReleaseKeyboardInput();
g_graphics->ReleaseFadeEndCommand();
}
auto Python::GetModuleMethods() -> std::vector<PyMethodDef> {
@ -1114,8 +1149,6 @@ void Python::PushObjCall(ObjID obj_id, const std::string& arg) {
});
}
Python::~Python() { Reset(false); }
auto Python::GetResource(const char* key, const char* fallback_resource,
const char* fallback_value) -> std::string {
assert(HaveGIL());
@ -2259,12 +2292,13 @@ void Python::LogContextAuto() {
}
void Python::AcquireGIL() {
assert(InLogicThread());
auto debug_timing{g_app->debug_timing};
millisecs_t startms{debug_timing ? Platform::GetCurrentMilliseconds() : 0};
if (thread_state_) {
PyEval_RestoreThread(thread_state_);
thread_state_ = nullptr;
if (logic_thread_state_) {
PyEval_RestoreThread(logic_thread_state_);
logic_thread_state_ = nullptr;
}
if (debug_timing) {
@ -2275,9 +2309,11 @@ void Python::AcquireGIL() {
}
}
}
void Python::ReleaseGIL() {
assert(thread_state_ == nullptr);
thread_state_ = PyEval_SaveThread();
assert(InLogicThread());
assert(logic_thread_state_ == nullptr);
logic_thread_state_ = PyEval_SaveThread();
}
void Python::AddCleanFrameCommand(const Object::Ref<PythonContextCall>& c) {

View File

@ -80,9 +80,11 @@ class Python {
static auto LogContextAuto() -> void;
static auto LogContextNonLogicThread() -> void;
Python();
~Python();
static auto Create() -> Python*;
auto Reset(bool init = true) -> void;
auto InitCorePython() -> void;
auto InitBallisticaPython() -> void;
auto Reset() -> void;
/// Add classes to the newly created ba module.
static auto InitModuleClasses(PyObject* module) -> void;
@ -424,7 +426,7 @@ class Python {
PyObject* empty_dict_object_{};
PyObject* main_dict_{};
PyObject* env_{};
PyThreadState* thread_state_{};
PyThreadState* logic_thread_state_{};
};
} // namespace ballistica

View File

@ -13,7 +13,6 @@ namespace ballistica {
#pragma ide diagnostic ignored "RedundantCast"
PythonRef::PythonRef(PyObject* obj_in, ReferenceBehavior b) {
assert(g_python);
assert(Python::HaveGIL());
switch (b) {
case kSteal:
@ -54,7 +53,6 @@ void PythonRef::Acquire(PyObject* obj_in) {
void PythonRef::Steal(PyObject* obj_in) {
BA_PRECONDITION(obj_in);
assert(g_python);
assert(Python::HaveGIL());
// Assign before decrementing the old
@ -67,7 +65,6 @@ void PythonRef::Steal(PyObject* obj_in) {
}
void PythonRef::Release() {
assert(g_python);
assert(Python::HaveGIL());
// Py_CLEAR uses a temp variable and assigns o to nullptr first
@ -113,7 +110,6 @@ auto PythonRef::ValueAsInt() const -> int64_t {
}
auto PythonRef::GetAttr(const char* name) const -> PythonRef {
assert(g_python);
assert(Python::HaveGIL());
BA_PRECONDITION(obj_);
PyObject* val = PyObject_GetAttrString(get(), name);
@ -149,7 +145,6 @@ auto PythonRef::UnicodeCheck() const -> bool {
auto PythonRef::Call(PyObject* args, PyObject* keywds, bool print_errors) const
-> PythonRef {
assert(obj_);
assert(g_python);
assert(Python::HaveGIL());
assert(CallableCheck());
assert(args);

View File

@ -2,5 +2,6 @@
"assets/src/ba_data/python/ba/_generated/__init__.py",
"assets/src/ba_data/python/ba/_generated/enums.py",
"src/ballistica/generated/python_embedded/binding.inc",
"src/ballistica/generated/python_embedded/bootstrap.inc"
"src/ballistica/generated/python_embedded/bootstrap.inc",
"src/ballistica/generated/python_embedded/bootstrap_monolithic.inc"
]

View File

@ -17,7 +17,8 @@ sources: \
../../assets/src/ba_data/python/ba/_generated/__init__.py \
../../assets/src/ba_data/python/ba/_generated/enums.py \
../ballistica/generated/python_embedded/binding.inc \
../ballistica/generated/python_embedded/bootstrap.inc
../ballistica/generated/python_embedded/bootstrap.inc \
../ballistica/generated/python_embedded/bootstrap_monolithic.inc
../ballistica/generated/python_embedded/binding.inc : bameta/python_embedded/binding.py
@$(PCOMMAND) gen_binding_code $< $@
@ -25,6 +26,9 @@ sources: \
../ballistica/generated/python_embedded/bootstrap.inc : bameta/python_embedded/bootstrap.py
@$(PCOMMAND) gen_flat_data_code $< $@ bootstrap_code
../ballistica/generated/python_embedded/bootstrap_monolithic.inc : bameta/python_embedded/bootstrap_monolithic.py
@$(PCOMMAND) gen_flat_data_code $< $@ bootstrap_monolithic_code
../../assets/src/ba_data/python/ba/_generated/__init__.py : ../../tools/batools/pcommand.py
@$(PCOMMAND) gen_python_init_module $@
@ -45,7 +49,8 @@ efrocache-list:
@echo "../../assets/src/ba_data/python/ba/_generated/__init__.py" \
"../../assets/src/ba_data/python/ba/_generated/enums.py" \
"../ballistica/generated/python_embedded/binding.inc" \
"../ballistica/generated/python_embedded/bootstrap.inc"
"../ballistica/generated/python_embedded/bootstrap.inc" \
"../ballistica/generated/python_embedded/bootstrap_monolithic.inc"
efrocache-build: sources

View File

@ -1,6 +1,8 @@
# Released under the MIT License. See LICENSE for details.
#
"""Initial ballistica bootstrapping."""
"""Ballistica bootstrapping."""
# This code runs in the logic thread to bootstrap ballistica.
from __future__ import annotations

View File

@ -0,0 +1,22 @@
# Released under the MIT License. See LICENSE for details.
#
"""Main thread bootstrapping for Python monolithic builds."""
# This code runs in the main thread just after the interpreter comes up.
# It should *ONLY* do things that must be done in the main thread and
# should not import any ballistica stuff.
from __future__ import annotations
import signal
from typing import TYPE_CHECKING
if TYPE_CHECKING:
pass
# Tell Python to not handle SIGINT itself (it normally generates
# KeyboardInterrupts which make a mess; we want to intercept them
# for simple clean exit). We have to do this part here because it must
# run in the main thread. We add our own handler later in the logic thread
# alongside our other ba bootstrapping.
signal.signal(signal.SIGINT, signal.SIG_DFL) # Do default handling.