Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dearpygui/_dearpygui.pyi

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions dearpygui/_dearpygui_RTD.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions dearpygui/dearpygui.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 18 additions & 11 deletions src/dearpygui_commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -2271,19 +2271,26 @@ save_init_file(PyObject* self, PyObject* args, PyObject* kwargs)
static PyObject*
split_frame(PyObject* self, PyObject* args, PyObject* kwargs)
{
i32 delay = 32;

if (!Parse((GetParsers())["split_frame"], args, kwargs, __FUNCTION__,
&delay))
if (!Parse((GetParsers())["split_frame"], args, kwargs, __FUNCTION__))
return GetPyNone();

// std::lock_guard<std::recursive_mutex> lk(GContext->mutex);
if (GContext->running)
{
Py_BEGIN_ALLOW_THREADS;
std::unique_lock lk(GContext->frameEndedMutex);
GContext->frameEnded = false;
GContext->frameEndedEvent.wait(lk, []{return GContext->frameEnded;});
lk.unlock();

Py_BEGIN_ALLOW_THREADS;
GContext->waitOneFrame = true;
while (GContext->waitOneFrame)
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
Py_END_ALLOW_THREADS;
Py_END_ALLOW_THREADS;
}

// Now let's see if it was successful (there's a chance that DPG got stopped while we were waiting)
if (!GContext->running)
{
mvThrowPythonError(mvErrorCode::mvNone, "split_frame is exiting: there is no active rendering loop.");
return nullptr;
}

return GetPyNone();
}
Expand Down Expand Up @@ -2654,7 +2661,7 @@ destroy_context(PyObject* self, PyObject* args, PyObject* kwargs)
else
{
// Make sure everyone knows we're shutting down, even if stop_dearpygui
// was not called.
// was not called. This also releases any waiting split_frame calls.
StopRendering();

Py_BEGIN_ALLOW_THREADS;
Expand Down
2 changes: 1 addition & 1 deletion src/dearpygui_parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ InsertParser_Block1(std::map<std::string, mvPythonParser>& parsers)

{
std::vector<mvPythonDataElement> args;
args.push_back({ mvPyDataType::Integer, "delay", mvArgType::KEYWORD_ARG, "32", "Minimal delay in in milliseconds" });
args.push_back({ mvPyDataType::Integer, "delay", mvArgType::DEPRECATED_REMOVE_KEYWORD_ARG, "32", "Do not use it anymore, it has no effect." });

mvPythonParserSetup setup;
setup.about = "Waits one frame.";
Expand Down
37 changes: 26 additions & 11 deletions src/mvContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,20 +182,22 @@ Render()

mvToolManager::Draw();

if (GContext->resetTheme)
{
if (GContext->resetTheme)
{
SetDefaultTheme();
GContext->resetTheme = false;
}

mvRunTasks();
RenderItemRegistry(*GContext->itemRegistry);
mvRunTasks();
SetDefaultTheme();
GContext->resetTheme = false;
}

if (GContext->waitOneFrame == true)
GContext->waitOneFrame = false;
mvRunTasks();
RenderItemRegistry(*GContext->itemRegistry);
mvRunTasks();

// release split_frame if it's waiting for the frame end
{
std::lock_guard lk(GContext->frameEndedMutex);
GContext->frameEnded = true;
}
GContext->frameEndedEvent.notify_all();
}

std::map<std::string, mvPythonParser>&
Expand All @@ -206,7 +208,20 @@ GetParsers()

void StopRendering()
{
// While it may seem reasonable to set it to false with frameEndedMutex locked
// (to set it simultaneously with frameEnded), we don't want to spur another
// race condition between split_frame() and is_dearpygui_running() in the
// rendering loop. Let's trigger it as early as possible.
GContext->running = false;

// Unblock handlers (or other code) that might be waiting in `split_frame()`
{
std::lock_guard lk(GContext->frameEndedMutex);
// Simulate an end of frame even though there's no real frame this time.
// Otherwise split_frame will continue waiting.
GContext->frameEnded = true;
}
GContext->frameEndedEvent.notify_all();
}

void
Expand Down
4 changes: 3 additions & 1 deletion src/mvContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ struct mvIO

struct mvContext
{
std::atomic_bool waitOneFrame = false;
std::mutex frameEndedMutex;
std::condition_variable frameEndedEvent;
bool frameEnded = false;
// Indicates whether DPG has started at least once in this context, i.e. whether
// associated Dear ImGui contexts exist and can be read from.
std::atomic_bool started = false;
Expand Down
Loading