Synchronizing RCU-Protected Data Structures With External State

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.