1

I'm trying to compile something like this:


#include <list>

class thread
{
public:
 static volatile std::list<thread *> threadList;    //This is also protected by a mutex
};
volatile std::list<thread *> thread::threadList;

void main()
{
 thread A;
 thread::threadList.push_back(&A);
 thread::threadList.remove(&A);
}

I get these errors when trying to compile:


test.cpp(14): error C2663: 'std::list::push_back' : 2 overloads have no legal conversion for 'this' pointer
          with
          [
              _Ty=thread *
          ]
test.cpp(15): error C2662: 'std::list::remove' : cannot convert 'this' pointer from 'volatile std::list' to 'std::list &'
          with
          [
              _Ty=thread *
          ]
          Conversion loses qualifiers

What am I doing wrong?
EDIT: fixed some formatting errors with < and >
EDIT2: threadList is protected by a mutex, I just didn't put it here for simplicity

Mark
  • 2,082
  • 3
  • 17
  • 30
  • I'm betting he wants a list of all c++0x or boost `thread` s he has and he wants the container holding them to be synchronized – KitsuneYMG Jan 27 '11 at 03:12

3 Answers3

4

Remove volatile and remove the problem. So for the real answer, it might help if you explain why you need to volatile, and what it is intended to mean here. It won't make the whole list be treated as volatile.

See also previous answer

Community
  • 1
  • 1
Keith
  • 6,756
  • 19
  • 23
  • I'm using volatile because the list will be used by multiple threads. Also this code is simplified; my actual code has the list protected by a mutex. Now that I think about it, would volatile even make a difference in that case? – Mark Jan 27 '11 at 03:12
  • 1
    @Mark: No. If you have a lock around it, `volatile` is not needed for simple access protection. – JaredC Jan 27 '11 at 03:21
  • 2
    @Mark- Volatile won't make the `vector` thread-safe. You'll need to use explicit locks. Usually, `volatile` means "don't optimize reads and writes of this value because it might be changed from some other space," not "prevent multiple threads from touching this variable." – templatetypedef Jan 27 '11 at 03:22
  • I'm also using volatile with the list because I'm afraid some thread will change it, but the change will go unnoticed by other threads due to the compiler over optimizing – Mark Jan 27 '11 at 03:32
  • 1
    @Mark: That's why you need to use a lock to synchronize access to the `vector`. `volatile` does not do whatever you think it does. You can't use it to guarantee anything in multithreading. – James McNellis Jan 27 '11 at 03:35
3

First of all, volatile is possibly the least understood keyword, and its more than likely NOT doing what you think it is. I learned this the hard way.

That being said, The issue is that volatile can also be used as a qualifier on functions to ensure that they're called in the correct context. The push_back() function is not declared with the volatile qualifier, so calling it on a volatile object is not valid. A nonvolatile member function can only be called for a nonvolatile object.

Community
  • 1
  • 1
JaredC
  • 5,150
  • 1
  • 20
  • 45
2

Using g++ to compile this gives

test.cpp:13: error: passing ‘volatile std::list >’ as ‘this’ argument of ‘void std::list<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = thread*, _Alloc = std::allocator]’ discards qualifiers ...

The discards qualifiers is your hint. The function list::push_back cannot be called on const or volatile instances.

One way to do this:

  • make the list private
  • create a private static mutex
  • create a static public function that add and remove
  • in add and remove acquire the lock, then add or remove from the list
KitsuneYMG
  • 12,753
  • 4
  • 37
  • 58