class Atomic {
	std::atomic<int> val = 0;
	static const int writeLockBit = 0x40000000;
	static const int upgradableBit = 0x00010000;
	static const int readerBits = 0x0000ffff;

	void LockInternal(int delta, int testBits)
	{
		int expected;
		do {
			do {
				expected = val;
			} while (expected & testBits);
		} while (!val.compare_exchange_weak(expected, expected + delta));
	}

public:
	void ReadLock()	{ LockInternal(1, writeLockBit); }
	void ReadUnlock() { val.fetch_sub(1); }
	void ReadLockUpgradable() { LockInternal(upgradableBit, writeLockBit | upgradableBit); }
	void ReadUnlockUpgradable() { val.fetch_sub(upgradableBit); }
	void Upgrade() { LockInternal(writeLockBit - upgradableBit, readerBits | writeLockBit); }
	void WriteLock() { LockInternal(writeLockBit, readerBits | writeLockBit); }
	void WriteUnlock() { val.fetch_sub(writeLockBit); }
};