Skip to content

Commit afa7a79

Browse files
author
Roberto De Ioris
committed
more solid threading support
1 parent b30b184 commit afa7a79

File tree

7 files changed

+89
-47
lines changed

7 files changed

+89
-47
lines changed

Source/UnrealEnginePython/Private/ConsoleManager/UEPyIConsoleManager.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,10 @@ static PyObject *py_ue_iconsole_manager_unregister_object(PyObject *cls, PyObjec
434434
return PyErr_Format(PyExc_Exception, "unable to find console object \"%s\"", key);
435435
}
436436

437+
438+
FPythonSmartConsoleDelegate::UnregisterPyDelegate(c_object);
439+
440+
437441
IConsoleManager::Get().UnregisterConsoleObject(c_object, false);
438442

439443
Py_RETURN_NONE;
@@ -539,6 +543,9 @@ void FPythonSmartConsoleDelegate::OnConsoleCommand(const TArray < FString > & In
539543
Py_DECREF(ret);
540544
}
541545

546+
// static TArray declaration
547+
TArray<FPythonSmartConsoleDelegatePair> FPythonSmartConsoleDelegate::PyDelegatesMapping;
548+
542549
static PyObject *py_ue_iconsole_manager_register_command(PyObject *cls, PyObject * args)
543550
{
544551
char *key;
@@ -565,10 +572,14 @@ static PyObject *py_ue_iconsole_manager_register_command(PyObject *cls, PyObject
565572
FConsoleCommandWithArgsDelegate console_delegate;
566573
console_delegate.BindSP(py_delegate, &FPythonSmartConsoleDelegate::OnConsoleCommand);
567574

568-
if (!IConsoleManager::Get().RegisterConsoleCommand(UTF8_TO_TCHAR(key), help ? UTF8_TO_TCHAR(help) : UTF8_TO_TCHAR(key), console_delegate, 0))
569-
{
575+
576+
577+
c_object = IConsoleManager::Get().RegisterConsoleCommand(UTF8_TO_TCHAR(key), help ? UTF8_TO_TCHAR(help) : UTF8_TO_TCHAR(key), console_delegate, 0);
578+
if (!c_object)
570579
return PyErr_Format(PyExc_Exception, "unable to register console command \"%s\"", key);
571-
}
580+
581+
// this allows the delegates to not be destroyed
582+
FPythonSmartConsoleDelegate::RegisterPyDelegate(c_object, py_delegate);
572583

573584
Py_RETURN_NONE;
574585
}

Source/UnrealEnginePython/Private/ConsoleManager/UEPyIConsoleManager.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,50 @@ typedef struct
1010
/* Type-specific fields go here. */
1111
} ue_PyIConsoleManager;
1212

13+
class FPythonSmartConsoleDelegate;
14+
struct FPythonSmartConsoleDelegatePair
15+
{
16+
IConsoleObject *Key;
17+
TSharedRef<FPythonSmartConsoleDelegate> Value;
18+
19+
FPythonSmartConsoleDelegatePair(IConsoleObject *InKey, TSharedRef<FPythonSmartConsoleDelegate> InValue) : Key(InKey), Value(InValue)
20+
{
21+
22+
}
23+
};
24+
1325
class FPythonSmartConsoleDelegate : public FPythonSmartDelegate
1426
{
1527

1628
public:
1729
void OnConsoleCommand(const TArray < FString > &InArgs);
30+
31+
static void RegisterPyDelegate(IConsoleObject *InKey, TSharedRef<FPythonSmartConsoleDelegate> InValue)
32+
{
33+
FPythonSmartConsoleDelegatePair Pair(InKey, InValue);
34+
PyDelegatesMapping.Add(Pair);
35+
}
36+
37+
static void UnregisterPyDelegate(IConsoleObject *Key)
38+
{
39+
int32 Index = -1;
40+
for (int32 i = 0; i < PyDelegatesMapping.Num(); i++)
41+
{
42+
if (PyDelegatesMapping[i].Key == Key)
43+
{
44+
Index = i;
45+
break;
46+
}
47+
}
48+
49+
if (Index >= 0)
50+
{
51+
PyDelegatesMapping.RemoveAt(Index);
52+
}
53+
}
54+
55+
private:
56+
static TArray<FPythonSmartConsoleDelegatePair> PyDelegatesMapping;
1857
};
1958

