/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.CyclicBarrier;

public class Main implements Runnable {

    // Timeout in minutes. Make it larger than the run-test timeout to get a native thread dump by
    // ART on timeout when running on the host.
    private final static long TIMEOUT_VALUE = 7;

    private final static long MAX_SIZE = 1000;  // Maximum size of array-list to allocate.

    private final static int THREAD_COUNT = 16;

    // Use a couple of different forms of synchronizing to test some of these...
    private final static AtomicInteger counter = new AtomicInteger(-1);
    private final static Object gate = new Object();
    private volatile static int waitCount = 0;

    static {
        // If we're using the interpreter for the boot class path, the VarHandle implementation of
        // AtomicInteger.incrementAndGet() needs to resolve a MethodType which is then cached for
        // subsequent uses. Make sure the MethodType is resolved early, otherwise the
        // counter.incrementAndGet() call in work(), after we have tried to allocate all memory,
        // could throw OOME.
        counter.incrementAndGet();
    }

    public static void main(String[] args) throws Exception {
        Thread[] threads = new Thread[THREAD_COUNT];

        // This barrier is used to synchronize the threads starting to allocate.
        // Note: Even though a barrier is not allocation-free, this one is fine, as it will be used
        //       before filling the heap.
        CyclicBarrier startBarrier = new CyclicBarrier(threads.length);

        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new Main(startBarrier));
            threads[i].start();
        }

        // Wait for the threads to finish.
        for (Thread thread : threads) {
            thread.join();
        }

        // Allocate objects to definitely run GC before quitting.
        allocateObjectsToRunGc();

        new ArrayList<Object>(50);
    }

    private static void allocateObjectsToRunGc() {
      ArrayList<Object> l = new ArrayList<Object>();
      try {
          for (int i = 0; i < 100000; i++) {
              l.add(new ArrayList<Object>(i));
          }
      } catch (OutOfMemoryError oom) {
      }
    }

    private Main(CyclicBarrier startBarrier) {
        this.startBarrier = startBarrier;
    }

    private ArrayList<Object> store;
    private CyclicBarrier startBarrier;

    public void run() {
        try {
            work();
        } catch (Throwable t) {
            // Any exception or error getting here is bad.
            try {
                // May need allocations...
                t.printStackTrace(System.out);
            } catch (Throwable tInner) {
            }
            System.exit(1);
        }
    }

    private void work() throws Exception {
        // Any exceptions except an OOME in the allocation loop are bad and handed off to the
        // caller which should abort the whole runtime.

        ArrayList<Object> l = new ArrayList<Object>();
        store = l;  // Keep it alive.

        // Wait for the start signal.
        startBarrier.await(TIMEOUT_VALUE, java.util.concurrent.TimeUnit.MINUTES);

        // Allocate.
        try {
            for (int i = 0; i < MAX_SIZE; i++) {
                l.add(new ArrayList<Object>(i));
            }
        } catch (OutOfMemoryError oome) {
            // Fine, we're done.
        }

        // Atomically increment the counter and check whether we were last.
        int number = counter.incrementAndGet();

        if (number < THREAD_COUNT) {
            // Not last.
            synchronized (gate) {
                // Increment the wait counter.
                waitCount++;
                gate.wait(TIMEOUT_VALUE * 1000 * 60);
            }
        } else {
            // Last. Wait until waitCount == THREAD_COUNT - 1.
            for (int loops = 0; ; loops++) {
                synchronized (gate) {
                    if (waitCount == THREAD_COUNT - 1) {
                        // OK, everyone's waiting. Notify and break out.
                        gate.notifyAll();
                        break;
                    } else if (loops > 40) {
                        // 1s wait, too many tries.
                        System.out.println("Waited too long for the last thread.");
                        System.exit(1);
                    }
                }
                // Wait a bit.
                Thread.sleep(25);
            }
        }

        store = null;  // Allow GC to reclaim it.
    }
}
