changeset 184:f34f3a149c22 java-code-model

added class PythonThreadsAllower
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 02 Jul 2024 15:49:05 +0200
parents d31f216c9462
children 7e8085f80df5
files CMakeLists.txt CodeAnalysis/FunctionBody.mustache CodeAnalysis/GenerateOrthancSDK.py CodeAnalysis/sdk.cpp.mustache NEWS Sources/Autogenerated/sdk.cpp Sources/Autogenerated/sdk_GlobalFunctions.impl.h Sources/Autogenerated/sdk_OrthancPluginDicomInstance.methods.h Sources/Autogenerated/sdk_OrthancPluginFindAnswers.methods.h Sources/Autogenerated/sdk_OrthancPluginFindMatcher.methods.h Sources/Autogenerated/sdk_OrthancPluginFindQuery.methods.h Sources/Autogenerated/sdk_OrthancPluginImage.methods.h Sources/Autogenerated/sdk_OrthancPluginJob.methods.h Sources/Autogenerated/sdk_OrthancPluginPeers.methods.h Sources/Autogenerated/sdk_OrthancPluginRestOutput.methods.h Sources/Autogenerated/sdk_OrthancPluginStorageArea.methods.h Sources/Autogenerated/sdk_OrthancPluginWorklistAnswers.methods.h Sources/Autogenerated/sdk_OrthancPluginWorklistQuery.methods.h Sources/PythonHeaderWrapper.h Sources/PythonLock.h Sources/PythonThreadsAllower.cpp Sources/PythonThreadsAllower.h
diffstat 22 files changed, 692 insertions(+), 154 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Tue Jul 02 14:52:20 2024 +0200
+++ b/CMakeLists.txt	Tue Jul 02 15:49:05 2024 +0200
@@ -184,6 +184,7 @@
   Sources/PythonModule.cpp
   Sources/PythonObject.cpp
   Sources/PythonString.cpp
+  Sources/PythonThreadsAllower.cpp
   Sources/ReceivedInstanceCallback.cpp
   Sources/RestCallbacks.cpp
   Sources/StorageArea.cpp
