📄 agents.h
字号:
/// The number of items in the <c>single_link_registry</c> object.
/// </returns>
/**/
virtual size_t count()
{
return (_M_connectedLink == NULL) ? 0 : 1;
}
/// <summary>
/// Returns an iterator to the first element in the <c>single_link_registry</c> object.
/// </summary>
/// <remarks>
/// The end state is indicated by a <c>NULL</c> link.
/// </remarks>
/// <returns>
/// An iterator addressing the first element in the <c>single_link_registry</c> object.
/// </returns>
/**/
virtual iterator begin()
{
return (iterator(this, 0));
}
protected:
/// <summary>
/// Skips empty slots and updates the index to the next
/// non-empty slot. This is called by the iterator.
/// </summary>
/// <param name="_Index">
/// A reference to the index that is to be updated.
/// </param>
/**/
virtual void _Next_index(size_t& _Index)
{
if (_M_connectedLink == NULL)
{
_Index++;
}
}
/// <summary>
/// Retrieves the element at the given index. If the index is out of bounds,
/// <c>NULL</c> is returned. Users need to use the iterator to access the links.
/// </summary>
/// <param name="_Index">
/// The index of the link to be retrieved.
/// </param>
/// <returns>
/// The element in the registry at the index specified by the <paramref name="_Index"/> parameter.
/// </returns>
/**/
virtual _EType _Get_element(size_t _Index) const
{
if (_Index == 0)
{
return _M_connectedLink;
}
return NULL;
}
private:
// A single pointer is used to hold the link
_EType _M_connectedLink;
};
/// <summary>
/// The <c>multi_link_registry</c> object is a <c>network_link_registry</c> that manages multiple
/// source blocks or multiple target blocks.
/// </summary>
/// <typeparam name="_Block">
/// The block data type being stored in the <c>multi_link_registry</c> object.
/// </typeparam>
/// <seealso cref="single_link_registry Class"/>
/**/
template<class _Block>
class multi_link_registry : public network_link_registry<_Block>
{
public:
/// <summary>
/// Constructs a <c>multi_link_registry</c> object.
/// </summary>
/**/
multi_link_registry() : _M_maxLinks(_NOT_SET)
{
}
/// <summary>
/// Destroys the <c>multi_link_registry</c> object.
/// </summary>
/// <remarks>
/// The method throws an <see cref="invalid_operation Class">invalid_operation</see> exception if
/// called before all links are removed.
/// </remarks>
/**/
virtual ~multi_link_registry()
{
// It is an error to delete link registry with links
// still present
if (count() != 0)
{
throw invalid_operation("Deleting link registry before removing all the links");
}
}
/// <summary>
/// Sets an upper bound on the number of links that the <c>multi_link_registry</c> object
/// can hold.
/// </summary>
/// <param name="_MaxLinks">
/// The maximum number of links that the <c>multi_link_registry</c> object can hold.
/// </param>
/// <remarks>
/// Once a bound is set, unlinking an entry will cause the <c>multi_link_registry</c>
/// object to enter an immutable state where further calls to <c>add</c> will throw an
/// <c>invalid_link_target</c> exception.
/// </remarks>
/**/
void set_bound(size_t _MaxLinks)
{
_ASSERTE(count() == 0);
_M_maxLinks = _MaxLinks;
}
/// <summary>
/// Adds a link to the <c>multi_link_registry</c> object.
/// </summary>
/// <param name="_Link">
/// A pointer to a block to be added.
/// </param>
/// <remarks>
/// The method throws an <see cref="invalid_link_target Class">invalid_link_target</see> exception if
/// the link is already present in the registry, or if a bound has already been set with the <c>set_bound</c>
/// function and a link has since been removed.
/// </remarks>
/**/
virtual void add(_EType _Link)
{
if (_Link == NULL)
{
return;
}
_Add(_Link);
}
/// <summary>
/// Removes a link from the <c>multi_link_registry</c> object.
/// </summary>
/// <param name="_Link">
/// A pointer to a block to be removed, if found.
/// </param>
/// <returns>
/// <c>true</c> if the link was found and removed, <c>false</c> otherwise.
/// </returns>
/**/
virtual bool remove(_EType _Link)
{
if (_Link == NULL)
{
return false;
}
return (_Remove(_Link));
}
/// <summary>
/// Searches the <c>multi_link_registry</c> object for a specified block.
/// </summary>
/// <param name="_Link">
/// A pointer to a block that is to be searched for in the <c>multi_link_registry</c> object.
/// </param>
/// <returns>
/// <c>true</c> if the specified block was found, <c>false</c> otherwise.
/// </returns>
/**/
virtual bool contains(_EType _Link)
{
if (_Link == NULL)
{
return false;
}
return (_Find(_Link) < _M_vector._Size());
}
/// <summary>
/// Counts the number of items in the <c>multi_link_registry</c> object.
/// </summary>
/// <returns>
/// The number of items in the <c>multi_link_registry</c> object.
/// </returns>
/**/
virtual size_t count()
{
return _Count();
}
/// <summary>
/// Returns an iterator to the first element in the <c>multi_link_registry</c> object.
/// </summary>
/// <remarks>
/// The end state is indicated by a <c>NULL</c> link.
/// </remarks>
/// <returns>
/// An iterator addressing the first element in the <c>multi_link_registry</c> object.
/// </returns>
/**/
virtual iterator begin()
{
return (iterator(this, 0));
}
protected:
/// <summary>
/// Skips empty slots and updates the index to the next
/// non-empty slot. This is called by the iterator.
/// </summary>
/// <param name="_Index">
/// A reference to the index that is to be updated.
/// </param>
/**/
virtual void _Next_index(size_t& _Index)
{
size_t _Size = _M_vector._Size();
while (_Index < _Size)
{
if (_M_vector[_Index] != NULL)
{
break;
}
++_Index;
}
}
/// <summary>
/// Retrieves the element at the given index. If the index is out of bounds,
/// <c>NULL</c> is returned. Users need to use the iterator to access the links
/// </summary>
/// <param name="_Index">
/// Index of the link to be retrieved.
/// </param>
/// <returns>
/// The element in the registry at the index specified by the <paramref name="_Index"/> parameter.
/// </returns>
/**/
virtual _EType _Get_element(size_t _Index) const
{
if (_Index < _M_vector._Size())
{
return _M_vector[_Index];
}
return NULL;
}
private:
/// <summary>
/// Adds a link to the <c>multi_link_registry</c> object.
/// </summary>
/// <param name="_Link">
/// A pointer to a block to be added.
/// </param>
/**/
void _Add(_EType _Link)
{
size_t _Size = _M_vector._Size();
size_t _Insert_pos = 0;
_ASSERTE(_Link != NULL);
// If max links is set, ensure that inserting the new
// link will not exceed the bound.
if ((_M_maxLinks != _NOT_SET) && ((_Size+1) > (size_t) _M_maxLinks))
{
throw invalid_link_target("_Link");
}
for (size_t _Index = 0; _Index < _Size; _Index++)
{
if (_M_vector[_Index] != NULL)
{
// We want to find the first NULL entry after all the
// non-NULL entries.
_Insert_pos = _Index + 1;
// Throw if dupiclate entry is found
if (_M_vector[_Index] == _Link)
{
throw invalid_link_target("_Link");
}
}
}
if (_Insert_pos < _Size)
{
_M_vector[_Insert_pos] = _Link;
}
else
{
_M_vector._Push_back(_Link);
}
}
/// <summary>
/// Removes a link from the <c>multi_link_registry</c>
/// </summary>
/// <param name="_Link">
/// A pointer to a block to be removed, if found.
/// </param>
/// <returns>
/// <c>true</c> if the specified link was found and removed, <c>false</c> otherwise.
/// </returns>
/**/
bool _Remove(_EType _Link)
{
_ASSERTE(_Link != NULL);
for (size_t _Index = 0; _Index < _M_vector._Size(); _Index++)
{
if (_M_vector[_Index] == _Link)
{
_M_vector[_Index] = NULL;
// If max links is set, prevent new additions to the registry
if (_M_maxLinks != _NOT_SET && _M_maxLinks > 0)
{
// Setting the bound to 0. This causes add to always throw.
_M_maxLinks = 0;
}
return true;
}
}
return false;
}
/// <summary>
/// Searches the registry for the given link
/// </summary>
/// <param name="_Link">
/// A pointer to a block that is to be searched.
/// </param>
/// <returns>
/// Index of the entry if found.
/// </returns>
/**/
virtual size_t _Find(_EType _Link)
{
size_t _Index = 0;
for (_Index = 0; _Index < _M_vector._Size(); _Index++)
{
if (_M_vector[_Index] == _Link)
{
break;
}
}
return _Index;
}
/// <summary>
/// Returns the count of items in the registry.
/// </summary>
/// <returns>
/// The count of items in the registry.
/// </returns>
/**/
size_t _Count() const
{
size_t _Count = 0;
for (size_t _Index = 0; _Index < _M_vector._Size(); _Index++)
{
if (_M_vector[_Index] != NULL)
{
_Count++;
}
}
return _Count;
}
static const size_t _NOT_SET = SIZE_MAX;
// Maximum number of links allowed.
size_t _M_maxLinks;
// ::Concurrency::details::_Dynamic_array is used to hold the links
::Concurrency::details::_Dynamic_array<_EType> _M_vector;
};
// Forward declaration for the iterator
template<class _LinkRegistry> class source_link_manager;
/// <summary>
/// Const Iterator for referenced link manager.
/// </summary>
/// <typeparam name="_LinkRegistry">
/// The underlying network link registry
/// </typeparam>
/**/
template<class _LinkRegistry>
class _Source_link_iterator
{
public:
typedef typename _LinkRegistry::type _Block;
typedef _Source_link_iterator<_LinkRegistry> _Myt;
typedef source_link_manager<_LinkRegistry> _MyContainer;
// Element type
typedef _Block* _EType;
// Const iterator - iterator shall not be used to modify the links
typedef _EType const& const_reference;
typedef _EType const* const_pointer;
/// <summary>
/// Construct iterator
/// </summary>
/**/
_Source_link_iterator(_MyContainer * _PNetwork_link, size_t _Index) : _M_pNetwork_link(_PNetwork_link), _M_index(_Index), _M_sentinel(NULL)
{
// Take a snapshot of the link registry. This will reference the registry.
_M_pNetwork_link->_To_array(_M_array);
}
/// <summary>
/// Destruct iterator
/// </summary>
/**/
virtual ~_Source_link_iterator()
{
if (_M_pNetwork_link != NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -