Skip to content

Commit

Permalink
#124 implement new query change detection
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderMertens committed Dec 25, 2021
1 parent be21305 commit 0ec9bd5
Show file tree
Hide file tree
Showing 12 changed files with 1,252 additions and 296 deletions.
477 changes: 370 additions & 107 deletions flecs.c

Large diffs are not rendered by default.

46 changes: 40 additions & 6 deletions flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -2831,7 +2831,7 @@ typedef struct ecs_filter_iter_t {
/** Query-iterator specific data */
typedef struct ecs_query_iter_t {
ecs_query_t *query;
ecs_query_table_node_t *node;
ecs_query_table_node_t *node, *prev;
int32_t sparse_smallest;
int32_t sparse_first;
int32_t bitset_first;
Expand Down Expand Up @@ -6055,18 +6055,52 @@ bool ecs_query_next_instanced(
ecs_iter_t *iter);

/** Returns whether the query data changed since the last iteration.
* This operation must be invoked before obtaining the iterator, as this will
* reset the changed state. The operation will return true after:
* The operation will return true after:
* - new entities have been matched with
* - new tables have been matched/unmatched with
* - matched entities were deleted
* - matched components were changed
*
* @param query The query.
* The operation will not return true after a write-only (EcsOut) or filter
* (EcsInOutFilter) term has changed, when a term is not matched with the
* current table (This subject) or for tag terms.
*
* The changed state of a table is reset after it is iterated. If a iterator was
* not iterated until completion, tables may still be marked as changed.
*
* If no iterator is provided the operation will return the changed state of the
* all matched tables of the query.
*
* If an iterator is provided, the operation will return the changed state of
* the currently returned iterator result. The following preconditions must be
* met before using an iterator with change detection:
*
* - The iterator is a query iterator (created with ecs_query_iter)
* - The iterator must be valid (ecs_query_next must have returned true)
* - The iterator must be instanced
*
* @param query The query (optional if 'it' is provided).
* @param it The iterator result to test (optional if 'query' is provided).
* @return true if entities changed, otherwise false.
*/
FLECS_API
bool ecs_query_changed(
const ecs_query_t *query);
ecs_query_t *query,
ecs_iter_t *it);

/** Skip a table while iterating.
* This operation lets the query iterator know that a table was skipped while
* iterating. A skipped table will not reset its changed state, and the query
* will not update the dirty flags of the table for its out columns.
*
* Only valid iterators must be provided (next has to be called at least once &
* return true) and the iterator must be a query iterator.
*
* @param it The iterator result to skip.
*/
FLECS_API
void ecs_query_skip(
ecs_iter_t *it);

/** Returns whether query is orphaned.
* When the parent query of a subquery is deleted, it is left in an orphaned
Expand Down Expand Up @@ -18526,7 +18560,7 @@ struct query_base {
* @return true if entities changed, otherwise false.
*/
bool changed() {
return ecs_query_changed(m_query);
return ecs_query_changed(m_query, 0);
}

/** Returns whether query is orphaned.
Expand Down
42 changes: 38 additions & 4 deletions include/flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -2885,18 +2885,52 @@ bool ecs_query_next_instanced(
ecs_iter_t *iter);

/** Returns whether the query data changed since the last iteration.
* This operation must be invoked before obtaining the iterator, as this will
* reset the changed state. The operation will return true after:
* The operation will return true after:
* - new entities have been matched with
* - new tables have been matched/unmatched with
* - matched entities were deleted
* - matched components were changed
*
* @param query The query.
* The operation will not return true after a write-only (EcsOut) or filter
* (EcsInOutFilter) term has changed, when a term is not matched with the
* current table (This subject) or for tag terms.
*
* The changed state of a table is reset after it is iterated. If a iterator was
* not iterated until completion, tables may still be marked as changed.
*
* If no iterator is provided the operation will return the changed state of the
* all matched tables of the query.
*
* If an iterator is provided, the operation will return the changed state of
* the currently returned iterator result. The following preconditions must be
* met before using an iterator with change detection:
*
* - The iterator is a query iterator (created with ecs_query_iter)
* - The iterator must be valid (ecs_query_next must have returned true)
* - The iterator must be instanced
*
* @param query The query (optional if 'it' is provided).
* @param it The iterator result to test (optional if 'query' is provided).
* @return true if entities changed, otherwise false.
*/
FLECS_API
bool ecs_query_changed(
const ecs_query_t *query);
ecs_query_t *query,
ecs_iter_t *it);

/** Skip a table while iterating.
* This operation lets the query iterator know that a table was skipped while
* iterating. A skipped table will not reset its changed state, and the query
* will not update the dirty flags of the table for its out columns.
*
* Only valid iterators must be provided (next has to be called at least once &
* return true) and the iterator must be a query iterator.
*
* @param it The iterator result to skip.
*/
FLECS_API
void ecs_query_skip(
ecs_iter_t *it);

/** Returns whether query is orphaned.
* When the parent query of a subquery is deleted, it is left in an orphaned
Expand Down
2 changes: 1 addition & 1 deletion include/flecs/addons/cpp/mixins/query/impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ struct query_base {
* @return true if entities changed, otherwise false.
*/
bool changed() {
return ecs_query_changed(m_query);
return ecs_query_changed(m_query, 0);
}

/** Returns whether query is orphaned.
Expand Down
2 changes: 1 addition & 1 deletion include/flecs/private/api_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ typedef struct ecs_filter_iter_t {
/** Query-iterator specific data */
typedef struct ecs_query_iter_t {
ecs_query_t *query;
ecs_query_table_node_t *node;
ecs_query_table_node_t *node, *prev;
int32_t sparse_smallest;
int32_t sparse_first;
int32_t bitset_first;
Expand Down
4 changes: 3 additions & 1 deletion src/private_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,8 @@ struct ecs_query_table_match_t {

/* Next match in cache for same table (includes empty tables) */
ecs_query_table_match_t *next_match;

int32_t *monitor; /* Used to monitor table for changes */
};

/** A single table can occur multiple times in the cache when a term matches
Expand All @@ -303,7 +305,6 @@ typedef struct ecs_query_table_t {
ecs_table_cache_hdr_t hdr; /* Header for ecs_table_cache_t */
ecs_query_table_match_t *first; /* List with matches for table */
ecs_query_table_match_t *last; /* Last discovered match for table */
int32_t *monitor; /* Used to monitor table for changes */
} ecs_query_table_t;

/** Points to the beginning & ending of a query group */
Expand All @@ -322,6 +323,7 @@ typedef struct ecs_query_table_list_t {
#define EcsQueryIsOrphaned (512) /* Is subquery orphaned */
#define EcsQueryHasOutColumns (1024) /* Does query have out columns */
#define EcsQueryHasOptional (2048) /* Does query have optional columns */
#define EcsQueryHasMonitor (4096) /* Does query track changes */

/* Query event type for notifying queries of world events */
typedef enum ecs_query_eventkind_t {
Expand Down
Loading

0 comments on commit 0ec9bd5

Please sign in to comment.