Use simple mutexes for cases where RDLOCK is not native.

This is exactly the same as using two mutexes because
for RDLOCK you do
  LOCK(lock->read);
for WRLOCK you do
  LOCK(lock->read);
the second lock on ->write is irrelevant because it exists within this mutex always.

So it is simpler & faster to use just a single lock.

Once that is in place, the RDLOCK for the native READLOCK has a race condition

ref_count++ | ref_count--

for the cache entry can run in two parallel processes with ambigous results.

The gcc/vc++ intrinsics for the atomic increments remove this race condition

__sync_add_and_fetch(ref_count) | __sync_sub_and_fetch(ref_count)

will run safely in parallel, as they lock each other out during the read-modify-write sections.