Skip to content

Commit b380969

Browse files
committed
range_str: use hash_set_shared in OpenMP region
Explicitly check the return value and update the shared pointer when necessary. If a reallocation attempt fails, signal an error when possible.
1 parent afd53b5 commit b380969

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

src/forder.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,8 @@ static void range_str(const SEXP *x, int n, uint64_t *out_min, uint64_t *out_max
298298
bool anynotascii=false, anynotutf8=false;
299299
if (ustr_n!=0) internal_error_with_cleanup(__func__, "ustr isn't empty when starting range_str: ustr_n=%d, ustr_alloc=%d", ustr_n, ustr_alloc); // # nocov
300300
if (ustr_maxlen!=0) internal_error_with_cleanup(__func__, "ustr_maxlen isn't 0 when starting range_str"); // # nocov
301-
#pragma omp parallel for num_threads(getDTthreads(n, true)) shared(marks)
301+
bool fail = false;
302+
#pragma omp parallel for num_threads(getDTthreads(n, true)) shared(marks, fail)
302303
for(int i=0; i<n; i++) {
303304
SEXP s = x[i];
304305
if (s==NA_STRING) {
@@ -317,9 +318,16 @@ static void range_str(const SEXP *x, int n, uint64_t *out_min, uint64_t *out_max
317318
if (ustr==NULL) STOP(_("Unable to realloc %d * %d bytes in range_str"), ustr_alloc, (int)sizeof(SEXP)); // # nocov
318319
}
319320
ustr[ustr_n++] = s;
320-
// Under the OpenMP memory model, if the hash table is expanded, we have to explicitly update the pointer.
321-
#pragma omp atomic write
322-
marks = hash_set_shared(marks, s, -ustr_n); // unique in any order is fine. first-appearance order is achieved later in count_group
321+
hashtab *new_marks = hash_set_shared(marks, s, -ustr_n); // unique in any order is fine. first-appearance order is achieved later in count_group
322+
if (new_marks != marks) {
323+
if (new_marks) {
324+
// Under the OpenMP memory model, if the hash table is expanded, we have to explicitly update the pointer.
325+
#pragma omp atomic write
326+
marks = new_marks;
327+
} else { // longjmp() from a non-main thread not allowed
328+
fail = true;
329+
}
330+
}
323331
if (LENGTH(s)>ustr_maxlen) ustr_maxlen=LENGTH(s);
324332
if (!anynotutf8 && // even if anynotascii we still want to know if anynotutf8, and anynotutf8 implies anynotascii already
325333
!IS_ASCII(s)) { // anynotutf8 implies anynotascii and IS_ASCII will be cheaper than IS_UTF8, so start with this one
@@ -330,6 +338,7 @@ static void range_str(const SEXP *x, int n, uint64_t *out_min, uint64_t *out_max
330338
}
331339
}
332340
}
341+
if (fail) internal_error_with_cleanup(__func__, "failed to grow the 'marks' hash table");
333342
*out_na_count = na_count;
334343
*out_anynotascii = anynotascii;
335344
*out_anynotutf8 = anynotutf8;

0 commit comments

Comments
 (0)