--- a/CodeAnalysis/FunctionBody.mustache	Tue Jul 02 14:52:20 2024 +0200
+++ b/CodeAnalysis/FunctionBody.mustache	Tue Jul 02 15:49:05 2024 +0200
@@ -17,16 +17,20 @@
   }
 {{/check_object_type}}{{/args}}
 {{#return_long}}
-  {{#allow_threads}}PyThreadState *_save = PyEval_SaveThread();{{/allow_threads}}
-  long value = {{c_function}}(OrthancPlugins::GetGlobalContext(){{self}}{{call_args}});
-  {{#allow_threads}}PyEval_RestoreThread(_save);{{/allow_threads}}
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = {{c_function}}(OrthancPlugins::GetGlobalContext(){{self}}{{call_args}});
+  }
   {{#args}}{{release}}{{/args}}
   return PyLong_FromLong(value);
 {{/return_long}}
 {{#return_static_string}}
-  {{#allow_threads}}PyThreadState *_save = PyEval_SaveThread();{{/allow_threads}}
-  const char* s = {{c_function}}(OrthancPlugins::GetGlobalContext(){{self}}{{call_args}});
-  {{#allow_threads}}PyEval_RestoreThread(_save);{{/allow_threads}}
+  const char* s;
+  {
+    PythonThreadsAllower allower;
+    s = {{c_function}}(OrthancPlugins::GetGlobalContext(){{self}}{{call_args}});
+  }
   {{#args}}{{release}}{{/args}}
   if (s == NULL)
   {
@@ -39,10 +43,11 @@
   }
 {{/return_static_string}}
 {{#return_dynamic_string}}
-  {{#allow_threads}}PyThreadState *_save = PyEval_SaveThread();{{/allow_threads}}
   OrthancPlugins::OrthancString s;
-  s.Assign({{c_function}}(OrthancPlugins::GetGlobalContext(){{self}}{{call_args}}));
-  {{#allow_threads}}PyEval_RestoreThread(_save);{{/allow_threads}}
+  {
+    PythonThreadsAllower allower;
+    s.Assign({{c_function}}(OrthancPlugins::GetGlobalContext(){{self}}{{call_args}}));
+  }
   {{#args}}{{release}}{{/args}}
   if (s.GetContent() == NULL)
   {
@@ -55,18 +60,21 @@
   }
 {{/return_dynamic_string}}
 {{#return_void}}
-  {{#allow_threads}}PyThreadState *_save = PyEval_SaveThread();{{/allow_threads}}
-  {{c_function}}(OrthancPlugins::GetGlobalContext(){{self}}{{call_args}});
-  {{#allow_threads}}PyEval_RestoreThread(_save);{{/allow_threads}}
+  {
+    PythonThreadsAllower allower;
+    {{c_function}}(OrthancPlugins::GetGlobalContext(){{self}}{{call_args}});
+  }
   {{#args}}{{release}}{{/args}}
 
   Py_INCREF(Py_None);
   return Py_None;
 {{/return_void}}
 {{#return_error}}
-  {{#allow_threads}}PyThreadState *_save = PyEval_SaveThread();{{/allow_threads}}
-  OrthancPluginErrorCode code = {{c_function}}(OrthancPlugins::GetGlobalContext(){{self}}{{call_args}});
-  {{#allow_threads}}PyEval_RestoreThread(_save);{{/allow_threads}}
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = {{c_function}}(OrthancPlugins::GetGlobalContext(){{self}}{{call_args}});
+  }
   {{#args}}{{release}}{{/args}}
 
   if (code == OrthancPluginErrorCode_Success)
@@ -82,9 +90,11 @@
 {{/return_error}}
 {{#return_object}}
   // This is the case of a constructor
-  {{#allow_threads}}PyThreadState *_save = PyEval_SaveThread();{{/allow_threads}}
-  {{return_object}}* obj = {{c_function}}(OrthancPlugins::GetGlobalContext(){{self}}{{call_args}});
-  {{#allow_threads}}PyEval_RestoreThread(_save);{{/allow_threads}}
+  {{return_object}}* obj;
+  {
+    PythonThreadsAllower allower;
+    obj = {{c_function}}(OrthancPlugins::GetGlobalContext(){{self}}{{call_args}});
+  }
   {{#args}}{{release}}{{/args}}
   if (obj == NULL)
   {
@@ -100,10 +110,12 @@
   }
 {{/return_object}}
 {{#return_bytes}}
-  {{#allow_threads}}PyThreadState *_save = PyEval_SaveThread();{{/allow_threads}}
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = {{c_function}}(OrthancPlugins::GetGlobalContext(), *buffer{{self}}{{call_args}});
-  {{#allow_threads}}PyEval_RestoreThread(_save);{{/allow_threads}}
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = {{c_function}}(OrthancPlugins::GetGlobalContext(), *buffer{{self}}{{call_args}});
+  }
   {{#args}}{{release}}{{/args}}
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -116,9 +128,11 @@
   }
 {{/return_bytes}}
 {{#return_enumeration}}
-  {{#allow_threads}}PyThreadState *_save = PyEval_SaveThread();{{/allow_threads}}
-  {{return_enumeration}} value = {{c_function}}(OrthancPlugins::GetGlobalContext(){{self}}{{call_args}});
-  {{#allow_threads}}PyEval_RestoreThread(_save);{{/allow_threads}}
+  {{return_enumeration}} value;
+  {
+    PythonThreadsAllower allower;
+    value = {{c_function}}(OrthancPlugins::GetGlobalContext(){{self}}{{call_args}});
+  }
   {{#args}}{{release}}{{/args}}
   return PyLong_FromLong(value);
 {{/return_enumeration}}
--- a/CodeAnalysis/GenerateOrthancSDK.py	Tue Jul 02 14:52:20 2024 +0200
+++ b/CodeAnalysis/GenerateOrthancSDK.py	Tue Jul 02 15:49:05 2024 +0200
@@ -220,7 +220,6 @@
         'count_args' : len(f['args']),
     }
 
-    allow_threads = True
     tuple_format = ''
     tuple_target = []
     call_args = []
@@ -235,7 +234,6 @@
                 'release' : 'PyBuffer_Release(&%s);' % arg['name'],
             })
             tuple_format += 's*'
-            allow_threads = False
         elif arg['sdk_type'] == 'const char *':
             args.append({
                 'name' : arg['name'],
@@ -243,7 +241,6 @@
                 'initialization' : ' = NULL',
             })
             tuple_format += 's'
-            allow_threads = False
         elif arg['sdk_type'] == 'enumeration':
             args.append({
                 'name' : arg['name'],
@@ -259,7 +256,6 @@
                 'check_object_type' : arg['sdk_class'],
             })
             tuple_format += 'O'
-            allow_threads = False
         elif arg['sdk_type'] in ORTHANC_TO_PYTHON_NUMERIC_TYPES:
             t = ORTHANC_TO_PYTHON_NUMERIC_TYPES[arg['sdk_type']]
             args.append({
@@ -310,10 +306,7 @@
         print('Ignoring function with unsupported return type: %s(), type = %s' % (f['c_function'], f['return_sdk_type']))
         return None
 
-    allow_threads = False   # TODO
-
     answer['tuple_format'] = ', '.join([ '"' + tuple_format + '"' ] + tuple_target)
-    answer['allow_threads'] = allow_threads
 
     if 'documentation' in f:
         answer['documentation'] = DocumentFunction(f)
@@ -321,9 +314,6 @@
     if len(call_args) > 0:
         answer['call_args'] = ', ' + ', '.join(call_args)
 
-    if not allow_threads:
-        print('Threads are not allowed in function: %s()' % f['c_function'])
-
     return answer
 
 
--- a/CodeAnalysis/sdk.cpp.mustache	Tue Jul 02 14:52:20 2024 +0200
+++ b/CodeAnalysis/sdk.cpp.mustache	Tue Jul 02 15:49:05 2024 +0200
@@ -22,6 +22,7 @@
 #include "sdk.h"
 
 #include "../PythonLock.h"
+#include "../PythonThreadsAllower.h"
 
 #include "../../Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h"
 
--- a/NEWS	Tue Jul 02 14:52:20 2024 +0200
+++ b/NEWS	Tue Jul 02 15:49:05 2024 +0200
@@ -2,6 +2,7 @@
 ===============================
 
 * Created Python documentation for the Orthanc interface, check out "orthanc.pyi"
+* Added possibility to release the GIL during the call to the native SDK functions
 * Added Windows builder for Python 3.12
 
 
--- a/Sources/Autogenerated/sdk.cpp	Tue Jul 02 14:52:20 2024 +0200
+++ b/Sources/Autogenerated/sdk.cpp	Tue Jul 02 15:49:05 2024 +0200
@@ -22,6 +22,7 @@
 #include "sdk.h"
 
 #include "../PythonLock.h"
+#include "../PythonThreadsAllower.h"
 
 #include "../../Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h"
 
--- a/Sources/Autogenerated/sdk_GlobalFunctions.impl.h	Tue Jul 02 14:52:20 2024 +0200
+++ b/Sources/Autogenerated/sdk_GlobalFunctions.impl.h	Tue Jul 02 15:49:05 2024 +0200
@@ -31,7 +31,11 @@
     return NULL;
   }
 
-  const char* s = OrthancPluginAutodetectMimeType(OrthancPlugins::GetGlobalContext(), arg0);
+  const char* s;
+  {
+    PythonThreadsAllower allower;
+    s = OrthancPluginAutodetectMimeType(OrthancPlugins::GetGlobalContext(), arg0);
+  }
   
   if (s == NULL)
   {
@@ -59,7 +63,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginBufferCompression(OrthancPlugins::GetGlobalContext(), *buffer, arg0.buf, arg0.len, static_cast<OrthancPluginCompressionType>(arg2), arg3);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginBufferCompression(OrthancPlugins::GetGlobalContext(), *buffer, arg0.buf, arg0.len, static_cast<OrthancPluginCompressionType>(arg2), arg3);
+  }
   PyBuffer_Release(&arg0);
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -78,7 +86,11 @@
 
 
 
-  long value = OrthancPluginCheckVersion(OrthancPlugins::GetGlobalContext());
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginCheckVersion(OrthancPlugins::GetGlobalContext());
+  }
   
   return PyLong_FromLong(value);
 }
@@ -97,7 +109,11 @@
     return NULL;
   }
 
-  long value = OrthancPluginCheckVersionAdvanced(OrthancPlugins::GetGlobalContext(), arg0, arg1, arg2);
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginCheckVersionAdvanced(OrthancPlugins::GetGlobalContext(), arg0, arg1, arg2);
+  }
   
   return PyLong_FromLong(value);
 }
@@ -120,7 +136,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginCompressJpegImage(OrthancPlugins::GetGlobalContext(), *buffer, static_cast<OrthancPluginPixelFormat>(arg0), arg1, arg2, arg3, arg4.buf, arg5);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginCompressJpegImage(OrthancPlugins::GetGlobalContext(), *buffer, static_cast<OrthancPluginPixelFormat>(arg0), arg1, arg2, arg3, arg4.buf, arg5);
+  }
   PyBuffer_Release(&arg4);
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -150,7 +170,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginCompressPngImage(OrthancPlugins::GetGlobalContext(), *buffer, static_cast<OrthancPluginPixelFormat>(arg0), arg1, arg2, arg3, arg4.buf);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginCompressPngImage(OrthancPlugins::GetGlobalContext(), *buffer, static_cast<OrthancPluginPixelFormat>(arg0), arg1, arg2, arg3, arg4.buf);
+  }
   PyBuffer_Release(&arg4);
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -176,7 +200,10 @@
   }
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginComputeMd5(OrthancPlugins::GetGlobalContext(), arg0.buf, arg0.len));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginComputeMd5(OrthancPlugins::GetGlobalContext(), arg0.buf, arg0.len));
+  }
   PyBuffer_Release(&arg0);
   if (s.GetContent() == NULL)
   {
@@ -202,7 +229,10 @@
   }
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginComputeSha1(OrthancPlugins::GetGlobalContext(), arg0.buf, arg0.len));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginComputeSha1(OrthancPlugins::GetGlobalContext(), arg0.buf, arg0.len));
+  }
   PyBuffer_Release(&arg0);
   if (s.GetContent() == NULL)
   {
@@ -236,7 +266,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginCreateDicom(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1 == Py_None ? NULL : reinterpret_cast<sdk_OrthancPluginImage_Object*>(arg1)->object_, static_cast<OrthancPluginCreateDicomFlags>(arg2));
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginCreateDicom(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1 == Py_None ? NULL : reinterpret_cast<sdk_OrthancPluginImage_Object*>(arg1)->object_, static_cast<OrthancPluginCreateDicomFlags>(arg2));
+  }
   
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -271,7 +305,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginCreateDicom2(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1 == Py_None ? NULL : reinterpret_cast<sdk_OrthancPluginImage_Object*>(arg1)->object_, static_cast<OrthancPluginCreateDicomFlags>(arg2), arg3);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginCreateDicom2(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1 == Py_None ? NULL : reinterpret_cast<sdk_OrthancPluginImage_Object*>(arg1)->object_, static_cast<OrthancPluginCreateDicomFlags>(arg2), arg3);
+  }
   
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -297,7 +335,11 @@
   }
 
   // This is the case of a constructor
-  OrthancPluginDicomInstance* obj = OrthancPluginCreateDicomInstance(OrthancPlugins::GetGlobalContext(), arg0.buf, arg0.len);
+  OrthancPluginDicomInstance* obj;
+  {
+    PythonThreadsAllower allower;
+    obj = OrthancPluginCreateDicomInstance(OrthancPlugins::GetGlobalContext(), arg0.buf, arg0.len);
+  }
   PyBuffer_Release(&arg0);
   if (obj == NULL)
   {
@@ -326,7 +368,11 @@
   }
 
   // This is the case of a constructor
-  OrthancPluginFindMatcher* obj = OrthancPluginCreateFindMatcher(OrthancPlugins::GetGlobalContext(), arg0.buf, arg0.len);
+  OrthancPluginFindMatcher* obj;
+  {
+    PythonThreadsAllower allower;
+    obj = OrthancPluginCreateFindMatcher(OrthancPlugins::GetGlobalContext(), arg0.buf, arg0.len);
+  }
   PyBuffer_Release(&arg0);
   if (obj == NULL)
   {
@@ -357,7 +403,11 @@
   }
 
   // This is the case of a constructor
-  OrthancPluginImage* obj = OrthancPluginCreateImage(OrthancPlugins::GetGlobalContext(), static_cast<OrthancPluginPixelFormat>(arg0), arg1, arg2);
+  OrthancPluginImage* obj;
+  {
+    PythonThreadsAllower allower;
+    obj = OrthancPluginCreateImage(OrthancPlugins::GetGlobalContext(), static_cast<OrthancPluginPixelFormat>(arg0), arg1, arg2);
+  }
   
   if (obj == NULL)
   {
@@ -386,7 +436,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginCreateMemoryBuffer(OrthancPlugins::GetGlobalContext(), *buffer, arg0);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginCreateMemoryBuffer(OrthancPlugins::GetGlobalContext(), *buffer, arg0);
+  }
   
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -413,7 +467,11 @@
   }
 
   // This is the case of a constructor
-  OrthancPluginImage* obj = OrthancPluginDecodeDicomImage(OrthancPlugins::GetGlobalContext(), arg0.buf, arg0.len, arg2);
+  OrthancPluginImage* obj;
+  {
+    PythonThreadsAllower allower;
+    obj = OrthancPluginDecodeDicomImage(OrthancPlugins::GetGlobalContext(), arg0.buf, arg0.len, arg2);
+  }
   PyBuffer_Release(&arg0);
   if (obj == NULL)
   {
@@ -445,7 +503,10 @@
   }
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginDicomBufferToJson(OrthancPlugins::GetGlobalContext(), arg0.buf, arg0.len, static_cast<OrthancPluginDicomToJsonFormat>(arg2), static_cast<OrthancPluginDicomToJsonFlags>(arg3), arg4));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginDicomBufferToJson(OrthancPlugins::GetGlobalContext(), arg0.buf, arg0.len, static_cast<OrthancPluginDicomToJsonFormat>(arg2), static_cast<OrthancPluginDicomToJsonFlags>(arg3), arg4));
+  }
   PyBuffer_Release(&arg0);
   if (s.GetContent() == NULL)
   {
@@ -474,7 +535,10 @@
   }
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginDicomInstanceToJson(OrthancPlugins::GetGlobalContext(), arg0, static_cast<OrthancPluginDicomToJsonFormat>(arg1), static_cast<OrthancPluginDicomToJsonFlags>(arg2), arg3));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginDicomInstanceToJson(OrthancPlugins::GetGlobalContext(), arg0, static_cast<OrthancPluginDicomToJsonFormat>(arg1), static_cast<OrthancPluginDicomToJsonFlags>(arg2), arg3));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -499,7 +563,10 @@
     return NULL;
   }
 
-  OrthancPluginExtendOrthancExplorer(OrthancPlugins::GetGlobalContext(), arg0);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginExtendOrthancExplorer(OrthancPlugins::GetGlobalContext(), arg0);
+  }
   
 
   Py_INCREF(Py_None);
@@ -513,7 +580,10 @@
 
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginGenerateRestApiAuthorizationToken(OrthancPlugins::GetGlobalContext()));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginGenerateRestApiAuthorizationToken(OrthancPlugins::GetGlobalContext()));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -533,7 +603,10 @@
 
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginGenerateUuid(OrthancPlugins::GetGlobalContext()));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginGenerateUuid(OrthancPlugins::GetGlobalContext()));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -559,7 +632,10 @@
   }
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginGetCommandLineArgument(OrthancPlugins::GetGlobalContext(), arg0));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginGetCommandLineArgument(OrthancPlugins::GetGlobalContext(), arg0));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -578,7 +654,11 @@
 
 
 
-  long value = OrthancPluginGetCommandLineArgumentsCount(OrthancPlugins::GetGlobalContext());
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginGetCommandLineArgumentsCount(OrthancPlugins::GetGlobalContext());
+  }
   
   return PyLong_FromLong(value);
 }
@@ -590,7 +670,10 @@
 
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginGetConfiguration(OrthancPlugins::GetGlobalContext()));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginGetConfiguration(OrthancPlugins::GetGlobalContext()));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -610,7 +693,10 @@
 
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginGetConfigurationPath(OrthancPlugins::GetGlobalContext()));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginGetConfigurationPath(OrthancPlugins::GetGlobalContext()));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -636,7 +722,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginGetDicomForInstance(OrthancPlugins::GetGlobalContext(), *buffer, arg0);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginGetDicomForInstance(OrthancPlugins::GetGlobalContext(), *buffer, arg0);
+  }
   
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -661,7 +751,11 @@
     return NULL;
   }
 
-  const char* s = OrthancPluginGetErrorDescription(OrthancPlugins::GetGlobalContext(), static_cast<OrthancPluginErrorCode>(arg0));
+  const char* s;
+  {
+    PythonThreadsAllower allower;
+    s = OrthancPluginGetErrorDescription(OrthancPlugins::GetGlobalContext(), static_cast<OrthancPluginErrorCode>(arg0));
+  }
   
   if (s == NULL)
   {
@@ -680,7 +774,11 @@
 
 
 
-  long value = OrthancPluginGetExpectedDatabaseVersion(OrthancPlugins::GetGlobalContext());
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginGetExpectedDatabaseVersion(OrthancPlugins::GetGlobalContext());
+  }
   
   return PyLong_FromLong(value);
 }
@@ -697,7 +795,11 @@
     return NULL;
   }
 
-  const char* s = OrthancPluginGetFontName(OrthancPlugins::GetGlobalContext(), arg0);
+  const char* s;
+  {
+    PythonThreadsAllower allower;
+    s = OrthancPluginGetFontName(OrthancPlugins::GetGlobalContext(), arg0);
+  }
   
   if (s == NULL)
   {
@@ -722,7 +824,11 @@
     return NULL;
   }
 
-  long value = OrthancPluginGetFontSize(OrthancPlugins::GetGlobalContext(), arg0);
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginGetFontSize(OrthancPlugins::GetGlobalContext(), arg0);
+  }
   
   return PyLong_FromLong(value);
 }
@@ -733,7 +839,11 @@
 
 
 
-  long value = OrthancPluginGetFontsCount(OrthancPlugins::GetGlobalContext());
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginGetFontsCount(OrthancPlugins::GetGlobalContext());
+  }
   
   return PyLong_FromLong(value);
 }
@@ -752,7 +862,10 @@
   }
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginGetGlobalProperty(OrthancPlugins::GetGlobalContext(), arg0, arg1));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginGetGlobalProperty(OrthancPlugins::GetGlobalContext(), arg0, arg1));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -772,7 +885,10 @@
 
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginGetOrthancDirectory(OrthancPlugins::GetGlobalContext()));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginGetOrthancDirectory(OrthancPlugins::GetGlobalContext()));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -792,7 +908,10 @@
 
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginGetOrthancPath(OrthancPlugins::GetGlobalContext()));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginGetOrthancPath(OrthancPlugins::GetGlobalContext()));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -812,7 +931,11 @@
 
 
   // This is the case of a constructor
-  OrthancPluginPeers* obj = OrthancPluginGetPeers(OrthancPlugins::GetGlobalContext());
+  OrthancPluginPeers* obj;
+  {
+    PythonThreadsAllower allower;
+    obj = OrthancPluginGetPeers(OrthancPlugins::GetGlobalContext());
+  }
   
   if (obj == NULL)
   {
@@ -843,7 +966,10 @@
   }
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginGetTagName(OrthancPlugins::GetGlobalContext(), arg0, arg1, arg2));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginGetTagName(OrthancPlugins::GetGlobalContext(), arg0, arg1, arg2));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -870,7 +996,11 @@
     return NULL;
   }
 
-  OrthancPluginErrorCode code = OrthancPluginHttpDelete(OrthancPlugins::GetGlobalContext(), arg0, arg1, arg2);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginHttpDelete(OrthancPlugins::GetGlobalContext(), arg0, arg1, arg2);
+  }
   
 
   if (code == OrthancPluginErrorCode_Success)
@@ -900,7 +1030,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginHttpGet(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1, arg2);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginHttpGet(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1, arg2);
+  }
   
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -929,7 +1063,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginHttpPost(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1.buf, arg1.len, arg3, arg4);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginHttpPost(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1.buf, arg1.len, arg3, arg4);
+  }
   PyBuffer_Release(&arg1);
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -958,7 +1096,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginHttpPut(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1.buf, arg1.len, arg3, arg4);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginHttpPut(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1.buf, arg1.len, arg3, arg4);
+  }
   PyBuffer_Release(&arg1);
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -983,7 +1125,10 @@
     return NULL;
   }
 
-  OrthancPluginLogError(OrthancPlugins::GetGlobalContext(), arg0);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginLogError(OrthancPlugins::GetGlobalContext(), arg0);
+  }
   
 
   Py_INCREF(Py_None);
@@ -1002,7 +1147,10 @@
     return NULL;
   }
 
-  OrthancPluginLogInfo(OrthancPlugins::GetGlobalContext(), arg0);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginLogInfo(OrthancPlugins::GetGlobalContext(), arg0);
+  }
   
 
   Py_INCREF(Py_None);
@@ -1021,7 +1169,10 @@
     return NULL;
   }
 
-  OrthancPluginLogWarning(OrthancPlugins::GetGlobalContext(), arg0);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginLogWarning(OrthancPlugins::GetGlobalContext(), arg0);
+  }
   
 
   Py_INCREF(Py_None);
@@ -1041,7 +1192,10 @@
   }
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginLookupInstance(OrthancPlugins::GetGlobalContext(), arg0));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginLookupInstance(OrthancPlugins::GetGlobalContext(), arg0));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -1067,7 +1221,10 @@
   }
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginLookupPatient(OrthancPlugins::GetGlobalContext(), arg0));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginLookupPatient(OrthancPlugins::GetGlobalContext(), arg0));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -1093,7 +1250,10 @@
   }
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginLookupSeries(OrthancPlugins::GetGlobalContext(), arg0));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginLookupSeries(OrthancPlugins::GetGlobalContext(), arg0));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -1119,7 +1279,10 @@
   }
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginLookupStudy(OrthancPlugins::GetGlobalContext(), arg0));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginLookupStudy(OrthancPlugins::GetGlobalContext(), arg0));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -1145,7 +1308,10 @@
   }
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginLookupStudyWithAccessionNumber(OrthancPlugins::GetGlobalContext(), arg0));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginLookupStudyWithAccessionNumber(OrthancPlugins::GetGlobalContext(), arg0));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -1171,7 +1337,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginReadFile(OrthancPlugins::GetGlobalContext(), *buffer, arg0);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginReadFile(OrthancPlugins::GetGlobalContext(), *buffer, arg0);
+  }
   
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -1201,7 +1371,11 @@
     return NULL;
   }
 
