Skip to content

Commit

Permalink
Play better with GIL, keeping most of the complexity in mvCallbackJob.
Browse files Browse the repository at this point in the history
Drag and drop still crashes in the demo.
  • Loading branch information
bzczb committed Feb 13, 2024
1 parent 2397626 commit b3d6ad0
Show file tree
Hide file tree
Showing 24 changed files with 466 additions and 381 deletions.
47 changes: 18 additions & 29 deletions src/dearpygui_commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -1873,15 +1873,10 @@ set_frame_callback(PyObject* self, PyObject* args, PyObject* kwargs)
if (frame > GContext->callbackRegistry->highestFrame)
GContext->callbackRegistry->highestFrame = frame;

// TODO: check previous entry and deprecate if existing
Py_XINCREF(callback);

if(user_data)
Py_XINCREF(user_data);
mvSubmitCallback([=]()
{
GContext->callbackRegistry->frameCallbacks[frame] = callback;
GContext->callbackRegistry->frameCallbacksUserData[frame] = user_data;
GContext->callbackRegistry->frameCallbacks[frame] = std::make_shared<mvPyObjectStrict>(callback);
GContext->callbackRegistry->frameCallbacksUserData[frame] = std::make_shared<mvPyObjectStrict>(user_data);
});

return GetPyNone();
Expand Down Expand Up @@ -2365,13 +2360,16 @@ output_frame_buffer(PyObject* self, PyObject* args, PyObject* kwargs)

if (filepathLength == 0 && callback) // not specified, return array instead
{
//Py_XINCREF(callback);
auto callback_ptr = std::make_shared<mvPyObjectStrict>(callback);

PyObject* newbuffer = nullptr;
PymvBuffer* newbufferview = PyObject_New(PymvBuffer, &PymvBufferType);
newbuffer = PyObject_Init((PyObject*)newbufferview, &PymvBufferType);
mvSubmitTask([newbuffer, callback, newbufferview]() {
auto appdata_ptr = std::make_shared<mvPyObjectStrict>(newbuffer, false);

mvSubmitTask([appdata_ptr, callback_ptr, newbufferview]() {
OutputFrameBufferArray(newbufferview);
mvAddCallbackJob({callback, 0, newbuffer, nullptr});
mvAddCallbackJob({callback_ptr, 0, appdata_ptr, nullptr});
});

return GetPyNone();
Expand Down Expand Up @@ -3595,32 +3593,32 @@ get_item_configuration(PyObject* self, PyObject* args, PyObject* kwargs)

if (appitem->config.callback)
{
Py_XINCREF(appitem->config.callback);
PyDict_SetItemString(pdict, "callback", appitem->config.callback);
Py_XINCREF(*appitem->config.callback);
PyDict_SetItemString(pdict, "callback", *appitem->config.callback);
}
else
PyDict_SetItemString(pdict, "callback", GetPyNone());

if (appitem->config.dropCallback)
{
Py_XINCREF(appitem->config.dropCallback);
PyDict_SetItemString(pdict, "drop_callback", appitem->config.dropCallback);
Py_XINCREF(*appitem->config.dropCallback);
PyDict_SetItemString(pdict, "drop_callback", *appitem->config.dropCallback);
}
else
PyDict_SetItemString(pdict, "drop_callback", GetPyNone());

if (appitem->config.dragCallback)
{
Py_XINCREF(appitem->config.dragCallback);
PyDict_SetItemString(pdict, "drag_callback", appitem->config.dragCallback);
Py_XINCREF(*appitem->config.dragCallback);
PyDict_SetItemString(pdict, "drag_callback", *appitem->config.dragCallback);
}
else
PyDict_SetItemString(pdict, "drag_callback", GetPyNone());

if (appitem->config.user_data)
{
Py_XINCREF(appitem->config.user_data);
PyDict_SetItemString(pdict, "user_data", appitem->config.user_data);
Py_XINCREF(*appitem->config.user_data);
PyDict_SetItemString(pdict, "user_data", *appitem->config.user_data);
}
else
PyDict_SetItemString(pdict, "user_data", GetPyNone());
Expand Down Expand Up @@ -4051,21 +4049,12 @@ capture_next_item(PyObject* self, PyObject* args, PyObject* kwargs)

std::lock_guard<std::recursive_mutex> lk(GContext->mutex);

if (GContext->itemRegistry->captureCallback)
Py_XDECREF(GContext->itemRegistry->captureCallback);

if (GContext->itemRegistry->captureCallbackUserData)
Py_XDECREF(GContext->itemRegistry->captureCallbackUserData);

Py_XINCREF(callable);
if(user_data)
Py_XINCREF(user_data);
if (callable == Py_None)
GContext->itemRegistry->captureCallback = nullptr;
else
GContext->itemRegistry->captureCallback = callable;
GContext->itemRegistry->captureCallback = std::make_shared<mvPyObjectStrict>(callable);

GContext->itemRegistry->captureCallbackUserData = user_data;
GContext->itemRegistry->captureCallbackUserData = std::make_shared<mvPyObjectStrict>(user_data);

return GetPyNone();
}
Expand Down
58 changes: 15 additions & 43 deletions src/mvAppItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ mvAppItem::~mvAppItem()
static_cast<mvTable*>(this)->onChildrenRemoved();

mvGlobalIntepreterLock gil;
if (config.callback) Py_DECREF(config.callback);
if (config.user_data) Py_DECREF(config.user_data);
if (config.dragCallback) Py_DECREF(config.dragCallback);
if (config.dropCallback) Py_DECREF(config.dropCallback);
config.callback = nullptr;
config.user_data = nullptr;
config.dragCallback = nullptr;
config.dropCallback = nullptr;

// in case item registry is destroyed
if (GContext->itemRegistry)
Expand All @@ -54,13 +54,15 @@ mvAppItem::~mvAppItem()
}
}

