简体   繁体   中英

C++ structs and volatiles

I've got some C code that I'm hoping to transition towards C++, and as a first step, I'm trying to get things compilable with a C++ compiler (g++ right now).

It uses some shared memory segments for IPC and the pointers to these are declared as volatile:

volatile my_rec_t *myRec;

(Where my_rec_t is just a plain old data structure, and myRec is accessed as an array of these).

I'm having some problems with the volatility of this data structure: C++ seems to require a whole lot more casting than C did, and I'm not quite sure I understand why...

There are some auto-generated accessor functions to get/set a field in the shared memory structure (currently all C-style code). This is working for primitive data types but where one of the fields in my_rec_t is itself a struct, it produces errors:

int setIndexNode( int myRecNo, index_node_t indexNode )
{
  myRec[ myRecNo ].indexNode = indexNode;
  return TRUE;
}

In C++ this generates the following: error: passing 'volatile index_node_t' as 'this' argument of 'index_node_t& index_node_t::operator=(const index_node_t&)' discards qualifiers . And for getting the value:

index_node_t getIndexNode( int myRecNo )
{
  return myRec[ myRecNo ].indexNode;
}

The error is error: no matching function for call to 'index_node_t::index_node_t(volatile index_node_t&)'

The get problem is more baffling to me because structs are passed by value, so the returned value, as a copy, is naturally going to lose it's volatility? For the set case, surely volatility is more important in terms of reading the data in case it is changed by another process - I don't really know what volatile means when writing to the data location.

NB: the code snippets are cut down for the purposes of this example, there is various locking and bounds checking code in there :)

For getIndexNode the answer appears to be fairly straightforward: const_cast away the volatility before returning it, since that's your intended semantic. Note that as long as the memory being pointed to by the volatile pointer is not originally declared volatile , casting it away is perfectly well defined.

For the copy assignment operator you could try making it volatile , although you haven't shown enough code to say for sure if that will fix your problem. For example index_node_t& index_node_t::operator=(const index_node_t&) volatile .

It's never safe to cast away the volatility; you can only use member functions that are marked as volatile .

However just doing this does not guarantee safety; the operations are probably non-atomic so a thread switch could rek them. You'll have to also make sure via some locking mechanism or otherwise that when you are using one of these volatile structs, the operation will complete without the struct's data being changed by something else during the operation.

It may turn out to be easier not to use these structs in your shared memory ,but to use some bloc data that you can read and write atomically via an OS function (if such a thing exists).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM