Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/language.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions src/Amalgam/SeparableBoxFilterDataStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,14 @@ class SeparableBoxFilterDataStore
}
}

//removes the label specified by label_sid
inline void RemoveLabel(StringInternPool::StringID label_sid)
{
size_t column_index = GetColumnIndexFromLabelId(label_sid);
if(column_index < columnData.size())
RemoveColumnIndex(column_index);
}

//adds an entity to the database
void AddEntity(Entity *entity, size_t entity_index);

Expand Down
2 changes: 2 additions & 0 deletions src/Amalgam/amlg_code/full_test.amlg
Original file line number Diff line number Diff line change
Expand Up @@ -3827,6 +3827,8 @@

(print "--reclaim_resources--\n")

(reclaim_resources (null) .true ["x"] .true .true )

(reclaim_resources (null) .true .true .true .true )

(print "--null equality tests--\n")
Expand Down
55 changes: 35 additions & 20 deletions src/Amalgam/entity/Entity.h
Original file line number Diff line number Diff line change
Expand Up @@ -586,18 +586,26 @@ class Entity
//when calling this, must ensure that there is a write lock on the entity or that nothing can execute on it
inline void ClearQueryCaches()
{
if(hasContainedEntities && entityRelationships.relationships->queryCaches)
{
#if defined(MULTITHREAD_SUPPORT) || defined(MULTITHREAD_INTERFACE)
//obtain a write lock and immediately release it to make sure there aren't any operations
//waiting to complete. don't need to worry about new operations as they will not be able
//to start with a write lock on this entity
Concurrency::WriteLock write_lock(entityRelationships.relationships->queryCaches->mutex);
write_lock.release();
#endif
if(!HasQueryCaches())
return;

#if defined(MULTITHREAD_SUPPORT) || defined(MULTITHREAD_INTERFACE)
//obtain a write lock and immediately release it to make sure there aren't any operations
//waiting to complete. don't need to worry about new operations as they will not be able
//to start with a write lock on this entity
Concurrency::WriteLock write_lock(entityRelationships.relationships->queryCaches->mutex);
write_lock.release();
#endif

entityRelationships.relationships->queryCaches.reset();
}
entityRelationships.relationships->queryCaches.reset();
}

inline void ClearQueryCacheForLabel(StringInternPool::StringID label_sid)
{
if(!HasQueryCaches())
return;

entityRelationships.relationships->queryCaches->RemoveLabelFromCache(label_sid);
}

//creates a cache if it does not exist
Expand All @@ -607,9 +615,9 @@ class Entity
//returns a nullptr if does not have an active cache
inline EntityQueryCaches *GetQueryCaches()
{
if(hasContainedEntities && entityRelationships.relationships->queryCaches)
return entityRelationships.relationships->queryCaches.get();
return nullptr;
if(!HasQueryCaches())
return nullptr;
return entityRelationships.relationships->queryCaches.get();
}

//returns a pointer to the query caches for this entity's container
Expand Down Expand Up @@ -745,9 +753,15 @@ class Entity
if(this != exclude_entity)
{
if constexpr(std::is_same<EntityReferenceType, EntityWriteReference>::value)
{
if(IsEntityCurrentlyBeingExecuted())
return erbr;
entityWriteReferenceBuffer.emplace_back(this);
}
else
{
entityReadReferenceBuffer.emplace_back(this);
}
}

erbr.maxEntityPathDepth++;
Expand Down Expand Up @@ -965,22 +979,23 @@ class Entity
if(!hasContainedEntities)
return true;

if constexpr(std::is_same<EntityReferenceType, EntityWriteReference>::value)
{
if(IsEntityCurrentlyBeingExecuted())
return false;
}

auto &contained_entities = GetContainedEntities();
for(Entity *e : contained_entities)
{
if(e == exclude_entity)
continue;

if constexpr(std::is_same<EntityReferenceType, EntityWriteReference>::value)
{
if(e->IsEntityCurrentlyBeingExecuted())
return false;

entityWriteReferenceBuffer.emplace_back(e);
}
else
{
entityReadReferenceBuffer.emplace_back(e);
}
}

for(auto &ce : contained_entities)
Expand Down
9 changes: 9 additions & 0 deletions src/Amalgam/entity/EntityQueryCaches.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ class EntityQueryCaches
void EnsureLabelsAreCached(EntityQueryCondition *cond);
#endif

//removes label_sid from the cache
inline void RemoveLabelFromCache(StringInternPool::StringID label_sid)
{
#if defined(MULTITHREAD_SUPPORT) || defined(MULTITHREAD_INTERFACE)
Concurrency::WriteLock write_lock(mutex);
#endif
sbfds.RemoveLabel(label_sid);
}

//returns the set matching_entities of entity ids in the cache that match the provided query condition cond, will fill compute_results with numeric results if KNN query
//if is_first is true, optimizes to skip unioning results with matching_entities (just overwrites instead).
void GetMatchingEntities(EntityQueryCondition *cond, BitArrayIntegerSet &matching_entities, std::vector<DistanceReferencePair<size_t>> &compute_results, bool is_first, bool update_matching_entities);
Expand Down
35 changes: 30 additions & 5 deletions src/Amalgam/interpreter/InterpreterOpcodesBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,13 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_RECLAIM_RESOURCES(Evaluabl
if(ocn.size() > 1)
apply_to_all_contained_entities = InterpretNodeIntoBoolValue(ocn[1]);

bool clear_query_caches = true;
auto clear_query_caches_node = EvaluableNodeReference::Null();
auto node_stack = CreateOpcodeStackStateSaver();
if(ocn.size() > 2)
clear_query_caches = InterpretNodeIntoBoolValue(ocn[2]);
{
clear_query_caches_node = InterpretNode(ocn[2]);
node_stack.PushEvaluableNode(clear_query_caches_node);
}

bool collect_garbage = true;
if(ocn.size() > 3)
Expand All @@ -330,6 +334,13 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_RECLAIM_RESOURCES(Evaluabl
else
target_entity = EntityWriteReference(curEntity);

bool clear_all_query_caches = false;
bool clear_select_query_caches = false;
if(EvaluableNode::IsOrderedArray(clear_query_caches_node))
clear_select_query_caches = true;
else
clear_all_query_caches = EvaluableNode::ToBool(clear_query_caches_node);

if(apply_to_all_contained_entities)
{
//lock all entities
Expand All @@ -338,12 +349,26 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_RECLAIM_RESOURCES(Evaluabl
return EvaluableNodeReference::Null();

for(auto &e : *contained_entities)
e->ReclaimResources(clear_query_caches, collect_garbage, force_free_memory);
{
e->ReclaimResources(clear_all_query_caches, collect_garbage, force_free_memory);
if(clear_select_query_caches)
{
for(auto cn : clear_query_caches_node->GetOrderedChildNodesReference())
target_entity->ClearQueryCacheForLabel(EvaluableNode::ToStringIDIfExists(cn));
}
}
}
else
{
target_entity->ReclaimResources(clear_query_caches, collect_garbage, force_free_memory);
}
target_entity->ReclaimResources(clear_all_query_caches, collect_garbage, force_free_memory);
if(clear_select_query_caches)
{
for(auto cn : clear_query_caches_node->GetOrderedChildNodesReference())
target_entity->ClearQueryCacheForLabel(EvaluableNode::ToStringIDIfExists(cn));
}
}

evaluableNodeManager->FreeNodeTreeIfPossible(clear_query_caches_node);

return EvaluableNodeReference::Null();
}
Expand Down