2059
void ue_python_init_iconsole_manager(PyObject *);

Source/UnrealEnginePython/Private/UEPyModule.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,9 @@ static PyObject *py_unreal_engine_exec(PyObject * self, PyObject * args)
157157
return NULL;
158158
}
159159
FUnrealEnginePythonModule &PythonModule = FModuleManager::GetModuleChecked<FUnrealEnginePythonModule>("UnrealEnginePython");
160-
UEPyGlobalState = PyEval_SaveThread();
160+
Py_BEGIN_ALLOW_THREADS;
161161
PythonModule.RunFile(filename);
162-
PyEval_RestoreThread(UEPyGlobalState);
162+
Py_END_ALLOW_THREADS;
163163
Py_RETURN_NONE;
164164
}
165165

Source/UnrealEnginePython/Private/UObject/UEPyTransform.cpp

Lines changed: 28 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,7 @@ PyObject *py_ue_set_actor_location(ue_PyUObject *self, PyObject * args)
236236
FHitResult hit;
237237
bool success = false;
238238

239-
Py_BEGIN_ALLOW_THREADS;
240239
success = actor->SetActorLocation(vec, sweep, &hit, teleport_physics ? ETeleportType::TeleportPhysics : ETeleportType::None);
241-
Py_END_ALLOW_THREADS;
242240

