Is CList thread-safe

I have one global CList<> object in app and many threads. Is syncronization built-in into CList?
If not, what will be the easiest way to sync access to global CList object?
amakalskiAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

migelCommented:
Hi!
All collections in MFC isn`t thread safe:
IMHO The best way to get thread safety list is write thread safe wrapper around list. Or get thread safe collections from boost library.
0
amakalskiAuthor Commented:
Are std collections thread-safe?

>Or get thread safe collections from boost library
Boost library? Never heard of that, where can I read about it?

I will add points for someone who can show how to code safe wrapper?
0
migelCommented:
For what MFC version you need this class?
0
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

AlexFMCommented:
Suppose you need to write safe wrapper for CList<> class. I recommend to use STL and not MFC container, but it doesn't matter. Safe-thread class has critical section which protects all it's functions from parallel execution in various threads:

class CThreadSafe
{
public:
    <any functions accessing the list>

protected:
    CList<...> m_list;
    CCriticalSection m_CriticalSection;
};

For example, function which adds new element to list:

void CThreadSafe::Add(int n)
{
    m_CriticalSection.Lock();

    // all code between Lock and Unlock is thread-safe
    m_list.AddTail(n);

    m_CriticalSection.Unlock();
}

or, using CSingleLock class, which unlocks critical section in destructor:

void CThreadSafe::Add(int n)
{
    CSingleLock lock(&m_CriticalSection, TRUE);

    // all code between after this line is thread-safe

    m_list.AddTail(n);
}

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
migelCommented:
oops :-)
A can`t write so much code so fast :-)
0
inoxCommented:

that what commented before may be right, but also may not help you. In a way you use that list you must protect outside the List, so a 'protected list' is not suitable and can't be done in a wrapper class:

imagin following situation:

thread 1 calls something like:
1   pos=Lst.GetHeadposition()
2   ptr=Lst.Getnext(pos)
3   ptr->dosomething()

thread 2 calls something like:
1   pos=Lst.GetHeadposition()
2   ptr=Lst.Getnext(pos)
3   ..
4  delete ptr
5  ...

if thread 2 interrupts thread 1 between line1 and 2 ......  :-(
situations like that can hardly be protected by a wrapper class
0
AlexFMCommented:
I don't mean that every CList function should be wrapped in the separate wrapper function. Every function which user needs should be wrapped, and it may contain number of calls to internal CList. For example:

void CThreadSafe::SomeComplicatedFunction(...)
{
   CSingleLock lock(&m_CriticalSection, TRUE);

   // thread-safe code
   pos=m_list.GetHeadposition();
   ptr=m_list.Getnext(pos);
   ptr->dosomething();
   ...
}

Thread-safe class may expose also functions Lock and Unlock which allow to client to call number of function by thread-safe way:

pCThreadSafe->Lock();    // internally locks m_CriticalSection

pCThreadSafe->Function1();
pCThreadSafe->Function2();
...

pCThreadSafe->Unlock();    // internally unlocks m_CriticalSection
0
inoxCommented:

AlexFM,
I agree on your comments. I only wanted to point out to the difference of List-operations-threadsafety and List-contents-threadsafety (even thread-relating problems not outlined completely)

Also I mentioned "you must protect outside the List", thats what you confirmed in your 2nd comment with "pCThreadSafe->Lock();" (outside means: not inside a method of the wrapperclass)

I wanted to prevent amakalski beeing in the assumption he could freely use any operations if he does protect just (and only) inside a  wrapper class.
An exception of this is if it is a wrapper that hides the origin List completely behind a locked list (like Delphi)
0
amakalskiAuthor Commented:
Thanks everybody,
especially AlexFM for excellent code.
0
amakalskiAuthor Commented:
And for future readers of this solution (as inox and AlexFM noted). If you need to iterate through the list outside of the CThreadSafe class
THEN use something like

threadsafelist->Lock();
// Iteration code goes here

threadsafelist->Unlock();
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.