Improve const-correctness in the LocklessQueue code

This will allow using a read-only mapping for reading data from queues
in ShmEventLoop. This will make it much harder for code reading from a
queue to accidentally modify it.

This involves splitting up LocklessQueue into individual components.
This makes it much more obvious what state is used where, and allows
adding some consts.

Change-Id: Ic83b0d2169e6dfae3eec656aa8e49852125698d9
diff --git a/aos/ipc_lib/index.h b/aos/ipc_lib/index.h
index 890e85f..a47121e 100644
--- a/aos/ipc_lib/index.h
+++ b/aos/ipc_lib/index.h
@@ -133,12 +133,12 @@
 struct AtomicQueueIndex {
  public:
   // Atomically reads the index without any ordering constraints.
-  QueueIndex RelaxedLoad(uint32_t count) {
+  QueueIndex RelaxedLoad(uint32_t count) const {
     return QueueIndex(index_.load(::std::memory_order_relaxed), count);
   }
 
   // Full bidirectional barriers here.
-  QueueIndex Load(uint32_t count) {
+  QueueIndex Load(uint32_t count) const {
     return QueueIndex(index_.load(::std::memory_order_acquire), count);
   }
   inline void Store(QueueIndex value) {
@@ -222,7 +222,7 @@
 class AtomicIndex {
  public:
   // Stores and loads atomically without ordering constraints.
-  Index RelaxedLoad() {
+  Index RelaxedLoad() const {
     return Index(index_.load(::std::memory_order_relaxed));
   }
   void RelaxedStore(Index index) {
@@ -237,7 +237,7 @@
   void Store(Index index) {
     index_.store(index.index_, ::std::memory_order_release);
   }
-  Index Load() { return Index(index_.load(::std::memory_order_acquire)); }
+  Index Load() const { return Index(index_.load(::std::memory_order_acquire)); }
 
   // Swaps expected for index atomically.  Returns true on success, false
   // otherwise.