PyObject*
std::shared_ptr<mvPyObjectStrict>
mvAppItem::getCallback(bool ignore_enabled)
{
if (config.enabled)
return config.callback;

return ignore_enabled ? config.callback : nullptr;
if (config.enabled || ignore_enabled) {
return std::shared_ptr<mvPyObjectStrict>(shared_from_this(), &config.callback);
}
else {
return nullptr;
}
}

void
Expand Down Expand Up @@ -163,52 +165,22 @@ mvAppItem::handleKeywordArgs(PyObject* dict, const std::string& parser)

if (PyObject* item = PyDict_GetItemString(dict, "callback"))
{
if (config.callback)
Py_XDECREF(config.callback);

// TODO: investigate if PyNone should be increffed
Py_XINCREF(item);
if (item == Py_None)
config.callback = nullptr;
else
config.callback = item;
config.callback = mvPyObjectStrict(item);
}

if (PyObject* item = PyDict_GetItemString(dict, "drag_callback"))
{
if (config.dragCallback)
Py_XDECREF(config.dragCallback);

Py_XINCREF(item);
if (item == Py_None)
config.dragCallback = nullptr;
else
config.dragCallback = item;
config.dragCallback = mvPyObjectStrict(item);
}

if (PyObject* item = PyDict_GetItemString(dict, "drop_callback"))
{
if (config.dropCallback)
Py_XDECREF(config.dropCallback);

Py_XINCREF(item);

if (item == Py_None)
config.dropCallback = nullptr;
else
config.dropCallback = item;
config.dropCallback = mvPyObjectStrict(item);
}

if (PyObject* item = PyDict_GetItemString(dict, "user_data"))
{
if (config.user_data)
Py_XDECREF(config.user_data);

Py_XINCREF(item);
if (item == Py_None)
config.user_data = nullptr;
else
config.user_data = item;
config.user_data = mvPyObjectStrict(item);
}

handleSpecificKeywordArgs(dict);
Expand Down
15 changes: 9 additions & 6 deletions src/mvAppItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <string>
#include <vector>
#include <map>
#include <memory>
#include <imgui.h>
#include "mvAppItemState.h"
#include "mvCallbackRegistry.h"
Expand Down Expand Up @@ -127,10 +128,11 @@ struct mvAppItemConfig
bool searchDelayed = false;
bool useInternalLabel = true; // when false, will use specificed label
bool tracked = false;
PyObject* callback = nullptr;
PyObject* user_data = nullptr;
PyObject* dragCallback = nullptr;
PyObject* dropCallback = nullptr;

mvPyObjectStrict callback;
mvPyObjectStrict user_data;
mvPyObjectStrict dragCallback;
mvPyObjectStrict dropCallback;
};

struct mvAppItemDrawInfo
Expand All @@ -146,7 +148,7 @@ struct mvAppItemDrawInfo
//-----------------------------------------------------------------------------
// mvAppItem
//-----------------------------------------------------------------------------
class mvAppItem
class mvAppItem : public std::enable_shared_from_this<mvAppItem>
{

public:
Expand Down Expand Up @@ -207,7 +209,8 @@ class mvAppItem
//-----------------------------------------------------------------------------
// callbacks
//-----------------------------------------------------------------------------
[[nodiscard]] PyObject* getCallback(b8 ignore_enabled = true); // returns the callback. If ignore_enable false and item is disabled then no callback will be returned.
// returns the callback. If ignore_enable false and item is disabled then no callback will be returned.
[[nodiscard]] std::shared_ptr<mvPyObjectStrict> getCallback(b8 ignore_enabled = true);

//-----------------------------------------------------------------------------
// config setters
Expand Down
Loading

0 comments on commit b3d6ad0

Please sign in to comment.