commit 0074dd1030cc7230ca66f006dac00e0d5ac92953
parent 0bb41786faccbbf806512a7bf5a0dfc6493d774a
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Fri, 6 Apr 2018 17:40:24 +0200
BugFix: some static vars were reused without reset.
No static vars anymore
Fix error management too
Diffstat:
1 file changed, 184 insertions(+), 189 deletions(-)
diff --git a/src/senc2d_scene_analyze.c b/src/senc2d_scene_analyze.c
@@ -193,18 +193,21 @@ self_hit_filter
return (hit_component == *origin_component);
}
-static res_T
+static void
extract_connex_components
(struct senc2d_descriptor* desc,
struct segside* segsides,
struct darray_ptr_component_descriptor* connex_components,
const struct darray_segment_tmp* segments_tmp_array,
struct darray_segment_comp* segments_comp,
- struct s2d_scene_view** s2d_view)
+ struct s2d_scene_view** s2d_view,
+ ATOMIC* component_count,
+ /* Shared error status.
+ * We accept to overwritte an error with a different error */
+ res_T* res)
{
/* This function is called from an omp parallel block and executed
* concurrently. */
- res_T res = RES_OK;
const struct senc2d_scene* scn;
struct mem_allocator* alloc;
int64_t mm;
@@ -213,11 +216,9 @@ extract_connex_components
seg_id_t s_;
component_id_t c;
#endif
- /* shared between threads */
- static ATOMIC component_count = 0;
- static volatile int exit_for = 0;
- ASSERT(segsides && desc && connex_components && segments_tmp_array);
+ ASSERT(segsides && desc && connex_components && segments_tmp_array
+ && s2d_view && component_count && res);
alloc = descriptor_get_allocator(desc);
scn = desc->scene;
@@ -248,7 +249,7 @@ extract_connex_components
/* Any not-already-used side is used as a starting point */
side_id_t first_side_not_in_component;
- if(exit_for) continue;
+ if(*res != RES_OK) continue;
first_side_not_in_component
= darray_side_range_cdata_get(&scn->media_use)[m].first;
if(first_side_not_in_component == SIDE_NULL__)
@@ -278,12 +279,12 @@ extract_connex_components
/* Create and init a new component */
cc = MEM_ALLOC(alloc, sizeof(struct cc_descriptor));
if(!cc) {
- res = RES_MEM_ERR;
- goto error1;
+ *res = RES_MEM_ERR;
+ continue;
}
cc_descriptor_init(alloc, cc);
ASSERT(m == segsides[start_side_id].medium);
- cc->cc_id = (component_id_t)(ATOMIC_INCR(&component_count) - 1);
+ cc->cc_id = (component_id_t)(ATOMIC_INCR(component_count) - 1);
cc->medium = m;
cc->side_range.first = start_side_id;
@@ -406,8 +407,8 @@ extract_connex_components
SPLIT2(positions[segments_in[nbour_seg_id].vertice_id[1]].vec));
log_err(desc->scene->dev, "Media: %lu VS %lu\n",
(unsigned long)neighbour->medium, (unsigned long)crt_side->medium);
- res = RES_BAD_ARG;
- goto error1;
+ *res = RES_BAD_ARG;
+ continue;
}
if(neighbour->list_id == FLAG_LIST_COMPONENT) {
/* Already processed */
@@ -437,9 +438,9 @@ extract_connex_components
if(sz <= cc->cc_id) {
res_T tmp_res = darray_ptr_component_descriptor_resize(connex_components,
1 + cc->cc_id);
- if(tmp_res != RES_OK) res = tmp_res;
+ if(tmp_res != RES_OK) *res = tmp_res;
}
- if(res == RES_OK) {
+ if(*res == RES_OK) {
/* Don't set the pointer before resize as this can lead to move data */
components =
darray_ptr_component_descriptor_data_get(connex_components);
@@ -447,19 +448,15 @@ extract_connex_components
components[cc->cc_id] = cc;
}
}
- OK2(res, error1);
}
- continue;
- error1:
- /* Cannot goto out of openmp block */
- exit_for = 1;
- continue;
- }
- /* No barrier here (nowait clause).
- * The first thread here creates the s2d view */
+ } /* No barrier here */
+
darray_side_id_release(&stack);
+
+ /* The first thread here creates the s2d view */
#pragma omp single nowait
- if(res == RES_OK) {
+ if(*res == RES_OK) {
+ res_T tmp_res = RES_OK;
struct s2d_device* s2d = NULL;
struct s2d_scene* s2d_scn = NULL;
struct s2d_shape* s2d_shp = NULL;
@@ -470,77 +467,76 @@ extract_connex_components
attribs.get = get_scn_position;
/* Put geometry in a 2D view */
- OK(s2d_device_create(desc->scene->dev->logger, alloc, 0, &s2d));
- OK(s2d_scene_create(s2d, &s2d_scn));
- OK(s2d_shape_create_line_segments(s2d, &s2d_shp));
+ OK2(s2d_device_create(desc->scene->dev->logger, alloc, 0, &s2d));
+ OK2(s2d_scene_create(s2d, &s2d_scn));
+ OK2(s2d_shape_create_line_segments(s2d, &s2d_shp));
/* Back to API type for ntris and nverts */
ASSERT(desc->scene->nusegs < UINT_MAX);
ASSERT(desc->scene->nuverts < UINT_MAX);
- OK(s2d_line_segments_setup_indexed_vertices(s2d_shp,
+ OK2(s2d_line_segments_setup_indexed_vertices(s2d_shp,
(unsigned)desc->scene->nusegs, get_scn_indices,
(unsigned)desc->scene->nuverts, &attribs, 1, desc->scene));
s2d_line_segments_set_hit_filter_function(s2d_shp, self_hit_filter,
segments_comp);
- OK(s2d_scene_attach_shape(s2d_scn, s2d_shp));
- OK(s2d_scene_view_create(s2d_scn, S2D_TRACE, s2d_view));
- error:
+ OK2(s2d_scene_attach_shape(s2d_scn, s2d_shp));
+ OK2(s2d_scene_view_create(s2d_scn, S2D_TRACE, s2d_view));
+ tmp_error:
+ if(tmp_res != RES_OK) *res = tmp_res;
if(s2d) S2D(device_ref_put(s2d));
if(s2d_scn) S2D(scene_ref_put(s2d_scn));
if(s2d_shp) S2D(shape_ref_put(s2d_shp));
}
- OK2(res, error_);
+ if(*res != RES_OK) return;
#ifndef NDEBUG
/* Need to wait for all threads done to be able to check stuff */
#pragma omp barrier
- ASSERT(component_count ==
- (int)darray_ptr_component_descriptor_size_get(connex_components));
- FOR_EACH(s_, 0, scn->nusegs) {
- struct segment_comp* seg_comp =
- darray_segment_comp_data_get(segments_comp) + s_;
- ASSERT(seg_comp->component[SIDE_FRONT] != COMPONENT_NULL__);
- ASSERT(seg_comp->component[SIDE_BACK] != COMPONENT_NULL__);
- }
- FOR_EACH(c, 0, component_count) {
- struct cc_descriptor** components =
- darray_ptr_component_descriptor_data_get(connex_components);
- ASSERT(components[c] != NULL &&
- components[c]->cc_id == c);
- }
- ASSERT(desc->segment_count
- == darray_segment_comp_size_get(segments_comp));
+ #pragma omp single
+ {
+ ASSERT(*component_count ==
+ (int)darray_ptr_component_descriptor_size_get(connex_components));
+ FOR_EACH(s_, 0, scn->nusegs) {
+ struct segment_comp* seg_comp =
+ darray_segment_comp_data_get(segments_comp) + s_;
+ ASSERT(seg_comp->component[SIDE_FRONT] != COMPONENT_NULL__);
+ ASSERT(seg_comp->component[SIDE_BACK] != COMPONENT_NULL__);
+ }
+ FOR_EACH(c, 0, *component_count) {
+ struct cc_descriptor** components =
+ darray_ptr_component_descriptor_data_get(connex_components);
+ ASSERT(components[c] != NULL &&
+ components[c]->cc_id == c);
+ }
+ ASSERT(desc->segment_count
+ == darray_segment_comp_size_get(segments_comp));
+ } /* Implicit barrier here */
#endif
-
-exit:
- return res;
-error_:
- exit_for = 1;
- goto exit;
}
-static res_T
+static void
group_connex_components
(struct senc2d_descriptor* desc,
struct segside* segsides,
struct darray_segment_comp* segments_comp,
struct darray_ptr_component_descriptor* connex_components,
- struct s2d_scene_view* s2d_view)
+ struct s2d_scene_view* s2d_view,
+ ATOMIC* next_enclosure_id,
+ struct cc_descriptor** infinity_first_cc,
+ /* Shared error status.
+ * We accept to overwritte an error with a different error */
+ res_T* res)
{
/* This function is called from an omp parallel block and executed
* concurrently. */
- res_T res = RES_OK;
struct cc_descriptor** descriptors;
size_t tmp;
component_id_t cc_count;
int64_t ccc;
- /* shared between threads */
- static struct cc_descriptor* infinity_first_cc = NULL;
- static volatile int exit_for = 0;
- static ATOMIC next_enclosure_id = 1;
(void)segsides;
- ASSERT(desc && segsides && segments_comp && connex_components);
+ ASSERT(desc && segsides && segments_comp && connex_components
+ && next_enclosure_id && infinity_first_cc && res);
ASSERT(desc->enclosures_count == 1);
descriptors = darray_ptr_component_descriptor_data_get(connex_components);
@@ -551,6 +547,7 @@ group_connex_components
/* Cast rays to find links between connex components */
#pragma omp for
for(ccc = 0; ccc < (int64_t)cc_count; ccc++) {
+ res_T tmp_res = RES_OK;
component_id_t c = (component_id_t)ccc;
struct s2d_hit hit = S2D_HIT_NULL;
float origin[2];
@@ -562,7 +559,7 @@ group_connex_components
component_id_t self_hit_component
= origin_seg->component[1 - SEGSIDE_2_SIDE(cc->max_y_side_id)];
- if(exit_for) continue;
+ if(*res != RES_OK) continue;
ASSERT(cc->cc_id == c);
ASSERT(cc->cc_group_root == CC_GROUP_ID_NONE);
@@ -570,7 +567,7 @@ group_connex_components
int64_t id;
/* Don't need to cast a ray */
cc->cc_group_root = cc->cc_id; /* New group with self as root */
- id = ATOMIC_INCR(&next_enclosure_id) - 1;
+ id = ATOMIC_INCR(next_enclosure_id) - 1;
ASSERT(id < ENCLOSURE_MAX__);
cc->enclosure_id = (enclosure_id_t)id;
continue;
@@ -586,17 +583,21 @@ group_connex_components
== SEGSIDE_OPPOSITE(cc->max_y_side_id))));
f2_set_d2(origin, cc->max_vrtx);
/* Self-hit data: self hit if hit this component "on the other side" */
- OK2(s2d_scene_view_trace_ray(s2d_view, origin, dir, range,
- &self_hit_component, &hit), error_);
+ tmp_res = s2d_scene_view_trace_ray(s2d_view, origin, dir, range,
+ &self_hit_component, &hit);
+ if(tmp_res != RES_OK) {
+ *res = tmp_res;
+ continue;
+ }
/* If no hit, the component is facing an infinite medium */
if(S2D_HIT_NONE(&hit)) {
cc->cc_group_root = CC_GROUP_ROOT_INFINITE;
cc->enclosure_id = 0;
/* Keep track of the first component facing infinity */
- ATOMIC_CAS_PTR(&infinity_first_cc, cc, NULL);
- if(infinity_first_cc->medium != cc->medium) {
- const side_id_t infinity_first_side = infinity_first_cc->max_y_side_id;
- const medium_id_t infinity_medium = infinity_first_cc->medium;
+ ATOMIC_CAS_PTR(infinity_first_cc, cc, NULL);
+ if((*infinity_first_cc)->medium != cc->medium) {
+ const side_id_t infinity_first_side = (*infinity_first_cc)->max_y_side_id;
+ const medium_id_t infinity_medium = (*infinity_first_cc)->medium;
/* Medium mismatch! Model topology is broken. */
const seg_id_t t1 = SEGSIDE_2_SEG(infinity_first_side);
const seg_id_t t2 = SEGSIDE_2_SEG(cc->max_y_side_id);
@@ -623,11 +624,9 @@ group_connex_components
SPLIT2(positions[segments_in[t2].vertice_id[1]].vec));
log_err(desc->scene->dev, "Media: %lu VS %lu\n",
(unsigned long)infinity_medium, (unsigned long)cc->medium);
- res = RES_BAD_ARG;
- goto error_;
+ *res = RES_BAD_ARG;
}
/* Same medium as previous members of the group: OK */
- continue;
} else {
/* If hit, group this component */
const seg_id_t hit_seg_id = (seg_id_t)hit.prim.prim_id;
@@ -681,78 +680,70 @@ group_connex_components
(unsigned long)hit_seg_in->medium[hit_side],
(unsigned long)cc->medium);
- res = RES_BAD_ARG;
- goto error_;
+ *res = RES_BAD_ARG;
}
}
- continue;
- error_:
- /* Cannot goto out of openmp block */
- exit_for = 1;
- continue;
}
/* Implicit barrier here */
- ASSERT(next_enclosure_id < ENCLOSURE_MAX__);
- OK(res);
+ ASSERT(*next_enclosure_id < ENCLOSURE_MAX__);
+ if(*res != RES_OK) return;
/* One thread post-processes links to group connex components */
#pragma omp single
{
- desc->enclosures_count = (enclosure_id_t)next_enclosure_id;
- res = darray_enclosure_resize(&desc->enclosures, desc->enclosures_count);
- if(res == RES_OK) {
- FOR_EACH(ccc, 0, cc_count) {
- component_id_t c = (component_id_t)ccc;
- struct cc_descriptor* const cc = descriptors[c];
- const struct cc_descriptor* other_desc = cc;
- struct enclosure_data* enclosures
- = darray_enclosure_data_get(&desc->enclosures);
- component_id_t fst;
-
- while(other_desc->enclosure_id == CC_GROUP_ID_NONE) {
- other_desc = *(darray_ptr_component_descriptor_cdata_get(connex_components)
- + other_desc->cc_group_root);
- }
- ASSERT(other_desc->cc_group_root != CC_GROUP_ROOT_NONE);
- ASSERT(other_desc->enclosure_id != CC_GROUP_ID_NONE);
- ASSERT(cc->medium == other_desc->medium);
- cc->cc_group_root = other_desc->cc_group_root;
- cc->enclosure_id = other_desc->enclosure_id;
- ++enclosures[cc->enclosure_id].cc_count;
- /* Linked list of componnents */
- fst = enclosures[cc->enclosure_id].first_component;
- cc->enclosure_next_component = fst;
- enclosures[cc->enclosure_id].first_component = cc->cc_id;
- enclosures[cc->enclosure_id].side_range.first
- = MMIN(enclosures[cc->enclosure_id].side_range.first, cc->side_range.first);
- enclosures[cc->enclosure_id].side_range.last
- = MMAX(enclosures[cc->enclosure_id].side_range.last, cc->side_range.last);
- enclosures[cc->enclosure_id].side_count += cc->side_count;
+ res_T tmp_res = RES_OK;
+ desc->enclosures_count = (enclosure_id_t)*next_enclosure_id;
+ tmp_res = darray_enclosure_resize(&desc->enclosures, desc->enclosures_count);
+ if(tmp_res != RES_OK) {
+ *res = tmp_res;
+ return;
+ }
+ FOR_EACH(ccc, 0, cc_count) {
+ component_id_t c = (component_id_t)ccc;
+ struct cc_descriptor* const cc = descriptors[c];
+ const struct cc_descriptor* other_desc = cc;
+ struct enclosure_data* enclosures
+ = darray_enclosure_data_get(&desc->enclosures);
+ component_id_t fst;
+
+ while(other_desc->enclosure_id == CC_GROUP_ID_NONE) {
+ other_desc = *(darray_ptr_component_descriptor_cdata_get(connex_components)
+ + other_desc->cc_group_root);
}
+ ASSERT(other_desc->cc_group_root != CC_GROUP_ROOT_NONE);
+ ASSERT(other_desc->enclosure_id != CC_GROUP_ID_NONE);
+ ASSERT(cc->medium == other_desc->medium);
+ cc->cc_group_root = other_desc->cc_group_root;
+ cc->enclosure_id = other_desc->enclosure_id;
+ ++enclosures[cc->enclosure_id].cc_count;
+ /* Linked list of componnents */
+ fst = enclosures[cc->enclosure_id].first_component;
+ cc->enclosure_next_component = fst;
+ enclosures[cc->enclosure_id].first_component = cc->cc_id;
+ enclosures[cc->enclosure_id].side_range.first
+ = MMIN(enclosures[cc->enclosure_id].side_range.first, cc->side_range.first);
+ enclosures[cc->enclosure_id].side_range.last
+ = MMAX(enclosures[cc->enclosure_id].side_range.last, cc->side_range.last);
+ enclosures[cc->enclosure_id].side_count += cc->side_count;
}
}
/* Implicit barrier here */
- OK(res);
-
-exit:
- return res;
-error:
- exit_for = 1;
- goto exit;
}
-static res_T
+static void
collect_and_link_neighbours
(struct senc2d_scene* scn,
struct segside* segsides,
struct darray_segment_tmp* segments_tmp_array,
- struct darray_neighbourhood* neighbourhood_by_vertex)
+ struct darray_neighbourhood* neighbourhood_by_vertex,
+ /* Shared error status.
+ * We accept to overwritte an error with a different error */
+ res_T* res)
{
/* This function is called from an omp parallel block and executed
* concurrently.
* Resize / Push operations on neighbourhood_by_vertex are valid
* because each neighbourhood is processes by an unique thread */
- res_T res = RES_OK;
const struct segment_in *segments_in;
struct segment_tmp *segments_tmp;
const union double2* vertices;
@@ -760,10 +751,9 @@ collect_and_link_neighbours
const int rank = omp_get_thread_num();
vrtx_id_t v;
seg_id_t s;
- /* shared between threads */
- static volatile int exit_for = 0;
- ASSERT(scn && segsides && segments_tmp_array);
+ ASSERT(scn && segsides && segments_tmp_array
+ && neighbourhood_by_vertex && res);
ASSERT((size_t)scn->nuverts + (size_t)scn->nusegs + 2 <= EDGE_MAX__);
segments_in = darray_segment_in_cdata_get(&scn->segments_in);
@@ -781,8 +771,9 @@ collect_and_link_neighbours
struct neighbour_info* info;
const vrtx_id_t vertex = segments_in[s].vertice_id[vv];
size_t sz;
+ res_T tmp_res = RES_OK;
ASSERT(vertex < scn->nuverts);
- if(exit_for) continue;
+ if(*res != RES_OK) continue;
/* Process only "my" vertices! */
if((int64_t)vertex % thread_count != rank) continue;
/* Find neighbourhood */
@@ -794,9 +785,17 @@ collect_and_link_neighbours
if(darray_neighbour_capacity(neighbourhood) == sz) {
/* 2 seems to be a good guess for initial capacity */
size_t new_sz = sz ? sz + 1 : 2;
- OK(darray_neighbour_reserve(neighbourhood, new_sz));
+ tmp_res = darray_neighbour_reserve(neighbourhood, new_sz);
+ if(tmp_res != RES_OK) {
+ *res = tmp_res;
+ return;
+ }
+ }
+ tmp_res = darray_neighbour_resize(neighbourhood, 1 + sz);
+ if(tmp_res != RES_OK) {
+ *res = tmp_res;
+ return;
}
- OK(darray_neighbour_resize(neighbourhood, 1 + sz));
/* Add neighbour info to vertex's neighbour list */
info = darray_neighbour_data_get(neighbourhood) + sz;
info->seg_id = s;
@@ -807,6 +806,8 @@ collect_and_link_neighbours
* it can process them whithout waiting for other threads
* (no barrier needed here). */
+ if(*res != RES_OK) return;
+
/* For each of "my" vertices sort segments sides by rotation angle
* and connect neighbours.
* All threads considering all the vertices and processing some */
@@ -890,24 +891,20 @@ collect_and_link_neighbours
p_ccw_side->list_id = FLAG_LIST_SIDE_LIST;
}
}
-end:
/* Threads are allowed to return whitout sync. */
- return res;
-error:
- /* Cannot goto out of openmp block */
- exit_for = 1;
- goto end;
}
-static res_T
+static void
build_result
(struct senc2d_descriptor* desc,
const struct darray_ptr_component_descriptor* connex_components,
- const struct darray_segment_comp* segments_comp_array)
+ const struct darray_segment_comp* segments_comp_array,
+ /* Shared error status.
+ * We accept to overwritte an error with a different error */
+ res_T* res)
{
/* This function is called from an omp parallel block and executed
* concurrently. */
- res_T res = RES_OK;
struct mem_allocator* alloc;
struct cc_descriptor* const* cc_descriptors;
struct enclosure_data* enclosures;
@@ -917,22 +914,23 @@ build_result
struct htable_vrtx_id vtable;
int64_t sg;
int64_t ee;
- /* shared between threads */
- static volatile int exit_for = 0;
- ASSERT(desc && connex_components && segments_comp_array);
+ ASSERT(desc && connex_components && segments_comp_array && res);
alloc = descriptor_get_allocator(desc);
- ASSERT(darray_ptr_component_descriptor_size_get(connex_components) < COMPONENT_MAX__);
+ ASSERT(darray_ptr_component_descriptor_size_get(connex_components)
+ < COMPONENT_MAX__);
cc_descriptors = darray_ptr_component_descriptor_cdata_get(connex_components);
enclosures = darray_enclosure_data_get(&desc->enclosures);
segments_in = darray_segment_in_cdata_get(&desc->scene->segments_in);
segments_comp = darray_segment_comp_cdata_get(segments_comp_array);
#pragma omp single
{
- res = darray_segment_enc_resize(&desc->segments_enc, desc->scene->nusegs);
+ res_T tmp_res =
+ darray_segment_enc_resize(&desc->segments_enc, desc->scene->nusegs);
+ if(tmp_res != RES_OK) *res = tmp_res;
}/* Implicit barrier here. */
- OK2(res, error_);
+ if(*res != RES_OK) return;
segments_enc = darray_segment_enc_data_get(&desc->segments_enc);
/* Build global enclosure information */
@@ -965,11 +963,12 @@ build_result
seg_id_t fst_idx = 0;
seg_id_t sgd_idx = enc->side_count;
seg_id_t s;
+ res_T tmp_res = RES_OK;
ASSERT(enc->first_component
< darray_ptr_component_descriptor_size_get(connex_components));
ASSERT(current->cc_id == enc->first_component);
- if(exit_for) continue;
+ if(*res != RES_OK) continue;
ASSERT(e <= UINT_MAX);
enc->header.enclosure_id = (unsigned)e; /* Back to API type */
ASSERT(current->enclosure_id == enc->header.enclosure_id);
@@ -979,9 +978,11 @@ build_result
ASSERT(enc->header.enclosed_medium < desc->scene->nmeds);
/* Build side and vertex lists. */
- OK(darray_segment_in_resize(&enc->sides, enc->side_count));
+ tmp_res = darray_segment_in_resize(&enc->sides, enc->side_count);
+ if(*res != RES_OK) continue;
/* Size is just a int */
- OK(darray_vrtx_id_reserve(&enc->vertices, enc->side_count + 1));
+ tmp_res = darray_vrtx_id_reserve(&enc->vertices, enc->side_count + 1);
+ if(*res != RES_OK) continue;
/* New vertex numbering scheme local to the enclosure */
htable_vrtx_id_clear(&vtable);
ASSERT(desc->scene->nusegs
@@ -1011,9 +1012,8 @@ build_result
ASSERT(tmp == darray_vrtx_id_size_get(&enc->vertices));
ASSERT(tmp < VRTX_MAX__);
vertice_id[i] = (vrtx_id_t)tmp;
- OK(htable_vrtx_id_set(&vtable, seg_in->vertice_id + i,
- vertice_id + i));
- OK(darray_vrtx_id_push_back(&enc->vertices, seg_in->vertice_id + i));
+ OK2(htable_vrtx_id_set(&vtable, seg_in->vertice_id + i, vertice_id + i));
+ OK2(darray_vrtx_id_push_back(&enc->vertices, seg_in->vertice_id + i));
++enc->header.vertices_count;
}
}
@@ -1039,27 +1039,21 @@ build_result
if(fst_idx == sgd_idx) break;
}
continue;
- error:
- /* Cannot goto out of openmp block */
- exit_for = 1;
+ tmp_error:
+ ASSERT(tmp_res != RES_OK);
+ *res = tmp_res;
} /* No barrier here */
htable_vrtx_id_release(&vtable);
-
- OK2(res, error_);
-
-exit:
- return res;
-error_:
- goto exit;
}
/*******************************************************************************
* Exported functions
******************************************************************************/
res_T
-senc2d_scene_analyze(struct senc2d_scene* scn, struct senc2d_descriptor** out_desc)
+senc2d_scene_analyze
+ (struct senc2d_scene* scn,
+ struct senc2d_descriptor** out_desc)
{
- res_T res = RES_OK;
struct senc2d_descriptor* desc = NULL;
/* By segment tmp data */
struct darray_segment_tmp segments_tmp;
@@ -1077,6 +1071,12 @@ senc2d_scene_analyze(struct senc2d_scene* scn, struct senc2d_descriptor** out_de
/* Array to keep neighbourhood of vertices */
struct darray_neighbourhood neighbourhood_by_vertex;
char neighbourhood_by_vertex_initialized = 0;
+ /* Atomic counters to share beetwen threads */
+ ATOMIC component_count = 0;
+ ATOMIC next_enclosure_id = 1;
+ /* Used as args to have shared vars between threads in functions */
+ struct cc_descriptor* infinity_first_cc = NULL;
+ res_T res = RES_OK;
if(!scn || !out_desc) return RES_BAD_ARG;
@@ -1110,42 +1110,40 @@ senc2d_scene_analyze(struct senc2d_scene* scn, struct senc2d_descriptor** out_de
/* The end of the analyze is multithreaded */
#pragma omp parallel
{
- res_T thread_res = RES_OK;
-
/* Step 1: build neighbourhoods */
- thread_res = collect_and_link_neighbours(scn, segsides, &segments_tmp,
- &neighbourhood_by_vertex);
+ collect_and_link_neighbours(scn, segsides, &segments_tmp,
+ &neighbourhood_by_vertex, &res);
/* No barrier at the end of step 1: data used in step 1 cannot be
* released / data produced by step 1 cannot be used
* until next sync point */
- if(thread_res != RES_OK) {
- res = thread_res;
+ if(res != RES_OK) {
#pragma omp single nowait
{
log_err(scn->dev,
"%s: could not build neighbourhoods from scene.\n", FUNC_NAME);
} /* No barrier here */
}
- OK2(res, error_);
+ if(res != RES_OK) goto error_;
/* The first thread here allocates some data */
#pragma omp single
{
+ res_T tmp_res = RES_OK;
darray_ptr_component_descriptor_init(scn->dev->allocator,
&connex_components);
connex_components_initialized = 1;
/* Just a hint; to limit contention */
- thread_res = darray_ptr_component_descriptor_reserve(&connex_components,
- 2 * scn->nmeds);
- if(thread_res != RES_OK) res = thread_res;
+ OK2(darray_ptr_component_descriptor_reserve(&connex_components,
+ 2 * scn->nmeds));
darray_segment_comp_init(scn->dev->allocator, &segments_comp);
segments_comp_initialized = 1;
- thread_res = darray_segment_comp_resize(&segments_comp, scn->nusegs);
- if(thread_res != RES_OK) res = thread_res;
+ OK2(darray_segment_comp_resize(&segments_comp, scn->nusegs));
+ tmp_error:
+ if(tmp_res != RES_OK) res = tmp_res;
}
/* Implicit barrier here: constraints on step 1 data are now met */
- OK2(res, error_);
+ if(res != RES_OK) goto error_;
/* One thread releases some data before going to step 2,
* the others go to step 2 without sync */
@@ -1153,24 +1151,23 @@ senc2d_scene_analyze(struct senc2d_scene* scn, struct senc2d_descriptor** out_de
{
darray_neighbourhood_release(&neighbourhood_by_vertex);
neighbourhood_by_vertex_initialized = 0;
- } /* Barrier here */
+ } /* No barrier here */
/* Step 2: extract segment connex components */
- thread_res = extract_connex_components(desc, segsides, &connex_components,
- &segments_tmp, &segments_comp, &s2d_view);
+ extract_connex_components(desc, segsides, &connex_components,
+ &segments_tmp, &segments_comp, &s2d_view, &component_count, &res);
/* No barrier at the end of step 2: data used in step 2 cannot be
* released / data produced by step 2 cannot be used
* until next sync point */
- if(thread_res != RES_OK) {
- res = thread_res;
+ if(res != RES_OK) {
#pragma omp single nowait
{
log_err(scn->dev,
"%s: could not extract connex components from scene.\n", FUNC_NAME);
} /* No barrier here */
}
- OK2(res, error_);
+ if(res != RES_OK) goto error_;
#pragma omp barrier
/* Constraints on step 2 data are now met */
@@ -1184,8 +1181,8 @@ senc2d_scene_analyze(struct senc2d_scene* scn, struct senc2d_descriptor** out_de
} /* No barrier here */
/* Step 3: group components */
- thread_res = group_connex_components(desc, segsides, &segments_comp,
- &connex_components, s2d_view);
+ group_connex_components(desc, segsides, &segments_comp, &connex_components,
+ s2d_view, &next_enclosure_id, &infinity_first_cc, &res);
/* Barrier at the end of step 3: data used in step 3 can be released /
* data produced by step 2 can be used */
@@ -1198,29 +1195,27 @@ senc2d_scene_analyze(struct senc2d_scene* scn, struct senc2d_descriptor** out_de
} /* No barrier here */
if(res != RES_OK) {
- res = thread_res;
#pragma omp single nowait
{
log_err(scn->dev,
"%s: could not group connex components from scene.\n", FUNC_NAME);
} /* No barrier here */
}
- OK2(res, error_);
+ if(res != RES_OK) goto error_;
/* Step 4: Build result */
- thread_res = build_result(desc, &connex_components, &segments_comp);
+ build_result(desc, &connex_components, &segments_comp, &res);
/* No barrier at the end of step 4: data used in step 4 cannot be
* released / data produced by step 4 cannot be used
* until next sync point */
- if(thread_res != RES_OK) {
- res = thread_res;
+ if(res, res != RES_OK) {
#pragma omp single nowait
{
log_err(scn->dev, "%s: could not build result.\n", FUNC_NAME);
} /* No barrier here */
}
- OK2(res, error_);
+ if(res != RES_OK) goto error_;
#pragma omp barrier
/* Constraints on step 4 data are now met */