243241
if (!sweep)
244242
{
@@ -268,9 +266,8 @@ PyObject *py_ue_add_actor_world_offset(ue_PyUObject *self, PyObject * args)
268266
PyErr_Format(PyExc_Exception, "uobject is not an actor or a component");
269267

270268
FHitResult hit;
271-
Py_BEGIN_ALLOW_THREADS;
269+
272270
actor->AddActorWorldOffset(vec, sweep, &hit, teleport_physics ? ETeleportType::TeleportPhysics : ETeleportType::None);
273-
Py_END_ALLOW_THREADS;
274271

275272
if (!sweep)
276273
{
@@ -296,9 +293,7 @@ PyObject *py_ue_add_actor_local_offset(ue_PyUObject *self, PyObject * args)
296293
PyErr_Format(PyExc_Exception, "uobject is not an actor or a component");
297294

298295
FHitResult hit;
299-
Py_BEGIN_ALLOW_THREADS;
300296
actor->AddActorLocalOffset(vec, sweep, &hit, teleport_physics ? ETeleportType::TeleportPhysics : ETeleportType::None);
301-
Py_END_ALLOW_THREADS;
302297

303298
if (!sweep)
304299
{
@@ -324,9 +319,9 @@ PyObject *py_ue_add_actor_world_rotation(ue_PyUObject *self, PyObject * args)
324319
if (!actor)
325320
return PyErr_Format(PyExc_Exception, "uobject is not an actor or a component");
326321
FHitResult hit;
327-
Py_BEGIN_ALLOW_THREADS;
322+
328323
actor->AddActorWorldRotation(quat, sweep, &hit, teleport_physics ? ETeleportType::TeleportPhysics : ETeleportType::None);
329-
Py_END_ALLOW_THREADS;
324+
330325
if (!sweep)
331326
{
332327
Py_RETURN_NONE;
@@ -351,9 +346,9 @@ PyObject *py_ue_add_actor_local_rotation(ue_PyUObject *self, PyObject * args)
351346
return PyErr_Format(PyExc_Exception, "uobject is not an actor or a component");
352347
FHitResult hit;
353348

354-
Py_BEGIN_ALLOW_THREADS;
349+
355350
actor->AddActorLocalRotation(quat, sweep, &hit, teleport_physics ? ETeleportType::TeleportPhysics : ETeleportType::None);
356-
Py_END_ALLOW_THREADS;
351+
357352
if (!sweep)
358353
{
359354
Py_RETURN_NONE;
@@ -376,9 +371,9 @@ PyObject *py_ue_set_actor_scale(ue_PyUObject *self, PyObject * args)
376371
if (!actor)
377372
PyErr_Format(PyExc_Exception, "uobject is not an actor or a component");
378373

379-
Py_BEGIN_ALLOW_THREADS;
374+
380375
actor->SetActorScale3D(vec);
381-
Py_END_ALLOW_THREADS;
376+
382377

383378
Py_RETURN_NONE;
384379

@@ -400,9 +395,9 @@ PyObject *py_ue_set_actor_rotation(ue_PyUObject *self, PyObject * args)
400395

401396
bool success = false;
402397

403-
Py_BEGIN_ALLOW_THREADS;
398+
404399
success = actor->SetActorRotation(quat, teleport_physics ? ETeleportType::TeleportPhysics : ETeleportType::None);
405-
Py_END_ALLOW_THREADS;
400+
406401

407402
if (success)
408403
{
@@ -425,9 +420,9 @@ PyObject *py_ue_set_actor_transform(ue_PyUObject *self, PyObject * args)
425420
if (!actor)
426421
PyErr_Format(PyExc_Exception, "uobject is not an actor or a component");
427422

428-
Py_BEGIN_ALLOW_THREADS;
423+
429424
actor->SetActorTransform(t);
430-
Py_END_ALLOW_THREADS;
425+
431426

432427
Py_RETURN_NONE;
433428
}
@@ -567,9 +562,9 @@ PyObject *py_ue_set_world_location(ue_PyUObject *self, PyObject * args)
567562

568563
if (self->ue_object->IsA<USceneComponent>())
569564
{
570-
Py_BEGIN_ALLOW_THREADS;
565+
571566
((USceneComponent *)self->ue_object)->SetWorldLocation(vec, sweep, &hit, teleport_physics ? ETeleportType::TeleportPhysics : ETeleportType::None);
572-
Py_END_ALLOW_THREADS;
567+
573568
if (!sweep)
574569
{
575570
Py_RETURN_NONE;
@@ -587,11 +582,10 @@ PyObject *py_ue_set_world_rotation(ue_PyUObject *self, PyObject * args)
587582
return NULL;
588583
if (self->ue_object->IsA<USceneComponent>())
589584
{
590-
Py_BEGIN_ALLOW_THREADS;
585+
591586
((USceneComponent *)self->ue_object)->SetWorldRotation(rot);
592-
Py_END_ALLOW_THREADS;
593-
Py_INCREF(Py_None);
594-
return Py_None;
587+
588+
Py_RETURN_NONE;
595589
}
596590
return PyErr_Format(PyExc_Exception, "uobject is not a USceneComponent");
597591
}
@@ -605,10 +599,9 @@ PyObject *py_ue_set_world_scale(ue_PyUObject *self, PyObject * args)
605599

606600
if (self->ue_object->IsA<USceneComponent>())
607601
{
608-
Py_BEGIN_ALLOW_THREADS;
602+
609603
((USceneComponent *)self->ue_object)->SetWorldScale3D(vec);
610-
Py_RETURN_NONE;
611-
Py_END_ALLOW_THREADS;
604+
612605
}
613606
return PyErr_Format(PyExc_Exception, "uobject is not a USceneComponent");
614607
}
@@ -626,9 +619,9 @@ PyObject *py_ue_set_world_transform(ue_PyUObject *self, PyObject * args)
626619
if (!component)
627620
return PyErr_Format(PyExc_Exception, "uobject is not a USceneComponent");
628621

629-
Py_BEGIN_ALLOW_THREADS;
622+
630623
component->SetWorldTransform(t);
631-
Py_END_ALLOW_THREADS;
624+
632625

633626
Py_RETURN_NONE;
634627
}
@@ -646,9 +639,9 @@ PyObject *py_ue_set_relative_transform(ue_PyUObject *self, PyObject * args)
646639
if (!component)
647640
return PyErr_Format(PyExc_Exception, "uobject is not a USceneComponent");
648641

649-
Py_BEGIN_ALLOW_THREADS;
642+
650643
component->SetRelativeTransform(t);
651-
Py_END_ALLOW_THREADS;
644+
652645
Py_RETURN_NONE;
653646
}
654647

@@ -661,9 +654,9 @@ PyObject *py_ue_set_relative_location(ue_PyUObject *self, PyObject * args)
661654

662655
if (self->ue_object->IsA<USceneComponent>())
663656
{
664-
Py_BEGIN_ALLOW_THREADS;
657+
665658
((USceneComponent *)self->ue_object)->SetRelativeLocation(vec);
666-
Py_END_ALLOW_THREADS;
659+
667660
Py_RETURN_NONE;
668661
}
669662
return PyErr_Format(PyExc_Exception, "uobject is not a USceneComponent");
@@ -677,9 +670,9 @@ PyObject *py_ue_set_relative_rotation(ue_PyUObject *self, PyObject * args)
677670
return NULL;
678671
if (self->ue_object->IsA<USceneComponent>())
679672
{
680-
Py_BEGIN_ALLOW_THREADS;
673+
681674
((USceneComponent *)self->ue_object)->SetRelativeRotation(rot);
682-
Py_END_ALLOW_THREADS;
675+
683676
Py_RETURN_NONE;
684677
}
685678
return PyErr_Format(PyExc_Exception, "uobject is not a USceneComponent");
@@ -694,9 +687,9 @@ PyObject *py_ue_set_relative_scale(ue_PyUObject *self, PyObject * args)
694687

695688
if (self->ue_object->IsA<USceneComponent>())
696689
{
697-
Py_BEGIN_ALLOW_THREADS;
690+
698691
((USceneComponent *)self->ue_object)->SetRelativeScale3D(vec);
699-
Py_END_ALLOW_THREADS;
692+
700693
Py_RETURN_NONE;
701694
}
702695
return PyErr_Format(PyExc_Exception, "uobject is not a USceneComponent");

Source/UnrealEnginePython/Private/UnrealEnginePython.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ void FUnrealEnginePythonModule::StartupModule()
372372
}
373373

374374
// release the GIL
375-
UEPyGlobalState = PyEval_SaveThread();
375+
PyThreadState *UEPyGlobalState = PyEval_SaveThread();
376376
}
377377

378378
void FUnrealEnginePythonModule::ShutdownModule()

Source/UnrealEnginePython/Public/PythonHouseKeeper.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,8 @@ class FUnrealEnginePythonHouseKeeper
7171

7272
void RunGCDelegate()
7373
{
74-
PyGILState_STATE state = PyGILState_Ensure();
74+
FScopePythonGIL gil;
7575
RunGC();
76-
PyGILState_Release(state);
7776
}
7877

7978
int32 RunGC()

Source/UnrealEnginePython/Public/UnrealEnginePython.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,19 +122,19 @@ class UNREALENGINEPYTHON_API FUnrealEnginePythonModule : public IModuleInterface
122122
TSharedPtr<FSlateStyleSet> StyleSet;
123123
};
124124

125-
UNREALENGINEPYTHON_API extern PyThreadState* UEPyGlobalState;
126-
127125
struct FScopePythonGIL
128126
{
129127

128+
PyGILState_STATE state;
129+
130130
FScopePythonGIL()
131131
{
132-
PyEval_RestoreThread(UEPyGlobalState);
132+
state = PyGILState_Ensure();
133133
}
134134

135135
~FScopePythonGIL()
136136
{
137-
UEPyGlobalState = PyEval_SaveThread();
137+
PyGILState_Release(state);
138138
}
139139
};
140140

0 commit comments

Comments
 (0)