-  OrthancPluginErrorCode code = OrthancPluginRegisterDictionaryTag(OrthancPlugins::GetGlobalContext(), arg0, arg1, static_cast<OrthancPluginValueRepresentation>(arg2), arg3, arg4, arg5);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginRegisterDictionaryTag(OrthancPlugins::GetGlobalContext(), arg0, arg1, static_cast<OrthancPluginValueRepresentation>(arg2), arg3, arg4, arg5);
+  }
   
 
   if (code == OrthancPluginErrorCode_Success)
@@ -1230,7 +1404,11 @@
     return NULL;
   }
 
-  OrthancPluginErrorCode code = OrthancPluginRegisterErrorCode(OrthancPlugins::GetGlobalContext(), arg0, arg1, arg2);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginRegisterErrorCode(OrthancPlugins::GetGlobalContext(), arg0, arg1, arg2);
+  }
   
 
   if (code == OrthancPluginErrorCode_Success)
@@ -1263,7 +1441,11 @@
     return NULL;
   }
 
-  OrthancPluginErrorCode code = OrthancPluginRegisterPrivateDictionaryTag(OrthancPlugins::GetGlobalContext(), arg0, arg1, static_cast<OrthancPluginValueRepresentation>(arg2), arg3, arg4, arg5, arg6);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginRegisterPrivateDictionaryTag(OrthancPlugins::GetGlobalContext(), arg0, arg1, static_cast<OrthancPluginValueRepresentation>(arg2), arg3, arg4, arg5, arg6);
+  }
   
 
   if (code == OrthancPluginErrorCode_Success)
@@ -1290,7 +1472,11 @@
     return NULL;
   }
 
-  OrthancPluginErrorCode code = OrthancPluginRestApiDelete(OrthancPlugins::GetGlobalContext(), arg0);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginRestApiDelete(OrthancPlugins::GetGlobalContext(), arg0);
+  }
   
 
   if (code == OrthancPluginErrorCode_Success)
@@ -1317,7 +1503,11 @@
     return NULL;
   }
 
-  OrthancPluginErrorCode code = OrthancPluginRestApiDeleteAfterPlugins(OrthancPlugins::GetGlobalContext(), arg0);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginRestApiDeleteAfterPlugins(OrthancPlugins::GetGlobalContext(), arg0);
+  }
   
 
   if (code == OrthancPluginErrorCode_Success)
@@ -1345,7 +1535,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginRestApiGet(OrthancPlugins::GetGlobalContext(), *buffer, arg0);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginRestApiGet(OrthancPlugins::GetGlobalContext(), *buffer, arg0);
+  }
   
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -1371,7 +1565,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginRestApiGetAfterPlugins(OrthancPlugins::GetGlobalContext(), *buffer, arg0);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginRestApiGetAfterPlugins(OrthancPlugins::GetGlobalContext(), *buffer, arg0);
+  }
   
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -1398,7 +1596,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginRestApiPost(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1.buf, arg1.len);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginRestApiPost(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1.buf, arg1.len);
+  }
   PyBuffer_Release(&arg1);
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -1425,7 +1627,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginRestApiPostAfterPlugins(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1.buf, arg1.len);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginRestApiPostAfterPlugins(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1.buf, arg1.len);
+  }
   PyBuffer_Release(&arg1);
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -1452,7 +1658,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginRestApiPut(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1.buf, arg1.len);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginRestApiPut(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1.buf, arg1.len);
+  }
   PyBuffer_Release(&arg1);
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -1479,7 +1689,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginRestApiPutAfterPlugins(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1.buf, arg1.len);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginRestApiPutAfterPlugins(OrthancPlugins::GetGlobalContext(), *buffer, arg0, arg1.buf, arg1.len);
+  }
   PyBuffer_Release(&arg1);
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -1504,7 +1718,10 @@
     return NULL;
   }
 
-  OrthancPluginSetDescription(OrthancPlugins::GetGlobalContext(), arg0);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginSetDescription(OrthancPlugins::GetGlobalContext(), arg0);
+  }
   
 
   Py_INCREF(Py_None);
@@ -1524,7 +1741,11 @@
     return NULL;
   }
 
-  OrthancPluginErrorCode code = OrthancPluginSetGlobalProperty(OrthancPlugins::GetGlobalContext(), arg0, arg1);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginSetGlobalProperty(OrthancPlugins::GetGlobalContext(), arg0, arg1);
+  }
   
 
   if (code == OrthancPluginErrorCode_Success)
@@ -1553,7 +1774,10 @@
     return NULL;
   }
 
-  OrthancPluginSetMetricsValue(OrthancPlugins::GetGlobalContext(), arg0, arg1, static_cast<OrthancPluginMetricsType>(arg2));
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginSetMetricsValue(OrthancPlugins::GetGlobalContext(), arg0, arg1, static_cast<OrthancPluginMetricsType>(arg2));
+  }
   
 
   Py_INCREF(Py_None);
@@ -1572,7 +1796,10 @@
     return NULL;
   }
 
-  OrthancPluginSetRootUri(OrthancPlugins::GetGlobalContext(), arg0);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginSetRootUri(OrthancPlugins::GetGlobalContext(), arg0);
+  }
   
 
   Py_INCREF(Py_None);
@@ -1593,7 +1820,11 @@
   }
 
   // This is the case of a constructor
-  OrthancPluginDicomInstance* obj = OrthancPluginTranscodeDicomInstance(OrthancPlugins::GetGlobalContext(), arg0.buf, arg0.len, arg2);
+  OrthancPluginDicomInstance* obj;
+  {
+    PythonThreadsAllower allower;
+    obj = OrthancPluginTranscodeDicomInstance(OrthancPlugins::GetGlobalContext(), arg0.buf, arg0.len, arg2);
+  }
   PyBuffer_Release(&arg0);
   if (obj == NULL)
   {
@@ -1623,7 +1854,11 @@
   }
 
   // This is the case of a constructor
-  OrthancPluginImage* obj = OrthancPluginUncompressImage(OrthancPlugins::GetGlobalContext(), arg0.buf, arg0.len, static_cast<OrthancPluginImageFormat>(arg2));
+  OrthancPluginImage* obj;
+  {
+    PythonThreadsAllower allower;
+    obj = OrthancPluginUncompressImage(OrthancPlugins::GetGlobalContext(), arg0.buf, arg0.len, static_cast<OrthancPluginImageFormat>(arg2));
+  }
   PyBuffer_Release(&arg0);
   if (obj == NULL)
   {
@@ -1652,7 +1887,11 @@
     return NULL;
   }
 
-  OrthancPluginErrorCode code = OrthancPluginWriteFile(OrthancPlugins::GetGlobalContext(), arg0, arg1.buf, arg1.len);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginWriteFile(OrthancPlugins::GetGlobalContext(), arg0, arg1.buf, arg1.len);
+  }
   PyBuffer_Release(&arg1);
 
   if (code == OrthancPluginErrorCode_Success)
--- a/Sources/Autogenerated/sdk_OrthancPluginDicomInstance.methods.h	Tue Jul 02 14:52:20 2024 +0200
+++ b/Sources/Autogenerated/sdk_OrthancPluginDicomInstance.methods.h	Tue Jul 02 15:49:05 2024 +0200
@@ -12,7 +12,11 @@
 
 
 
-  const char* s = OrthancPluginGetInstanceRemoteAet(OrthancPlugins::GetGlobalContext(), self->object_);
+  const char* s;
+  {
+    PythonThreadsAllower allower;
+    s = OrthancPluginGetInstanceRemoteAet(OrthancPlugins::GetGlobalContext(), self->object_);
+  }
   
   if (s == NULL)
   {
@@ -38,7 +42,11 @@
 
 
 
-  long value = OrthancPluginGetInstanceSize(OrthancPlugins::GetGlobalContext(), self->object_);
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginGetInstanceSize(OrthancPlugins::GetGlobalContext(), self->object_);
+  }
   
   return PyLong_FromLong(value);
 }
@@ -57,7 +65,10 @@
 
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginGetInstanceJson(OrthancPlugins::GetGlobalContext(), self->object_));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginGetInstanceJson(OrthancPlugins::GetGlobalContext(), self->object_));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -84,7 +95,10 @@
 
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginGetInstanceSimplifiedJson(OrthancPlugins::GetGlobalContext(), self->object_));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginGetInstanceSimplifiedJson(OrthancPlugins::GetGlobalContext(), self->object_));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -116,7 +130,11 @@
     return NULL;
   }
 
-  long value = OrthancPluginHasInstanceMetadata(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginHasInstanceMetadata(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  }
   
   return PyLong_FromLong(value);
 }
@@ -140,7 +158,11 @@
     return NULL;
   }
 
-  const char* s = OrthancPluginGetInstanceMetadata(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  const char* s;
+  {
+    PythonThreadsAllower allower;
+    s = OrthancPluginGetInstanceMetadata(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  }
   
   if (s == NULL)
   {
@@ -166,7 +188,11 @@
 
 
 
-  OrthancPluginInstanceOrigin value = OrthancPluginGetInstanceOrigin(OrthancPlugins::GetGlobalContext(), self->object_);
+  OrthancPluginInstanceOrigin value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginGetInstanceOrigin(OrthancPlugins::GetGlobalContext(), self->object_);
+  }
   
   return PyLong_FromLong(value);
 }
@@ -185,7 +211,10 @@
 
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginGetInstanceTransferSyntaxUid(OrthancPlugins::GetGlobalContext(), self->object_));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginGetInstanceTransferSyntaxUid(OrthancPlugins::GetGlobalContext(), self->object_));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -211,7 +240,11 @@
 
 
 
-  long value = OrthancPluginHasInstancePixelData(OrthancPlugins::GetGlobalContext(), self->object_);
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginHasInstancePixelData(OrthancPlugins::GetGlobalContext(), self->object_);
+  }
   
   return PyLong_FromLong(value);
 }
@@ -229,7 +262,11 @@
 
 
 
-  long value = OrthancPluginGetInstanceFramesCount(OrthancPlugins::GetGlobalContext(), self->object_);
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginGetInstanceFramesCount(OrthancPlugins::GetGlobalContext(), self->object_);
+  }
   
   return PyLong_FromLong(value);
 }
@@ -254,7 +291,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginGetInstanceRawFrame(OrthancPlugins::GetGlobalContext(), *buffer, self->object_, arg0);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginGetInstanceRawFrame(OrthancPlugins::GetGlobalContext(), *buffer, self->object_, arg0);
+  }
   
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -287,7 +328,11 @@
   }
 
   // This is the case of a constructor
