The trick is to move the external state into the RCU-protected structure. So, instead of the original:
struct rcu_protected { int a; }; struct rcu_protected elements[3]; struct rcu_protected *current = &elements[0]; int consistent; /* must be 2 * current->a */
We write the following:
struct rcu_protected { int a; int consistent; }; struct rcu_protected elements[3]; struct rcu_protected *current = &elements[0];
Then, just before the rcu_assign_pointer()
that sets the
new element (call it p
) to be current, do the following:
p->consistent = 2 * p->a;
Each reader will then be guaranteed to see consistent state. This trick of hiding the relevant state behind a single RCU-protected pointer is a common technique that can greatly simplify concurrent algorithms. Similar techniques are also used in non-blocking synchronization and transactional memory.