If I understood correctly, then the concurrent collections create a snapshot as a source for the Enumerator
used in a foreach
loop, which requires locking.
Do they cache the snapshots or lock every time? Does this have a potential performance impact? I'm sceptical about micro-measurements, because they so easily lead to false conclusions and am trying to understand the inner workings.
Thanks!
No, it doesn't appear to cache. Here's the code from ConcurrentBag<T>
:
public IEnumerator<T> GetEnumerator()
{
if (m_headList != null)
{
bool lockTaken = false;
try
{
FreezeBag(ref lockTaken);
return ToList().GetEnumerator();
}
finally
{
UnfreezeBag(lockTaken);
}
}
return new List<T>().GetEnumerator();
}
private List<T> ToList()
{
List<T> list = new List<T>();
for (ThreadLocalList threadLocalList = m_headList; threadLocalList != null; threadLocalList = threadLocalList.m_nextList)
{
for (Node node = threadLocalList.m_head; node != null; node = node.m_next)
{
list.Add(node.m_value);
}
}
return list;
}