-  OrthancPluginImage* obj = OrthancPluginGetInstanceDecodedFrame(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  OrthancPluginImage* obj;
+  {
+    PythonThreadsAllower allower;
+    obj = OrthancPluginGetInstanceDecodedFrame(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  }
   
   if (obj == NULL)
   {
@@ -317,7 +362,11 @@
 
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginSerializeDicomInstance(OrthancPlugins::GetGlobalContext(), *buffer, self->object_);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginSerializeDicomInstance(OrthancPlugins::GetGlobalContext(), *buffer, self->object_);
+  }
   
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -352,7 +401,10 @@
   }
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginGetInstanceAdvancedJson(OrthancPlugins::GetGlobalContext(), self->object_, static_cast<OrthancPluginDicomToJsonFormat>(arg0), static_cast<OrthancPluginDicomToJsonFlags>(arg1), arg2));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginGetInstanceAdvancedJson(OrthancPlugins::GetGlobalContext(), self->object_, static_cast<OrthancPluginDicomToJsonFormat>(arg0), static_cast<OrthancPluginDicomToJsonFlags>(arg1), arg2));
+  }
   
   if (s.GetContent() == NULL)
   {
--- a/Sources/Autogenerated/sdk_OrthancPluginFindAnswers.methods.h	Tue Jul 02 14:52:20 2024 +0200
+++ b/Sources/Autogenerated/sdk_OrthancPluginFindAnswers.methods.h	Tue Jul 02 15:49:05 2024 +0200
@@ -18,7 +18,11 @@
     return NULL;
   }
 
-  OrthancPluginErrorCode code = OrthancPluginFindAddAnswer(OrthancPlugins::GetGlobalContext(), self->object_, arg0.buf, arg0.len);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginFindAddAnswer(OrthancPlugins::GetGlobalContext(), self->object_, arg0.buf, arg0.len);
+  }
   PyBuffer_Release(&arg0);
 
   if (code == OrthancPluginErrorCode_Success)
@@ -46,7 +50,11 @@
 
 
 
-  OrthancPluginErrorCode code = OrthancPluginFindMarkIncomplete(OrthancPlugins::GetGlobalContext(), self->object_);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginFindMarkIncomplete(OrthancPlugins::GetGlobalContext(), self->object_);
+  }
   
 
   if (code == OrthancPluginErrorCode_Success)
--- a/Sources/Autogenerated/sdk_OrthancPluginFindMatcher.methods.h	Tue Jul 02 14:52:20 2024 +0200
+++ b/Sources/Autogenerated/sdk_OrthancPluginFindMatcher.methods.h	Tue Jul 02 15:49:05 2024 +0200
@@ -18,7 +18,11 @@
     return NULL;
   }
 
-  long value = OrthancPluginFindMatcherIsMatch(OrthancPlugins::GetGlobalContext(), self->object_, arg0.buf, arg0.len);
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginFindMatcherIsMatch(OrthancPlugins::GetGlobalContext(), self->object_, arg0.buf, arg0.len);
+  }
   PyBuffer_Release(&arg0);
   return PyLong_FromLong(value);
 }
--- a/Sources/Autogenerated/sdk_OrthancPluginFindQuery.methods.h	Tue Jul 02 14:52:20 2024 +0200
+++ b/Sources/Autogenerated/sdk_OrthancPluginFindQuery.methods.h	Tue Jul 02 15:49:05 2024 +0200
@@ -12,7 +12,11 @@
 
 
 
-  long value = OrthancPluginGetFindQuerySize(OrthancPlugins::GetGlobalContext(), self->object_);
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginGetFindQuerySize(OrthancPlugins::GetGlobalContext(), self->object_);
+  }
   
   return PyLong_FromLong(value);
 }
@@ -37,7 +41,10 @@
   }
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginGetFindQueryTagName(OrthancPlugins::GetGlobalContext(), self->object_, arg0));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginGetFindQueryTagName(OrthancPlugins::GetGlobalContext(), self->object_, arg0));
+  }
   
   if (s.GetContent() == NULL)
   {
@@ -70,7 +77,10 @@
   }
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginGetFindQueryValue(OrthancPlugins::GetGlobalContext(), self->object_, arg0));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginGetFindQueryValue(OrthancPlugins::GetGlobalContext(), self->object_, arg0));
+  }
   
   if (s.GetContent() == NULL)
   {
--- a/Sources/Autogenerated/sdk_OrthancPluginImage.methods.h	Tue Jul 02 14:52:20 2024 +0200
+++ b/Sources/Autogenerated/sdk_OrthancPluginImage.methods.h	Tue Jul 02 15:49:05 2024 +0200
@@ -12,7 +12,11 @@
 
 
 
-  OrthancPluginPixelFormat value = OrthancPluginGetImagePixelFormat(OrthancPlugins::GetGlobalContext(), self->object_);
+  OrthancPluginPixelFormat value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginGetImagePixelFormat(OrthancPlugins::GetGlobalContext(), self->object_);
+  }
   
   return PyLong_FromLong(value);
 }
@@ -30,7 +34,11 @@
 
 
 
-  long value = OrthancPluginGetImageWidth(OrthancPlugins::GetGlobalContext(), self->object_);
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginGetImageWidth(OrthancPlugins::GetGlobalContext(), self->object_);
+  }
   
   return PyLong_FromLong(value);
 }
@@ -48,7 +56,11 @@
 
 
 
-  long value = OrthancPluginGetImageHeight(OrthancPlugins::GetGlobalContext(), self->object_);
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginGetImageHeight(OrthancPlugins::GetGlobalContext(), self->object_);
+  }
   
   return PyLong_FromLong(value);
 }
@@ -66,7 +78,11 @@
 
 
 
-  long value = OrthancPluginGetImagePitch(OrthancPlugins::GetGlobalContext(), self->object_);
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginGetImagePitch(OrthancPlugins::GetGlobalContext(), self->object_);
+  }
   
   return PyLong_FromLong(value);
 }
@@ -91,7 +107,11 @@
   }
 
   // This is the case of a constructor
-  OrthancPluginImage* obj = OrthancPluginConvertPixelFormat(OrthancPlugins::GetGlobalContext(), self->object_, static_cast<OrthancPluginPixelFormat>(arg0));
+  OrthancPluginImage* obj;
+  {
+    PythonThreadsAllower allower;
+    obj = OrthancPluginConvertPixelFormat(OrthancPlugins::GetGlobalContext(), self->object_, static_cast<OrthancPluginPixelFormat>(arg0));
+  }
   
   if (obj == NULL)
   {
@@ -132,7 +152,11 @@
     return NULL;
   }
 
-  OrthancPluginErrorCode code = OrthancPluginDrawText(OrthancPlugins::GetGlobalContext(), self->object_, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginDrawText(OrthancPlugins::GetGlobalContext(), self->object_, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
+  }
   
 
   if (code == OrthancPluginErrorCode_Success)
--- a/Sources/Autogenerated/sdk_OrthancPluginJob.methods.h	Tue Jul 02 14:52:20 2024 +0200
+++ b/Sources/Autogenerated/sdk_OrthancPluginJob.methods.h	Tue Jul 02 15:49:05 2024 +0200
@@ -19,7 +19,10 @@
   }
 
   OrthancPlugins::OrthancString s;
