commit 67ded6763e5e2bc346b68c8d65956a6332a9078e
parent c4ae42af3f8fdf65a2d9c92b672540826018bf10
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Tue, 23 Aug 2022 11:58:52 +0200
Allow a partition to be fetched by several threads
Diffstat:
1 file changed, 24 insertions(+), 6 deletions(-)
diff --git a/src/rnatm_voxel_partition.c b/src/rnatm_voxel_partition.c
@@ -42,6 +42,12 @@ struct partition {
size_t id; /* Unique identifier of the partition */
struct tile* tile; /* Set of voxels */
struct pool* pool;
+
+ /* Number of references on the partition. When the partition is commited, its
+ * reference count is set to the width of the voxel. Once fetched, a
+ * reference is given to the caller that it releases by calling
+ * partition_free */
+ ATOMIC ref;
};
struct pool {
@@ -64,7 +70,7 @@ struct pool {
struct cond* cond_fetch;
struct cond* cond_tile;
- size_t next_part_id; /* Indentifier of the next partition */
+ size_t next_part_id; /* Identifier of the next partition */
size_t partition_definition; /* #voxels along the 3 axis */
size_t partition_nvoxels; /* Overall number of voxels in a partition */
size_t voxel_width; /* Number of items per voxel data */
@@ -244,6 +250,9 @@ partition_free(struct partition* partition)
pool = partition->pool;
+ if(ATOMIC_DECR(&partition->ref) != 0)
+ return; /* The partition is still referenced */
+
mutex_lock(pool->mutex);
list_move_tail(&partition->node, &pool->parts_free); /* Free the partition */
if(partition->tile) { /* Free the reserved tile */
@@ -285,6 +294,9 @@ partition_commit(struct partition* partition)
pool = partition->pool;
+ /* Setup the number of partition references */
+ partition->ref = (ATOMIC)partition->pool->voxel_width;
+
/* Committed partitions are sorted in ascending order of their id. We are
* therefore looking for the partition whose id is less than the id of the
* partition to be committed in order to add the latter in the right place */
@@ -296,8 +308,12 @@ partition_commit(struct partition* partition)
list_add(node, &partition->node);
mutex_unlock(pool->mutex);
- /* Notify a thread waiting for a valid partition that we just registered one */
- cond_signal(pool->cond_fetch);
+ /* Notify the threads waiting for a valid partition that we just registered
+ * one. Note that a partition can register several items when voxel_width > 1
+ * and therefore several threads can wait for the same partition.
+ * Consequently, we broadcast the signal to all threads that are blocked on
+ * fetch condition */
+ cond_broadcast(pool->cond_fetch);
}
size_t
@@ -500,7 +516,7 @@ pool_fetch_partition(struct pool* pool, const size_t ipartition)
mutex_lock(pool->mutex);
while(!pool->error) {
- /* Finds the partition that matches the submitted id */
+ /* Search for the partition that matches the submitted id */
LIST_FOR_EACH(node, &pool->parts_commit) {
struct partition* partition = CONTAINER_OF(node, struct partition, node);
@@ -520,8 +536,10 @@ pool_fetch_partition(struct pool* pool, const size_t ipartition)
cond_wait(pool->cond_fetch, pool->mutex);
} else {
- /* Remove the found partition from the list of committed partition */
- list_del(&found_partition->node);
+ /* Do not remove the found partition from the list of committed
+ * partitions since the same partition can be fetched several times when
+ * the width of the voxels is greater than 1 */
+ /* list_del(&found_partition->node); */
break;
}
}