// Path: src/main/java/jocket/futex/Futex.java
// public class Futex implements WaitStrategy {
// 
//   private static boolean libAvailable;
// 
//   private final long futAddr;
// 
//   private final long seqAddr;
// 
//   private final MappedByteBuffer buf;
// 
//   private final int seqPos;
// 
//   /**
//    * @param b a mapped byte buffer
//    * @param futexPos position of the futex variable in buffer
//    * @param seqPos position where the writer writes its latest sequence number
//    */
//   public Futex(MappedByteBuffer b, int futexPos, int seqPos) {
//     this.buf = b;
//     this.seqPos = seqPos;
//     this.futAddr = computeAddress(b, futexPos);
//     this.seqAddr = computeAddress(b, seqPos);
//   }
// 
//   /**
//    * Blocks until the writer posts a packet with a seqnum higher than specified.
//    */
//   @Override
//   public void pauseWhile(int currentSeq) {
//     pause(futAddr, seqAddr, currentSeq);
//   }
// 
//   private static native void pause(long futAddr, long seqAddr, int seq);
// 
//   @Override
//   public void reset() {
//   }
// 
//   private static long computeAddress(MappedByteBuffer b, int pos) {
//     try {
//       return getAddress(b) + pos;
//     } catch (Exception e) {
//       throw new RuntimeException(e);
//     }
//   }
// 
//   /**
//    * For test purposes. Unsafe. Do not use.
//    */
//   public int getInt(int pos) {
//     return getInt0(computeAddress(buf, pos));
//   }
// 
//   /**
//    * For test purposes. Unsafe. Do not use.
//    */
//   public void setInt(int pos, int value) {
//     setInt0(computeAddress(buf, pos), value);
//   }
// 
//   private static native int getInt0(long addr);
// 
//   private static native void setInt0(long addr, int value);
// 
//   /**
//    * Signals the reader that a new packet is available. Happens mainly during
//    * flush(). It includes the cost of a JNI call and a native CAS. A FUTEX_CALL
//    * syscall is performed only if necessary (i.e. the reader is waiting for
//    * data).
//    * 
//    * @param seq
//    */
//   public void signal(int seq) {
//     signal0(futAddr);
//   }
// 
//   @Deprecated
//   public void await() {
//     await0(futAddr);
//   }
// 
//   public static native long getAddress(MappedByteBuffer b);
// 
//   private static native void signal0(long addr);
// 
//   @Deprecated
//   private static native void await0(long addr);
// 
//   public static native long rdtsc();
// 
//   static {
//     try {
//       LibLoader.loadLibrary("JocketFutex");
//       libAvailable = true;
//     } catch (Throwable e) {
//       libAvailable = false;
//       System.err.println("WARN: JNI futex lib is NOT available: " + e);
//     }
//   }
// 
//   public static boolean isAvailable() {
//     return libAvailable;
//   }
// }
// 
// Path: src/main/java/jocket/wait/BusyYieldSleep.java
// public class BusyYieldSleep implements WaitStrategy {
// 
//   public static final int SPIN = 1000000;
// 
//   public static final int YIELD = SPIN + 1;
// 
//   public static final int SLEEP = YIELD + 1;
// 
//   private int counter;
// 
//   @Override
//   public void pauseWhile(int seq) {
//     int counter = this.counter++;
//     if (counter < SPIN)
//       return;
//     else if (counter < YIELD)
//       Thread.yield();
//     else if (counter < SLEEP)
//       LockSupport.parkNanos(1);
//     else {
//       this.counter = 0;
//     }
//   }
// 
//   @Override
//   public void reset() {
//     counter = 0;
//   }
// }
// 
// Path: src/main/java/jocket/wait/WaitStrategy.java
// public interface WaitStrategy {
// 
//   /**
//    * Pauses for some time.
//    * @param seq TODO
//    */
//   void pauseWhile(int seq);
// 
//   /**
//    * Resets the strategy. Called when data has been read or written
//    * successfully.
//    */
//   void reset();
// 
// }


import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import jocket.futex.Futex;
import jocket.wait.BusyYieldSleep;
import jocket.wait.WaitStrategy;
package jocket.impl;



public class JocketReader extends AbstractJocketBuffer {

  private int rseq;