-  s.Assign(OrthancPluginSubmitJob(OrthancPlugins::GetGlobalContext(), self->object_, arg0));
+  {
+    PythonThreadsAllower allower;
+    s.Assign(OrthancPluginSubmitJob(OrthancPlugins::GetGlobalContext(), self->object_, arg0));
+  }
   
   if (s.GetContent() == NULL)
   {
--- a/Sources/Autogenerated/sdk_OrthancPluginPeers.methods.h	Tue Jul 02 14:52:20 2024 +0200
+++ b/Sources/Autogenerated/sdk_OrthancPluginPeers.methods.h	Tue Jul 02 15:49:05 2024 +0200
@@ -12,7 +12,11 @@
 
 
 
-  long value = OrthancPluginGetPeersCount(OrthancPlugins::GetGlobalContext(), self->object_);
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginGetPeersCount(OrthancPlugins::GetGlobalContext(), self->object_);
+  }
   
   return PyLong_FromLong(value);
 }
@@ -36,7 +40,11 @@
     return NULL;
   }
 
-  const char* s = OrthancPluginGetPeerName(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  const char* s;
+  {
+    PythonThreadsAllower allower;
+    s = OrthancPluginGetPeerName(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  }
   
   if (s == NULL)
   {
@@ -68,7 +76,11 @@
     return NULL;
   }
 
-  const char* s = OrthancPluginGetPeerUrl(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  const char* s;
+  {
+    PythonThreadsAllower allower;
+    s = OrthancPluginGetPeerUrl(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  }
   
   if (s == NULL)
   {
@@ -101,7 +113,11 @@
     return NULL;
   }
 
-  const char* s = OrthancPluginGetPeerUserProperty(OrthancPlugins::GetGlobalContext(), self->object_, arg0, arg1);
+  const char* s;
+  {
+    PythonThreadsAllower allower;
+    s = OrthancPluginGetPeerUserProperty(OrthancPlugins::GetGlobalContext(), self->object_, arg0, arg1);
+  }
   
   if (s == NULL)
   {
--- a/Sources/Autogenerated/sdk_OrthancPluginRestOutput.methods.h	Tue Jul 02 14:52:20 2024 +0200
+++ b/Sources/Autogenerated/sdk_OrthancPluginRestOutput.methods.h	Tue Jul 02 15:49:05 2024 +0200
@@ -19,7 +19,10 @@
     return NULL;
   }
 
-  OrthancPluginAnswerBuffer(OrthancPlugins::GetGlobalContext(), self->object_, arg0.buf, arg0.len, arg2);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginAnswerBuffer(OrthancPlugins::GetGlobalContext(), self->object_, arg0.buf, arg0.len, arg2);
+  }
   PyBuffer_Release(&arg0);
 
   Py_INCREF(Py_None);
@@ -49,7 +52,10 @@
     return NULL;
   }
 
-  OrthancPluginCompressAndAnswerPngImage(OrthancPlugins::GetGlobalContext(), self->object_, static_cast<OrthancPluginPixelFormat>(arg0), arg1, arg2, arg3, arg4.buf);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginCompressAndAnswerPngImage(OrthancPlugins::GetGlobalContext(), self->object_, static_cast<OrthancPluginPixelFormat>(arg0), arg1, arg2, arg3, arg4.buf);
+  }
   PyBuffer_Release(&arg4);
 
   Py_INCREF(Py_None);
@@ -75,7 +81,10 @@
     return NULL;
   }
 
-  OrthancPluginRedirect(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginRedirect(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  }
   
 
   Py_INCREF(Py_None);
@@ -101,7 +110,10 @@
     return NULL;
   }
 
-  OrthancPluginSendHttpStatusCode(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginSendHttpStatusCode(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  }
   
 
   Py_INCREF(Py_None);
@@ -127,7 +139,10 @@
     return NULL;
   }
 
-  OrthancPluginSendUnauthorized(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginSendUnauthorized(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  }
   
 
   Py_INCREF(Py_None);
@@ -153,7 +168,10 @@
     return NULL;
   }
 
-  OrthancPluginSendMethodNotAllowed(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginSendMethodNotAllowed(OrthancPlugins::GetGlobalContext(), self->object_, arg0);
+  }
   
 
   Py_INCREF(Py_None);
@@ -180,7 +198,10 @@
     return NULL;
   }
 
-  OrthancPluginSetCookie(OrthancPlugins::GetGlobalContext(), self->object_, arg0, arg1);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginSetCookie(OrthancPlugins::GetGlobalContext(), self->object_, arg0, arg1);
+  }
   
 
   Py_INCREF(Py_None);
@@ -207,7 +228,10 @@
     return NULL;
   }
 
-  OrthancPluginSetHttpHeader(OrthancPlugins::GetGlobalContext(), self->object_, arg0, arg1);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginSetHttpHeader(OrthancPlugins::GetGlobalContext(), self->object_, arg0, arg1);
+  }
   
 
   Py_INCREF(Py_None);
@@ -234,7 +258,11 @@
     return NULL;
   }
 
-  OrthancPluginErrorCode code = OrthancPluginStartMultipartAnswer(OrthancPlugins::GetGlobalContext(), self->object_, arg0, arg1);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginStartMultipartAnswer(OrthancPlugins::GetGlobalContext(), self->object_, arg0, arg1);
+  }
   
 
   if (code == OrthancPluginErrorCode_Success)
@@ -268,7 +296,11 @@
     return NULL;
   }
 
-  OrthancPluginErrorCode code = OrthancPluginSendMultipartItem(OrthancPlugins::GetGlobalContext(), self->object_, arg0.buf, arg0.len);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginSendMultipartItem(OrthancPlugins::GetGlobalContext(), self->object_, arg0.buf, arg0.len);
+  }
   PyBuffer_Release(&arg0);
 
   if (code == OrthancPluginErrorCode_Success)
@@ -303,7 +335,10 @@
     return NULL;
   }
 
-  OrthancPluginSendHttpStatus(OrthancPlugins::GetGlobalContext(), self->object_, arg0, arg1.buf, arg1.len);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginSendHttpStatus(OrthancPlugins::GetGlobalContext(), self->object_, arg0, arg1.buf, arg1.len);
+  }
   PyBuffer_Release(&arg1);
 
   Py_INCREF(Py_None);
@@ -334,7 +369,10 @@
     return NULL;
   }
 
-  OrthancPluginCompressAndAnswerJpegImage(OrthancPlugins::GetGlobalContext(), self->object_, static_cast<OrthancPluginPixelFormat>(arg0), arg1, arg2, arg3, arg4.buf, arg5);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginCompressAndAnswerJpegImage(OrthancPlugins::GetGlobalContext(), self->object_, static_cast<OrthancPluginPixelFormat>(arg0), arg1, arg2, arg3, arg4.buf, arg5);
+  }
   PyBuffer_Release(&arg4);
 
   Py_INCREF(Py_None);
@@ -361,7 +399,10 @@
     return NULL;
   }
 
-  OrthancPluginSetHttpErrorDetails(OrthancPlugins::GetGlobalContext(), self->object_, arg0, arg1);
+  {
+    PythonThreadsAllower allower;
+    OrthancPluginSetHttpErrorDetails(OrthancPlugins::GetGlobalContext(), self->object_, arg0, arg1);
+  }
   
 
   Py_INCREF(Py_None);
--- a/Sources/Autogenerated/sdk_OrthancPluginStorageArea.methods.h	Tue Jul 02 14:52:20 2024 +0200
+++ b/Sources/Autogenerated/sdk_OrthancPluginStorageArea.methods.h	Tue Jul 02 15:49:05 2024 +0200
@@ -21,7 +21,11 @@
     return NULL;
   }
 
