package concurrency.lmax;

import com.lmax.disruptor.*;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class Main {
  private static final class CpuUsageEvent {
    private int cpuUsage;

    public void setCpuUsage(int cpuUsage) {
      this.cpuUsage = cpuUsage;
    }

    public int getCpuUsage() {
      return cpuUsage;
    }
  }

  private static final EventFactory<CpuUsageEvent> factory = CpuUsageEvent::new;

  private static final EventHandler<CpuUsageEvent> handler =
      (event, sequence, endOfBatch) ->
          System.out.println(Thread.currentThread().getName() + "| Usage: " + event.getCpuUsage() + "% | sequence: " + sequence);

  private static final EventTranslatorOneArg<CpuUsageEvent, Integer> translator =
      (event, sequence, count) -> event.setCpuUsage(count);

  public static void main(String[] args) {
    ExecutorService executor = Executors.newCachedThreadPool();
    int bufferSize = 1024;

    WaitStrategy ws = new BlockingWaitStrategy();
    Disruptor<CpuUsageEvent> disruptor = new Disruptor<>(factory, bufferSize, executor, ProducerType.SINGLE, ws);
    disruptor.handleEventsWith(handler);
    RingBuffer<CpuUsageEvent> ringBuffer = disruptor.start();

    publishEvents(ringBuffer);

    disruptor.shutdown();
    executor.shutdown();
  }

  private static void publishEvents(RingBuffer<CpuUsageEvent> ringBuffer) {
    Random r = new Random();
    for (int i = 0; i < 10000; i++) {
      int p = r.nextInt(100);
      ringBuffer.publishEvent(translator, p);
    }
  }
}