diff --git a/src/vt/group/collective/group_info_collective.cc b/src/vt/group/collective/group_info_collective.cc index 7c7075eb67..f0ba9400cd 100644 --- a/src/vt/group/collective/group_info_collective.cc +++ b/src/vt/group/collective/group_info_collective.cc @@ -227,6 +227,7 @@ void InfoColl::setupCollective() { auto msg = makeMessage( group_, up_tree_cont_, in_group, size, child ); + envelopeSetSystemMsg(msg->env, true); theMsg()->sendMsg(parent, msg); } } @@ -336,6 +337,7 @@ void InfoColl::upTree() { auto msg = makeMessage( group,new_root_cont_,true,subtree_zero,root_node,0,extra ); + envelopeSetSystemMsg(msg->env, true); theMsg()->sendMsg(root_node, msg); for (std::size_t i = 1; i < msg_list.size(); i++) { @@ -377,6 +379,7 @@ void InfoColl::upTree() { auto cmsg = makeMessage( group,op,is_in_group,total_subtree,child,level ); + envelopeSetSystemMsg(cmsg->env, true); theMsg()->sendMsg(p, cmsg); for (auto&& msg : msg_in_group) { @@ -406,6 +409,7 @@ void InfoColl::upTree() { auto msg = makeMessage( group,op,is_in_group,static_cast(subtree_),child,0,extra ); + envelopeSetSystemMsg(msg->env, true); theMsg()->sendMsg(p, msg); /* * Forward all the children messages up the tree (up to 2 of them) @@ -438,9 +442,11 @@ void InfoColl::upTree() { auto msg = makeMessage( group,op,is_in_group,total_subtree,child,0,extra ); + envelopeSetSystemMsg(msg->env, true); theMsg()->sendMsg(p, msg); // new MsgPtr to avoid thief of original in collection auto msg_out = promoteMsg(msg_in_group[0].get()); + envelopeSetSystemMsg(msg_out->env, true); theMsg()->sendMsg(p, msg_out); } else { vtAssertExpr(msg_in_group.size() > 2); @@ -478,6 +484,7 @@ void InfoColl::upTree() { auto msg = makeMessage( group,op,is_in_group,total_subtree,child,0,extra ); + envelopeSetSystemMsg(msg->env, true); theMsg()->sendMsg(p, msg); vt_debug_print( @@ -639,12 +646,14 @@ void InfoColl::downTree(GroupCollectiveMsg* msg) { auto const& num = collective_->span_children_.size(); auto const& child = collective_->span_children_[msg->getChild() % num]; auto nmsg = makeMessage(*msg); + envelopeSetSystemMsg(nmsg->env, true); theMsg()->sendMsg(child, nmsg); ++send_down_; } auto const& group_ = getGroupID(); auto nmsg = makeMessage(group_,down_tree_fin_cont_); + envelopeSetSystemMsg(nmsg->env, true); theMsg()->sendMsg(from, nmsg); } @@ -686,6 +695,7 @@ void InfoColl::sendDownNewTree() { group_, c ); auto msg = makeMessage(group_,new_tree_cont_); + envelopeSetSystemMsg(msg->env, true); theMsg()->sendMsg(c, msg); } } @@ -727,6 +737,7 @@ void InfoColl::finalize() { auto msg = makeMessage( group_,finalize_cont_,known_root_node_,is_default_group_ ); + envelopeSetSystemMsg(msg->env, true); theMsg()->sendMsg(c, msg); } @@ -744,6 +755,7 @@ void InfoColl::finalize() { auto stamp = makeStamp(group_); auto msg = makeMessage(group_); + envelopeSetSystemMsg(msg->env, true); using OpType = collective::PlusOp; auto r = theGroup()->reducer(); diff --git a/src/vt/group/rooted/group_info_rooted.cc b/src/vt/group/rooted/group_info_rooted.cc index 757f85d97a..1f1a21594e 100644 --- a/src/vt/group/rooted/group_info_rooted.cc +++ b/src/vt/group/rooted/group_info_rooted.cc @@ -119,6 +119,7 @@ void InfoRooted::setupRooted() { auto msg = makeMessage( low_node, listsize, group_, op, listsize, this_node, &lst ); + envelopeSetSystemMsg(msg->env, true); is_forward_ = true; forward_node_ = low_node; if (this_node != low_node) { @@ -142,6 +143,7 @@ void InfoRooted::setupRooted() { low_node, regsize, group_, op, regsize, this_node, static_cast(region_.get()) ); + envelopeSetSystemMsg(msg->env, true); is_forward_ = true; forward_node_ = low_node; if (this_node != low_node) { diff --git a/src/vt/messaging/active.impl.h b/src/vt/messaging/active.impl.h index 610b8ece67..053c14cd0d 100644 --- a/src/vt/messaging/active.impl.h +++ b/src/vt/messaging/active.impl.h @@ -68,6 +68,7 @@ void ActiveMessenger::markAsTermMessage(MsgPtrT const msg) { #if vt_check_enabled(trace_enabled) envelopeSetTraceRuntimeEnabled(msg->env, theConfig()->traceTerm()); #endif + envelopeSetSystemMsg(msg->env, true); } template @@ -75,6 +76,7 @@ void ActiveMessenger::markAsLocationMessage(MsgPtrT const msg) { #if vt_check_enabled(trace_enabled) envelopeSetTraceRuntimeEnabled(msg->env, theConfig()->traceLocation()); #endif + envelopeSetSystemMsg(msg->env, true); } template @@ -82,6 +84,7 @@ void ActiveMessenger::markAsSerialMsgMessage(MsgPtrT const msg) { #if vt_check_enabled(trace_enabled) envelopeSetTraceRuntimeEnabled(msg->env, theConfig()->traceSerialMsg()); #endif + envelopeSetSystemMsg(msg->env, true); } template @@ -89,6 +92,7 @@ void ActiveMessenger::markAsCollectionMessage(MsgPtrT const msg) { #if vt_check_enabled(trace_enabled) envelopeSetTraceRuntimeEnabled(msg->env, theConfig()->traceCollection()); #endif + envelopeSetSystemMsg(msg->env, true); } template diff --git a/src/vt/messaging/envelope/envelope_base.h b/src/vt/messaging/envelope/envelope_base.h index 1f0660a2b0..0177919fc6 100644 --- a/src/vt/messaging/envelope/envelope_base.h +++ b/src/vt/messaging/envelope/envelope_base.h @@ -105,6 +105,10 @@ struct ActiveEnvelope { /// Used to denote that the message's bare handlers shouldn't record /// communication LB data due to redundancy bool comm_lb_data_recorded_above_bare_handler : 1; + + /// Used to denote that this is an internal system message that does not do + /// application work + bool system_msg : 1; }; }} /* end namespace vt::messaging */ diff --git a/src/vt/messaging/envelope/envelope_set.h b/src/vt/messaging/envelope/envelope_set.h index 440275be59..23d7e04409 100644 --- a/src/vt/messaging/envelope/envelope_set.h +++ b/src/vt/messaging/envelope/envelope_set.h @@ -250,6 +250,16 @@ inline void envelopeSetIsLocked(Env& env, bool is_locked); template inline void envelopeUnlockForForwarding(Env& env); +/** + * \brief Set whether this is an internal system message + * + * \param[in,out] env the envelope + * \param[in] is_system_msg value indicating message is a system message + */ +template +inline void envelopeSetSystemMsg(Env& env, bool is_system_msg); + + } /* end namespace vt */ #include "vt/messaging/envelope/envelope_set.impl.h" diff --git a/src/vt/messaging/envelope/envelope_set.impl.h b/src/vt/messaging/envelope/envelope_set.impl.h index 7a5c59e996..9c9c1b63ad 100644 --- a/src/vt/messaging/envelope/envelope_set.impl.h +++ b/src/vt/messaging/envelope/envelope_set.impl.h @@ -159,6 +159,11 @@ inline void envelopeSetCommLBDataRecordedAboveBareHandler( comm_lb_data_recorded_above_bare_handler; } +template +inline void envelopeSetSystemMsg(Env& env, bool is_system_msg) { + reinterpret_cast(&env)->system_msg = is_system_msg; +} + template inline void envelopeSetIsLocked(Env& env, bool is_locked) { reinterpret_cast(&env)->is_locked = is_locked; diff --git a/src/vt/messaging/envelope/envelope_setup.impl.h b/src/vt/messaging/envelope/envelope_setup.impl.h index ec7ed83d80..ca407934e7 100644 --- a/src/vt/messaging/envelope/envelope_setup.impl.h +++ b/src/vt/messaging/envelope/envelope_setup.impl.h @@ -76,6 +76,7 @@ inline void envelopeInit(Env& env) { #endif envelopeSetHasBeenSerialized(env, false); envelopeSetCommLBDataRecordedAboveBareHandler(env, false); + envelopeSetSystemMsg(env, false); } inline void envelopeInitEmpty(Envelope& env) { diff --git a/src/vt/scheduler/scheduler.cc b/src/vt/scheduler/scheduler.cc index ceb26aea08..d4687f7b37 100644 --- a/src/vt/scheduler/scheduler.cc +++ b/src/vt/scheduler/scheduler.cc @@ -412,6 +412,24 @@ void Scheduler::releaseEpochObjgroup(EpochType ep, ObjGroupProxyType proxy) { } } +void Scheduler::releaseEpochCollection(EpochType ep, UntypedCollection* untyped) { + if ( + auto iter = pending_collection_work_.find(ep); + iter != pending_collection_work_.end()) + { + if (auto iter2 = iter->second.find(untyped); iter2 != iter->second.end()) { + auto& container = iter2->second; + while (container.size() > 0) { + work_queue_.emplace(container.pop()); + } + iter->second.erase(iter2); + } + if (iter->second.size() == 0) { + pending_collection_work_.erase(iter); + } + } +} + bool Scheduler::isReleasedEpochObjgroup( EpochType ep, ObjGroupProxyType proxy ) const { diff --git a/src/vt/scheduler/scheduler.h b/src/vt/scheduler/scheduler.h index e3f67b82e8..21619d6a56 100644 --- a/src/vt/scheduler/scheduler.h +++ b/src/vt/scheduler/scheduler.h @@ -53,6 +53,7 @@ #include "vt/timing/timing.h" #include "vt/runtime/component/component_pack.h" #include "vt/messaging/async_op_wrapper.fwd.h" +#include "vt/vrt/collection/types/untyped.h" #include #include @@ -115,6 +116,7 @@ struct Scheduler : runtime::component::Component { using TriggerContainerType = std::list; using EventTriggerContType = std::vector; using RunnablePtrType = runnable::RunnableNew*; + using UntypedCollection = vrt::collection::UntypedCollection; struct SchedulerLoopGuard { SchedulerLoopGuard(Scheduler* scheduler); @@ -384,6 +386,13 @@ struct Scheduler : runtime::component::Component { */ void releaseEpochObjgroup(EpochType ep, ObjGroupProxyType proxy); + /** + * \brief Release an epoch to run + * + * \param[in] ep the epoch to release + */ + void releaseEpochCollection(EpochType ep, UntypedCollection* untyped); + /** * \brief Check if a epoch is released for an objgroup * @@ -426,6 +435,7 @@ struct Scheduler : runtime::component::Component { | idleTimeMinusTerm | pending_work_ | pending_objgroup_work_ + | pending_collection_work_ | released_objgroups_; } @@ -472,6 +482,10 @@ struct Scheduler : runtime::component::Component { EpochType, std::unordered_map> > pending_objgroup_work_; + std::unordered_map< + EpochType, std::unordered_map> + > pending_collection_work_; + /// Released epochs for an objgroup std::unordered_map> released_objgroups_; diff --git a/src/vt/scheduler/scheduler.impl.h b/src/vt/scheduler/scheduler.impl.h index 3a0e7ec561..0be989272b 100644 --- a/src/vt/scheduler/scheduler.impl.h +++ b/src/vt/scheduler/scheduler.impl.h @@ -120,22 +120,33 @@ void Scheduler::enqueue(MsgT* msg, RunT r) { template void Scheduler::enqueueOrPostpone(UnitT unit) { auto r = unit.getRunnable(); - auto ep = r->getEpoch(); - - bool const is_dep = epoch::EpochManip::isDep(ep); - - if (is_dep) { - auto obj = r->getObj(); - if (ep != no_epoch and ep != term::any_epoch_sentinel) { - if (obj and r->isObjGroup()) { - auto proxy = objgroup::getProxyFromPtr(obj); - if (released_objgroups_[ep].find(proxy) == released_objgroups_[ep].end()) { - pending_objgroup_work_[ep][proxy].push(unit); + auto m = r->getMsg(); + + // If it's a system message we can schedule it right away + if (m and not m->env.system_msg) { + auto ep = r->getEpoch(); + bool const is_dep = epoch::EpochManip::isDep(ep); + if (is_dep) { + auto obj = r->getObj(); + if (ep != no_epoch and ep != term::any_epoch_sentinel) { + if (obj) { + if (r->isObjGroup()) { + auto proxy = objgroup::getProxyFromPtr(obj); + if (released_objgroups_[ep].find(proxy) == released_objgroups_[ep].end()) { + pending_objgroup_work_[ep][proxy].push(unit); + return; + } + } else { + auto untyped = static_cast(obj); + if (not untyped->isReleasedEpoch(ep)) { + pending_collection_work_[ep][untyped].push(unit); + return; + } + } + } else if (not theTerm()->epochReleased(ep)) { + pending_work_[ep].push(unit); return; } - } else if (not theTerm()->epochReleased(ep)) { - pending_work_[ep].push(unit); - return; } } } diff --git a/src/vt/vrt/collection/manager.h b/src/vt/vrt/collection/manager.h index 9ef6540206..3a4dd0a181 100644 --- a/src/vt/vrt/collection/manager.h +++ b/src/vt/vrt/collection/manager.h @@ -1467,6 +1467,50 @@ struct CollectionManager template void addCleanupFn(VirtualProxyType proxy); +public: + /** + * \brief Release a dependent epoch for a given proxy index + * + * \param[in] proxy the element proxy + * \param[in] epoch epoch to release + */ + template + void releaseEpoch( + VrtElmProxy proxy, EpochType epoch + ); + + /** + * \brief Release a dependent epoch for the whole collection + * + * \param[in] proxy the collection proxy + * \param[in] epoch the epoch to release + */ + template + void releaseEpochCollection(VirtualProxyType proxy, EpochType epoch); + + /** + * \brief Check if a dependent epoch for a given proxy index is released + * + * \param[in] proxy the element proxy + * \param[in] epoch epoch to check + * + * \return whether it is released on this element + */ + template + bool isReleasedEpoch( + VrtElmProxy proxy, EpochType epoch + ); + +private: + /** + * \brief Handler to release a dependent epoch across the whole collection + * + * \param[in] proxy the collection proxy + * \param[in] epoch epoch to release + */ + template + static void releaseWholeCollection(VirtualProxyType proxy, EpochType epoch); + private: template friend struct CollectionElmAttorney; @@ -1782,6 +1826,7 @@ struct CollectionManager #include "vt/vrt/collection/destroy/manager_destroy_attorney.impl.h" #include "vt/vrt/collection/broadcast/broadcastable.impl.h" #include "vt/vrt/collection/rdmaable/rdmaable.impl.h" +#include "vt/vrt/collection/release/releasable.impl.h" #include "vt/vrt/collection/balance/col_lb_data.impl.h" #include "vt/vrt/collection/types/indexable.impl.h" #include "vt/vrt/collection/dispatch/dispatch.impl.h" diff --git a/src/vt/vrt/collection/manager.impl.h b/src/vt/vrt/collection/manager.impl.h index bbf8390711..e0f3dc570a 100644 --- a/src/vt/vrt/collection/manager.impl.h +++ b/src/vt/vrt/collection/manager.impl.h @@ -2319,6 +2319,59 @@ messaging::PendingSend CollectionManager::schedule( }); } +namespace { + +template +void releaseRemoteCollection( + ColT* col, VrtElmProxy proxy, EpochType ep +) { + proxy.release(ep); +} + +} /* end anon namespace */ + +template +void CollectionManager::releaseEpoch( + VrtElmProxy proxy, EpochType epoch +) { + if (auto ptr = proxy.tryGetLocalPtr(); ptr != nullptr) { + ptr->addReleasedEpoch(epoch); + theSched()->releaseEpochCollection(epoch, ptr); + } else { + proxy.template send>(proxy, epoch); + } +} + +template +void CollectionManager::releaseEpochCollection( + VirtualProxyType proxy, EpochType epoch +) { + theMsg()->broadcast>(proxy, epoch); +} + +template +bool CollectionManager::isReleasedEpoch( + VrtElmProxy proxy, EpochType epoch +) { + if (auto ptr = proxy.tryGetLocalPtr(); ptr != nullptr) { + return ptr->isReleasedEpoch(epoch); + } else { + vtAbort("Can not call isReleased on a non-local proxy"); + return false; + } +} + +template +/*static*/ void CollectionManager::releaseWholeCollection( + VirtualProxyType proxy, EpochType epoch +) { + CollectionProxyWrapType typed_proxy{proxy}; + auto const& idxs = theCollection()->getLocalIndices(typed_proxy); + for (auto&& idx : idxs) { + theCollection()->releaseEpoch(typed_proxy[idx], epoch); + } +} + }}} /* end namespace vt::vrt::collection */ #include "vt/vrt/collection/collection_builder.impl.h" diff --git a/src/vt/vrt/collection/proxy_traits/proxy_col_traits.h b/src/vt/vrt/collection/proxy_traits/proxy_col_traits.h index d93b75fcd6..c098014e0f 100644 --- a/src/vt/vrt/collection/proxy_traits/proxy_col_traits.h +++ b/src/vt/vrt/collection/proxy_traits/proxy_col_traits.h @@ -51,13 +51,17 @@ #include "vt/vrt/collection/insert/modifiable.h" #include "vt/vrt/collection/rdmaable/rdmaable.h" #include "vt/vrt/proxy/base_collection_proxy.h" +#include "vt/vrt/collection/release/releasable.h" namespace vt { namespace vrt { namespace collection { namespace col_proxy { template -using Chain5 = RDMAable>; +using Chain6 = ReleasableCol>; + +template +using Chain5 = RDMAable>; template using Chain4 = Modifiable>; diff --git a/src/vt/vrt/collection/proxy_traits/proxy_elm_traits.h b/src/vt/vrt/collection/proxy_traits/proxy_elm_traits.h index e5632b477f..388b981fde 100644 --- a/src/vt/vrt/collection/proxy_traits/proxy_elm_traits.h +++ b/src/vt/vrt/collection/proxy_traits/proxy_elm_traits.h @@ -51,13 +51,17 @@ #include "vt/vrt/collection/invoke/invokable.h" #include "vt/vrt/collection/gettable/gettable.h" #include "vt/vrt/collection/insert/insertable.h" +#include "vt/vrt/collection/release/releasable.h" namespace vt { namespace vrt { namespace collection { namespace elm_proxy { template -using Chain4 = Invokable>; +using Chain5 = Releaseable>; + +template +using Chain4 = Invokable>; template using Chain3 = Gettable>; diff --git a/src/vt/vrt/collection/release/releasable.h b/src/vt/vrt/collection/release/releasable.h new file mode 100644 index 0000000000..df6c06a70e --- /dev/null +++ b/src/vt/vrt/collection/release/releasable.h @@ -0,0 +1,92 @@ +/* +//@HEADER +// ***************************************************************************** +// +// releasable.h +// DARMA/vt => Virtual Transport +// +// Copyright 2019-2021 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#if !defined INCLUDED_VT_VRT_COLLECTION_RELEASE_RELEASABLE_H +#define INCLUDED_VT_VRT_COLLECTION_RELEASE_RELEASABLE_H + +#include "vt/vrt/proxy/base_collection_proxy.h" + +namespace vt::vrt::collection { + +template +struct Releaseable : BaseProxyT { + Releaseable() = default; + Releaseable( + typename BaseProxyT::ProxyType const& in_proxy, + typename BaseProxyT::ElementProxyType const& in_elm + ); + + /** + * \brief Check if dependent epoch is released + * + * \param[in] epoch the epoch in question + * + * \return whether it is released + */ + bool isReleased(EpochType epoch) const; + + /** + * \brief Release a dependent epoch for this element + * + * \param[in] epoch the epoch to release + */ + void release(EpochType epoch) const; +}; + +template +struct ReleasableCol : BaseProxyT { + ReleasableCol() = default; + + explicit ReleasableCol(VirtualProxyType const in_proxy); + + /** + * \brief Release a dependent epoch for the whole collection + * + * \param[in] epoch the epoch to release + */ + void release(EpochType epoch) const; +}; + +} /* end namespace vt::vrt::collection */ + +#endif /*INCLUDED_VT_VRT_COLLECTION_RELEASE_RELEASABLE_H*/ diff --git a/src/vt/vrt/collection/release/releasable.impl.h b/src/vt/vrt/collection/release/releasable.impl.h new file mode 100644 index 0000000000..02dfa0bccf --- /dev/null +++ b/src/vt/vrt/collection/release/releasable.impl.h @@ -0,0 +1,87 @@ +/* +//@HEADER +// ***************************************************************************** +// +// releasable.impl.h +// DARMA/vt => Virtual Transport +// +// Copyright 2019-2021 National Technology & Engineering Solutions of Sandia, LLC +// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact darma@sandia.gov +// +// ***************************************************************************** +//@HEADER +*/ + +#if !defined INCLUDED_VT_VRT_COLLECTION_RELEASE_RELEASABLE_IMPL_H +#define INCLUDED_VT_VRT_COLLECTION_RELEASE_RELEASABLE_IMPL_H + +#include "vt/vrt/collection/release/releasable.h" + +namespace vt::vrt::collection { + +template +Releaseable::Releaseable( + typename BaseProxyT::ProxyType const& in_proxy, + typename BaseProxyT::ElementProxyType const& in_elm +) : BaseProxyT(in_proxy, in_elm) +{ } + +template +bool Releaseable::isReleased(EpochType epoch) const { + auto const& proxy = VrtElmProxy( + this->getCollectionProxy(), this->getElementProxy() + ); + return theCollection()->isReleasedEpoch(proxy, epoch); +} + +template +void Releaseable::release(EpochType epoch) const { + auto const& proxy = VrtElmProxy( + this->getCollectionProxy(), this->getElementProxy() + ); + theCollection()->releaseEpoch(proxy, epoch); +} + +template +ReleasableCol::ReleasableCol( + VirtualProxyType const in_proxy +) : BaseProxyT(in_proxy) +{ } + +template +void ReleasableCol::release(EpochType epoch) const { + theCollection()->releaseEpochCollection(this->getProxy(), epoch); +} + +} /* end namespace vt::vrt::collection */ + +#endif /*INCLUDED_VT_VRT_COLLECTION_RELEASE_RELEASABLE_IMPL_H*/ diff --git a/src/vt/vrt/collection/types/untyped.h b/src/vt/vrt/collection/types/untyped.h index f83029f4c0..87d4e68fcb 100644 --- a/src/vt/vrt/collection/types/untyped.h +++ b/src/vt/vrt/collection/types/untyped.h @@ -61,7 +61,42 @@ struct UntypedCollection : VrtBase, HasMigrate { template void serialize(Serializer& s) { VrtBase::serialize(s); + s | released_epochs_; } + +public: + /** + * \brief Add a released epoch to the set + * + * \param[in] epoch the epoch to add + */ + void addReleasedEpoch(EpochType epoch) { released_epochs_.insert(epoch); } + + /** + * \brief Remove a released epoch from the set + * + * \param[in] epoch the epoch to remove + */ + void removeReleasedEpoch(EpochType epoch) { + if (auto i = released_epochs_.find(epoch); i != released_epochs_.end()) { + released_epochs_.erase(i); + } + } + + /** + * \brief Check if an epoch has been released + * + * \param[in] epoch the epoch to check + * + * \return whether it is released + */ + bool isReleasedEpoch(EpochType epoch) const { + return released_epochs_.find(epoch) != released_epochs_.end(); + } + +private: + /// Released epochs for this collection element + std::unordered_set released_epochs_; }; }}} /* end namespace vt::vrt::collection */