  private int wseq;

// Path: src/main/java/jocket/futex/Futex.java
// public class Futex implements WaitStrategy {
// 
//   private static boolean libAvailable;
// 
//   private final long futAddr;
// 
//   private final long seqAddr;
// 
//   private final MappedByteBuffer buf;
// 
//   private final int seqPos;
// 
//   /**
//    * @param b a mapped byte buffer
//    * @param futexPos position of the futex variable in buffer
//    * @param seqPos position where the writer writes its latest sequence number
//    */
//   public Futex(MappedByteBuffer b, int futexPos, int seqPos) {
//     this.buf = b;
//     this.seqPos = seqPos;
//     this.futAddr = computeAddress(b, futexPos);
//     this.seqAddr = computeAddress(b, seqPos);
//   }
// 
//   /**
//    * Blocks until the writer posts a packet with a seqnum higher than specified.
//    */
//   @Override
//   public void pauseWhile(int currentSeq) {
//     pause(futAddr, seqAddr, currentSeq);
//   }
// 
//   private static native void pause(long futAddr, long seqAddr, int seq);
// 
//   @Override
//   public void reset() {
//   }
// 
//   private static long computeAddress(MappedByteBuffer b, int pos) {
//     try {
//       return getAddress(b) + pos;
//     } catch (Exception e) {
//       throw new RuntimeException(e);
//     }
//   }
// 
//   /**
//    * For test purposes. Unsafe. Do not use.
//    */
//   public int getInt(int pos) {
//     return getInt0(computeAddress(buf, pos));
//   }
// 
//   /**
//    * For test purposes. Unsafe. Do not use.
//    */
//   public void setInt(int pos, int value) {
//     setInt0(computeAddress(buf, pos), value);
//   }
// 
//   private static native int getInt0(long addr);
// 
//   private static native void setInt0(long addr, int value);
// 
//   /**
//    * Signals the reader that a new packet is available. Happens mainly during
//    * flush(). It includes the cost of a JNI call and a native CAS. A FUTEX_CALL
//    * syscall is performed only if necessary (i.e. the reader is waiting for
//    * data).
//    * 
//    * @param seq
//    */
//   public void signal(int seq) {
//     signal0(futAddr);
//   }
// 
//   @Deprecated
//   public void await() {
//     await0(futAddr);
//   }
// 
//   public static native long getAddress(MappedByteBuffer b);
// 
//   private static native void signal0(long addr);
// 
//   @Deprecated
//   private static native void await0(long addr);
// 
//   public static native long rdtsc();
// 
//   static {
//     try {
//       LibLoader.loadLibrary("JocketFutex");
//       libAvailable = true;
//     } catch (Throwable e) {
//       libAvailable = false;
//       System.err.println("WARN: JNI futex lib is NOT available: " + e);
//     }
//   }
// 
//   public static boolean isAvailable() {
//     return libAvailable;
//   }
// }
// 
// Path: src/main/java/jocket/wait/BusyYieldSleep.java
// public class BusyYieldSleep implements WaitStrategy {
// 
//   public static final int SPIN = 1000000;
// 
//   public static final int YIELD = SPIN + 1;
// 
//   public static final int SLEEP = YIELD + 1;
// 
//   private int counter;
// 
//   @Override
//   public void pauseWhile(int seq) {
//     int counter = this.counter++;
//     if (counter < SPIN)
//       return;
//     else if (counter < YIELD)
//       Thread.yield();
//     else if (counter < SLEEP)
//       LockSupport.parkNanos(1);
//     else {
//       this.counter = 0;
//     }
//   }
// 
//   @Override
//   public void reset() {
//     counter = 0;
//   }
// }
// 
// Path: src/main/java/jocket/wait/WaitStrategy.java
// public interface WaitStrategy {
// 
//   /**
//    * Pauses for some time.
//    * @param seq TODO
//    */
//   void pauseWhile(int seq);
// 
//   /**
//    * Resets the strategy. Called when data has been read or written
//    * successfully.
//    */
//   void reset();
// 
// }


// Path: src/main/java/jocket/impl/JocketReader.java
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import jocket.futex.Futex;
import jocket.wait.BusyYieldSleep;
import jocket.wait.WaitStrategy;

package jocket.impl;



public class JocketReader extends AbstractJocketBuffer {

  private int rseq;

  private int wseq;

  private WaitStrategy waiter = new BusyYieldSleep();