// 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;
//   }
// }


import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.util.concurrent.atomic.AtomicBoolean;
import jocket.futex.Futex;
package jocket.impl;



/**
 * Base class for JocketReader and JocketWriter.
 *
 * @author pcdv
 */
public abstract class AbstractJocketBuffer implements Const {

  protected final ByteBuffer buf;

  /**
   * Number of data bytes that can be stored in buffer. Must be a power of 2.
   */
  protected final int capacity;

  /**
   * Equals (capacity - 1). Allows to perform quick modulo with binary AND.
   */
  protected final int dataMask;

  /**
   * Maximum number of packets that can be written but not read.
   */
  protected final int npackets;

  /**
   * Equals (npackets - 1). Allows to perform quick modulo with binary AND.
   */
  protected final int packetMask;

  private final AtomicBoolean barrier = new AtomicBoolean();

  protected final int dataOffset;

  protected int resetSeqNum = Integer.MAX_VALUE >> 1;

  protected boolean closed;

  /**
   * This indirection allows to shave off a few nanos by using Unsafe when
   * possible.
   */
  protected final ByteBufferAccessor acc;

  public AbstractJocketBuffer(ByteBuffer buf, int npackets) {
    if (Integer.bitCount(npackets) != 1)
      throw new IllegalArgumentException("npackets must be a power of 2");

// 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/impl/AbstractJocketBuffer.java
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.util.concurrent.atomic.AtomicBoolean;
import jocket.futex.Futex;

package jocket.impl;



/**
 * Base class for JocketReader and JocketWriter.
 *
 * @author pcdv
 */
public abstract class AbstractJocketBuffer implements Const {

  protected final ByteBuffer buf;

  /**
   * Number of data bytes that can be stored in buffer. Must be a power of 2.
   */
  protected final int capacity;

  /**
   * Equals (capacity - 1). Allows to perform quick modulo with binary AND.
   */
  protected final int dataMask;

  /**
   * Maximum number of packets that can be written but not read.
   */
  protected final int npackets;

  /**
   * Equals (npackets - 1). Allows to perform quick modulo with binary AND.
   */
  protected final int packetMask;

  private final AtomicBoolean barrier = new AtomicBoolean();

  protected final int dataOffset;

  protected int resetSeqNum = Integer.MAX_VALUE >> 1;

  protected boolean closed;

  /**
   * This indirection allows to shave off a few nanos by using Unsafe when
   * possible.
   */
  protected final ByteBufferAccessor acc;

  public AbstractJocketBuffer(ByteBuffer buf, int npackets) {
    if (Integer.bitCount(npackets) != 1)
      throw new IllegalArgumentException("npackets must be a power of 2");

    if (buf instanceof MappedByteBuffer && Futex.isAvailable())