diff --git a/src/libImaging/Arrow.c b/src/libImaging/Arrow.c index f7bcfcf97..0ad049f6b 100644 --- a/src/libImaging/Arrow.c +++ b/src/libImaging/Arrow.c @@ -188,7 +188,9 @@ export_single_channel_array(Imaging im, struct ArrowArray *array) { length = im->xsize * im->lines_per_block; } - im->arrow_borrow++; + MUTEX_LOCK(im->mutex); + im->refcount++; + MUTEX_UNLOCK(im->mutex); // Initialize primitive fields *array = (struct ArrowArray){// Data description .length = length, @@ -227,7 +229,9 @@ export_fixed_pixel_array(Imaging im, struct ArrowArray *array) { length = im->xsize * im->lines_per_block; } - im->arrow_borrow++; + MUTEX_LOCK(im->mutex); + im->refcount++; + MUTEX_UNLOCK(im->mutex); // Initialize primitive fields // Fixed length arrays are 1 buffer of validity, and the length in pixels. // Data is in a child array. @@ -254,7 +258,9 @@ export_fixed_pixel_array(Imaging im, struct ArrowArray *array) { array->children = calloc(1, sizeof(struct ArrowArray *)); array->children[0] = (struct ArrowArray *)calloc(1, sizeof(struct ArrowArray)); - im->arrow_borrow++; + MUTEX_LOCK(im->mutex); + im->refcount++; + MUTEX_UNLOCK(im->mutex); *array->children[0] = (struct ArrowArray){// Data description .length = length * 4, .offset = 0, diff --git a/src/libImaging/Imaging.h b/src/libImaging/Imaging.h index 2d1d45393..9fddf5eab 100644 --- a/src/libImaging/Imaging.h +++ b/src/libImaging/Imaging.h @@ -108,7 +108,7 @@ struct ImagingMemoryInstance { void (*destroy)(Imaging im); /* arrow */ - int arrow_borrow; /* Number of arrow arrays that have been allocated */ + int refcount; /* Number of arrow arrays that have been allocated */ char band_names[4][3]; /* names of bands, max 2 char + null terminator */ char arrow_band_format[2]; /* single character + null terminator */ @@ -117,6 +117,12 @@ struct ImagingMemoryInstance { int blocks_count; /* Number of blocks that have been allocated */ int lines_per_block; /* Number of lines in a block have been allocated */ + +#ifdef Py_GIL_DISABLED + PyMutex mutex; +#endif + + }; #define IMAGING_PIXEL_1(im, x, y) ((im)->image8[(y)][(x)]) diff --git a/src/libImaging/Storage.c b/src/libImaging/Storage.c index 7ac5f63a5..9e6439b88 100644 --- a/src/libImaging/Storage.c +++ b/src/libImaging/Storage.c @@ -58,7 +58,7 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size) { /* Setup image descriptor */ im->xsize = xsize; im->ysize = ysize; - im->arrow_borrow = 1; + im->refcount = 1; im->type = IMAGING_TYPE_UINT8; strcpy(im->arrow_band_format, "C"); @@ -299,11 +299,14 @@ ImagingDelete(Imaging im) { return; } - im->arrow_borrow--; + MUTEX_LOCK(im->mutex); + im->refcount--; - if (im->arrow_borrow > 0) { - return; + if (im->refcount > 0) { + MUTEX_UNLOCK(im->mutex); + return; } + MUTEX_UNLOCK(im->mutex); if (im->palette) { ImagingPaletteDelete(im->palette); @@ -697,10 +700,12 @@ ImagingNewArrow( int64_t pixels = (int64_t)xsize * (int64_t)ysize; // fmt:off // don't reformat this - if (((strcmp(schema->format, "I") == 0 && im->pixelsize == 4 && im->bands >= 2 - ) // INT32 into any INT32 Storage mode - || (strcmp(schema->format, im->arrow_band_format) == 0 && im->bands == 1) - ) // Single band match + if (((strcmp(schema->format, "I") == 0 // int32 + && im->pixelsize == 4 // 4xchar* storage + && im->bands >= 2) // INT32 into any INT32 Storage mode + || + (strcmp(schema->format, im->arrow_band_format) == 0 // same mode + && im->bands == 1)) // Single band match && pixels == external_array->length) { // one arrow element per, and it matches a pixelsize*char if (ImagingBorrowArrow(im, external_array, im->pixelsize)) {