-  OrthancPluginErrorCode code = OrthancPluginStorageAreaCreate(OrthancPlugins::GetGlobalContext(), self->object_, arg0, arg1.buf, arg2, static_cast<OrthancPluginContentType>(arg3));
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginStorageAreaCreate(OrthancPlugins::GetGlobalContext(), self->object_, arg0, arg1.buf, arg2, static_cast<OrthancPluginContentType>(arg3));
+  }
   PyBuffer_Release(&arg1);
 
   if (code == OrthancPluginErrorCode_Success)
@@ -57,7 +61,11 @@
   }
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginStorageAreaRead(OrthancPlugins::GetGlobalContext(), *buffer, self->object_, arg0, static_cast<OrthancPluginContentType>(arg1));
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginStorageAreaRead(OrthancPlugins::GetGlobalContext(), *buffer, self->object_, arg0, static_cast<OrthancPluginContentType>(arg1));
+  }
   
   if (code == OrthancPluginErrorCode_Success)
   {
@@ -90,7 +98,11 @@
     return NULL;
   }
 
-  OrthancPluginErrorCode code = OrthancPluginStorageAreaRemove(OrthancPlugins::GetGlobalContext(), self->object_, arg0, static_cast<OrthancPluginContentType>(arg1));
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginStorageAreaRemove(OrthancPlugins::GetGlobalContext(), self->object_, arg0, static_cast<OrthancPluginContentType>(arg1));
+  }
   
 
   if (code == OrthancPluginErrorCode_Success)
@@ -124,7 +136,11 @@
     return NULL;
   }
 
-  OrthancPluginErrorCode code = OrthancPluginReconstructMainDicomTags(OrthancPlugins::GetGlobalContext(), self->object_, static_cast<OrthancPluginResourceType>(arg0));
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginReconstructMainDicomTags(OrthancPlugins::GetGlobalContext(), self->object_, static_cast<OrthancPluginResourceType>(arg0));
+  }
   
 
   if (code == OrthancPluginErrorCode_Success)
--- a/Sources/Autogenerated/sdk_OrthancPluginWorklistAnswers.methods.h	Tue Jul 02 14:52:20 2024 +0200
+++ b/Sources/Autogenerated/sdk_OrthancPluginWorklistAnswers.methods.h	Tue Jul 02 15:49:05 2024 +0200
@@ -25,7 +25,11 @@
     return NULL;
   }
 
-  OrthancPluginErrorCode code = OrthancPluginWorklistAddAnswer(OrthancPlugins::GetGlobalContext(), self->object_, arg0 == Py_None ? NULL : reinterpret_cast<sdk_OrthancPluginWorklistQuery_Object*>(arg0)->object_, arg1.buf, arg1.len);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginWorklistAddAnswer(OrthancPlugins::GetGlobalContext(), self->object_, arg0 == Py_None ? NULL : reinterpret_cast<sdk_OrthancPluginWorklistQuery_Object*>(arg0)->object_, arg1.buf, arg1.len);
+  }
   PyBuffer_Release(&arg1);
 
   if (code == OrthancPluginErrorCode_Success)
@@ -53,7 +57,11 @@
 
 
 
-  OrthancPluginErrorCode code = OrthancPluginWorklistMarkIncomplete(OrthancPlugins::GetGlobalContext(), self->object_);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginWorklistMarkIncomplete(OrthancPlugins::GetGlobalContext(), self->object_);
+  }
   
 
   if (code == OrthancPluginErrorCode_Success)
--- a/Sources/Autogenerated/sdk_OrthancPluginWorklistQuery.methods.h	Tue Jul 02 14:52:20 2024 +0200
+++ b/Sources/Autogenerated/sdk_OrthancPluginWorklistQuery.methods.h	Tue Jul 02 15:49:05 2024 +0200
@@ -18,7 +18,11 @@
     return NULL;
   }
 
-  long value = OrthancPluginWorklistIsMatch(OrthancPlugins::GetGlobalContext(), self->object_, arg0.buf, arg0.len);
+  long value;
+  {
+    PythonThreadsAllower allower;
+    value = OrthancPluginWorklistIsMatch(OrthancPlugins::GetGlobalContext(), self->object_, arg0.buf, arg0.len);
+  }
   PyBuffer_Release(&arg0);
   return PyLong_FromLong(value);
 }
@@ -37,7 +41,11 @@
 
 
   OrthancPlugins::MemoryBuffer buffer;
-  OrthancPluginErrorCode code = OrthancPluginWorklistGetDicomQuery(OrthancPlugins::GetGlobalContext(), *buffer, self->object_);
+  OrthancPluginErrorCode code;
+  {
+    PythonThreadsAllower allower;
+    code = OrthancPluginWorklistGetDicomQuery(OrthancPlugins::GetGlobalContext(), *buffer, self->object_);
+  }
   
   if (code == OrthancPluginErrorCode_Success)
   {
--- a/Sources/PythonHeaderWrapper.h	Tue Jul 02 14:52:20 2024 +0200
+++ b/Sources/PythonHeaderWrapper.h	Tue Jul 02 15:49:05 2024 +0200
@@ -18,6 +18,9 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  **/
 
+
+#define PY_SSIZE_T_CLEAN  /* Make "s#" use Py_ssize_t rather than int. */
+
 #if defined(_MSC_VER) && (ORTHANC_PYTHON_WINDOWS_USE_RELEASE_LIBS == 1) && defined(_DEBUG)
 #  undef _DEBUG
 #    include <Python.h>
@@ -25,4 +28,3 @@
 #else
 #  include <Python.h>
 #endif
-
--- a/Sources/PythonLock.h	Tue Jul 02 14:52:20 2024 +0200
+++ b/Sources/PythonLock.h	Tue Jul 02 15:49:05 2024 +0200
@@ -23,7 +23,6 @@
 
 #include <orthanc/OrthancCPlugin.h>
 
-#define PY_SSIZE_T_CLEAN  /* Make "s#" use Py_ssize_t rather than int. */
 #include "PythonHeaderWrapper.h"
 
 #include <boost/noncopyable.hpp>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sources/PythonThreadsAllower.cpp	Tue Jul 02 15:49:05 2024 +0200
@@ -0,0 +1,55 @@
+/**
+ * Python plugin for Orthanc
+ * Copyright (C) 2020-2023 Osimis S.A., Belgium
+ * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium
+ * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "PythonThreadsAllower.h"
+
+
+static bool allowThreads_ = false;
+
+
+PythonThreadsAllower::PythonThreadsAllower()
+{
+  if (allowThreads_)
+  {
+    state_ = PyEval_SaveThread();
+  }
+  else
+  {
+    state_ = NULL;
+  }
+}
+
+
+PythonThreadsAllower::~PythonThreadsAllower()
+{
+  if (state_ != NULL)
+  {
+    PyEval_RestoreThread(state_);
+    state_ = NULL;
+  }
+}
+
+
+void PythonThreadsAllower::SetAllowThreads(bool allow)
+{
+  allowThreads_ = allow;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sources/PythonThreadsAllower.h	Tue Jul 02 15:49:05 2024 +0200
@@ -0,0 +1,45 @@
+/**
+ * Python plugin for Orthanc
+ * Copyright (C) 2020-2023 Osimis S.A., Belgium
+ * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium
+ * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "PythonHeaderWrapper.h"
+
+#include <boost/noncopyable.hpp>
+
+
+/**
+ * This class implements the RAII pattern for Py_BEGIN_ALLOW_THREADS /
+ * Py_END_ALLOW_THREADS:
+ * https://docs.python.org/3/c-api/init.html#releasing-the-gil-from-extension-code
+ **/
+class PythonThreadsAllower : public boost::noncopyable
+{
+private:
+  PyThreadState* state_;
+
+public:
+  PythonThreadsAllower();
+
+  ~PythonThreadsAllower();
+
+  static void SetAllowThreads(bool allow);
+};