diff options
| -rwxr-xr-x | build.sh | 4 | ||||
| -rw-r--r-- | python/nissy_module.c | 69 |
2 files changed, 45 insertions, 28 deletions
| @@ -159,8 +159,8 @@ WASMLINKFLAGS="--no-entry -sEXPORT_NAME='Nissy' -sMODULARIZE | |||
| 159 | -sALLOW_MEMORY_GROWTH -sSTACK_SIZE=5MB -sPTHREAD_POOL_SIZE=$THREADS | 159 | -sALLOW_MEMORY_GROWTH -sSTACK_SIZE=5MB -sPTHREAD_POOL_SIZE=$THREADS |
| 160 | -sFETCH -sASYNCIFY -sLINKABLE -sEXPORT_ALL" | 160 | -sFETCH -sASYNCIFY -sLINKABLE -sEXPORT_ALL" |
| 161 | 161 | ||
| 162 | if (command -v "python3-config" >/dev/null 2>&1) ; then | 162 | if (command -v "python3.13t-config" >/dev/null 2>&1) ; then |
| 163 | PYTHON3_INCLUDES="$(python3-config --includes)" | 163 | PYTHON3_INCLUDES="$(python3.13t-config --includes)" |
| 164 | PYTHON3="version $(echo "$PYTHON3_INCLUDES" | sed 's/.*3\./3./')" | 164 | PYTHON3="version $(echo "$PYTHON3_INCLUDES" | sed 's/.*3\./3./')" |
| 165 | else | 165 | else |
| 166 | PYTHON3_INCLUDES="" | 166 | PYTHON3_INCLUDES="" |
diff --git a/python/nissy_module.c b/python/nissy_module.c index 23ff589..43f5b02 100644 --- a/python/nissy_module.c +++ b/python/nissy_module.c | |||
| @@ -12,10 +12,7 @@ work until PEP 703 (freethreading python) is implemented. | |||
| 12 | 12 | ||
| 13 | #define MAX_SOLUTIONS_SIZE 250000 | 13 | #define MAX_SOLUTIONS_SIZE 250000 |
| 14 | 14 | ||
| 15 | typedef struct { | 15 | PyObject *poll_status_callback = NULL; |
| 16 | PyObject *callback; | ||
| 17 | PyThreadState *thread_state; | ||
| 18 | } thread_callback_t; | ||
| 19 | 16 | ||
| 20 | static bool | 17 | static bool |
| 21 | check_error(long long err) | 18 | check_error(long long err) |
| @@ -96,29 +93,36 @@ long_result(long long result) | |||
| 96 | } | 93 | } |
| 97 | 94 | ||
| 98 | static int | 95 | static int |
| 99 | callback_wrapper(void *data) | 96 | callback_wrapper(void *arg) |
| 100 | { | 97 | { |
| 101 | thread_callback_t *arg = data; | ||
| 102 | int r; | 98 | int r; |
| 103 | PyObject *result; | 99 | PyObject *result; |
| 104 | PyGILState_STATE gstate; | 100 | PyThreadState **thread; |
| 105 | 101 | ||
| 106 | if (arg->callback != NULL && PyCallable_Check(arg->callback) == 1) { | 102 | thread = (PyThreadState **)arg; |
| 107 | 103 | ||
| 108 | PyEval_RestoreThread(arg->thread_state); | 104 | printf("About to restore thread\n"); |
| 109 | gstate = PyGILState_Ensure(); | 105 | PyEval_RestoreThread(*thread); |
| 110 | result = PyObject_CallNoArgs(data); | 106 | printf("Restoring\n"); |
| 111 | PyGILState_Release(gstate); | ||
| 112 | arg->thread_state = PyEval_SaveThread(); | ||
| 113 | 107 | ||
| 114 | if (result == NULL) | 108 | if (poll_status_callback != NULL && poll_status_callback != Py_None && |
| 115 | return 0; | 109 | PyCallable_Check(poll_status_callback) == 1) { |
| 116 | Py_XDECREF(result); | 110 | result = PyObject_CallNoArgs(poll_status_callback); |
| 111 | if (result == NULL) { | ||
| 112 | r = 0; | ||
| 113 | goto callback_wrapper_end; | ||
| 114 | } | ||
| 117 | r = PyLong_AsInt(result); | 115 | r = PyLong_AsInt(result); |
| 118 | return r >= 0 && r <= 2 ? r : 0; | 116 | r = r >= 0 && r <= 2 ? r : 0; |
| 119 | } else { | 117 | } else { |
| 120 | return NISSY_STATUS_RUN; | 118 | r = NISSY_STATUS_RUN; |
| 121 | } | 119 | } |
| 120 | |||
| 121 | callback_wrapper_end: | ||
| 122 | printf("Saving\n"); | ||
| 123 | *thread = PyEval_SaveThread(); | ||
| 124 | printf("Saved\n"); | ||
| 125 | return r; | ||
| 122 | } | 126 | } |
| 123 | 127 | ||
| 124 | PyDoc_STRVAR(inverse_doc, | 128 | PyDoc_STRVAR(inverse_doc, |
| @@ -356,28 +360,38 @@ solve(PyObject *self, PyObject *args) | |||
| 356 | long long stats[NISSY_SIZE_SOLVE_STATS]; | 360 | long long stats[NISSY_SIZE_SOLVE_STATS]; |
| 357 | PyByteArrayObject *data; | 361 | PyByteArrayObject *data; |
| 358 | PyObject *callback; | 362 | PyObject *callback; |
| 359 | thread_callback_t callback_data; | ||
| 360 | 363 | ||
| 361 | if (!PyArg_ParseTuple(args, "ssIIIIIIYO", &cube, &solver, &nissflag, | 364 | if (!PyArg_ParseTuple(args, "ssIIIIIIYO", &cube, &solver, &nissflag, |
| 362 | &minmoves, &maxmoves, &maxsolutions, &optimal, &threads, &data, | 365 | &minmoves, &maxmoves, &maxsolutions, &optimal, &threads, &data, |
| 363 | &callback)) | 366 | &callback)) |
| 364 | return NULL; | 367 | return NULL; |
| 365 | 368 | ||
| 369 | if (Py_TYPE(callback) == NULL) | ||
| 370 | printf("Type of callback is NULL!\n"); | ||
| 371 | PyObject_Print(callback, stdout, 0); | ||
| 366 | printf("Checking callback here:\n"); | 372 | printf("Checking callback here:\n"); |
| 367 | PyObject *rrr = PyObject_CallNoArgs(callback); | 373 | PyObject *rrr = PyObject_CallNoArgs(callback); |
| 368 | printf("result: %d\n", PyLong_AsInt(rrr)); | 374 | printf("result: %d\n", PyLong_AsInt(rrr)); |
| 369 | 375 | ||
| 370 | callback_data.callback = callback; | 376 | poll_status_callback = callback; |
| 371 | callback_data.thread_state = PyEval_SaveThread(); | 377 | |
| 372 | //Py_BEGIN_ALLOW_THREADS | 378 | Py_BEGIN_ALLOW_THREADS |
| 373 | 379 | ||
| 380 | #ifdef Py_GIL_DISABLED | ||
| 374 | result = nissy_solve(cube, solver, nissflag, minmoves, maxmoves, | 381 | result = nissy_solve(cube, solver, nissflag, minmoves, maxmoves, |
| 375 | maxsolutions, optimal, threads, data->ob_alloc, | 382 | maxsolutions, optimal, threads, data->ob_alloc, |
| 376 | (unsigned char *)data->ob_bytes, MAX_SOLUTIONS_SIZE, solutions, | 383 | (unsigned char *)data->ob_bytes, MAX_SOLUTIONS_SIZE, solutions, |
| 377 | stats, callback_wrapper, &callback_data); | 384 | stats, callback_wrapper, &_save); |
| 378 | 385 | #else | |
| 379 | PyEval_RestoreThread(callback_data.thread_state); | 386 | if (callback != NULL && callback != Py_None) |
| 380 | //Py_END_ALLOW_THREADS | 387 | printf("Warning: pause / stop / resume not available on " |
| 388 | "versions of Python with GIL enabled.\n"); | ||
| 389 | result = nissy_solve(cube, solver, nissflag, minmoves, maxmoves, | ||
| 390 | maxsolutions, optimal, threads, data->ob_alloc, | ||
| 391 | (unsigned char *)data->ob_bytes, MAX_SOLUTIONS_SIZE, solutions, | ||
| 392 | stats, NULL, NULL); | ||
| 393 | #endif | ||
| 394 | Py_END_ALLOW_THREADS | ||
| 381 | 395 | ||
| 382 | return stringlist_result(result, solutions); | 396 | return stringlist_result(result, solutions); |
| 383 | } | 397 | } |
| @@ -506,6 +520,9 @@ PyMODINIT_FUNC PyInit_nissy(void) { | |||
| 506 | 520 | ||
| 507 | nissy_setlogger(log_stdout, NULL); | 521 | nissy_setlogger(log_stdout, NULL); |
| 508 | module = PyModule_Create(&nissy); | 522 | module = PyModule_Create(&nissy); |
| 523 | #ifdef Py_GIL_DISABLED | ||
| 524 | PyUnstable_Module_SetGIL(module, Py_MOD_GIL_NOT_USED); | ||
| 525 | #endif | ||
| 509 | 526 | ||
| 510 | PyModule_AddStringConstant(module, "solved_cube", NISSY_SOLVED_CUBE); | 527 | PyModule_AddStringConstant(module, "solved_cube", NISSY_SOLVED_CUBE); |
| 511 | PyModule_AddIntConstant(module, "nissflag_normal", NISSY_NISSFLAG_NORMAL); | 528 | PyModule_AddIntConstant(module, "nissflag_normal", NISSY_NISSFLAG_NORMAL); |
