/*
 * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @modules java.base/jdk.internal.foreign
 * @run testng/othervm TestMemorySession
 */

import java.lang.foreign.Arena;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import java.util.stream.IntStream;
import jdk.internal.foreign.MemorySessionImpl;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import static org.testng.Assert.*;

public class TestMemorySession {

    final static int N_THREADS = 100;

    @Test
    public void testConfined() {
        AtomicInteger acc = new AtomicInteger();
        Arena arena = Arena.ofConfined();
        for (int i = 0 ; i < N_THREADS ; i++) {
            int delta = i;
            addCloseAction(arena, () -> acc.addAndGet(delta));
        }
        assertEquals(acc.get(), 0);

        arena.close();
        assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum());
    }

    @Test(dataProvider = "sharedSessions")
    public void testSharedSingleThread(ArenaSupplier arenaSupplier) {
        AtomicInteger acc = new AtomicInteger();
        Arena session = arenaSupplier.get();
        for (int i = 0 ; i < N_THREADS ; i++) {
            int delta = i;
            addCloseAction(session, () -> acc.addAndGet(delta));
        }
        assertEquals(acc.get(), 0);

        if (!TestMemorySession.ArenaSupplier.isImplicit(session)) {
            TestMemorySession.ArenaSupplier.close(session);
            assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum());
        } else {
            session = null;
            int expected = IntStream.range(0, N_THREADS).sum();
            while (acc.get() != expected) {
                kickGC();
            }
        }
    }

    @Test(dataProvider = "sharedSessions")
    public void testSharedMultiThread(ArenaSupplier arenaSupplier) {
        AtomicInteger acc = new AtomicInteger();
        List<Thread> threads = new ArrayList<>();
        Arena session = arenaSupplier.get();
        AtomicReference<Arena> sessionRef = new AtomicReference<>(session);
        for (int i = 0 ; i < N_THREADS ; i++) {
            int delta = i;
            Thread thread = new Thread(() -> {
                try {
                    addCloseAction(sessionRef.get(), () -> {
                        acc.addAndGet(delta);
                    });
                } catch (IllegalStateException ex) {
                    // already closed - we need to call cleanup manually
                    acc.addAndGet(delta);
                }
            });
            threads.add(thread);
        }
        assertEquals(acc.get(), 0);
        threads.forEach(Thread::start);

        // if no cleaner, close - not all segments might have been added to the session!
        // if cleaner, don't unset the session - after all, the session is kept alive by threads
        if (!TestMemorySession.ArenaSupplier.isImplicit(session)) {
            while (true) {
                try {
                    TestMemorySession.ArenaSupplier.close(session);
                    break;
                } catch (IllegalStateException ise) {
                    // session is acquired (by add) - wait some more
                }
            }
        }

        threads.forEach(t -> {
            try {
                t.join();
            } catch (InterruptedException ex) {
                fail();
            }
        });

        if (!TestMemorySession.ArenaSupplier.isImplicit(session)) {
            assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum());
        } else {
            session = null;
            sessionRef.set(null);
            int expected = IntStream.range(0, N_THREADS).sum();
            while (acc.get() != expected) {
                kickGC();
            }
        }
    }

    @Test
    public void testLockSingleThread() {
        Arena arena = Arena.ofConfined();
        List<Arena> handles = new ArrayList<>();
        for (int i = 0 ; i < N_THREADS ; i++) {
            Arena handle = Arena.ofConfined();
            keepAlive(handle, arena);
            handles.add(handle);
        }

        while (true) {
            try {
                arena.close();
                assertEquals(handles.size(), 0);
                break;
            } catch (IllegalStateException ex) {
                assertTrue(handles.size() > 0);
                Arena handle = handles.remove(0);
                handle.close();
            }
        }
    }

    @Test
    public void testLockSharedMultiThread() {
        Arena arena = Arena.ofShared();
        AtomicInteger lockCount = new AtomicInteger();
        for (int i = 0 ; i < N_THREADS ; i++) {
            new Thread(() -> {
                try (Arena handle = Arena.ofConfined()) {
                    keepAlive(handle, arena);
                    lockCount.incrementAndGet();
                    waitSomeTime();
                    lockCount.decrementAndGet();
                } catch (IllegalStateException ex) {
                    // might be already closed - do nothing
                }
            }).start();
        }

        while (true) {
            try {
                arena.close();
                assertEquals(lockCount.get(), 0);
                break;
            } catch (IllegalStateException ex) {
                waitSomeTime();
            }
        }
    }

    @Test
    public void testCloseEmptyConfinedSession() {
        Arena.ofConfined().close();
    }

    @Test
    public void testCloseEmptySharedSession() {
        Arena.ofShared().close();
    }

    @Test
    public void testCloseConfinedLock() {
        Arena arena = Arena.ofConfined();
        Arena handle = Arena.ofConfined();
        keepAlive(handle, arena);
        AtomicReference<Throwable> failure = new AtomicReference<>();
        Thread t = new Thread(() -> {
            try {
                handle.close();
            } catch (Throwable ex) {
                failure.set(ex);
            }
        });
        t.start();
        try {
            t.join();
            assertNotNull(failure.get());
            assertEquals(failure.get().getClass(), WrongThreadException.class);
        } catch (Throwable ex) {
            throw new AssertionError(ex);
        }
    }

    @Test(dataProvider = "allSessions")
    public void testSessionAcquires(ArenaSupplier ArenaSupplier) {
        Arena session = ArenaSupplier.get();
        acquireRecursive(session, 5);
        if (!TestMemorySession.ArenaSupplier.isImplicit(session))
            TestMemorySession.ArenaSupplier.close(session);
    }

    private void acquireRecursive(Arena session, int acquireCount) {
        try (Arena arena = Arena.ofConfined()) {
            keepAlive(arena, session);
            if (acquireCount > 0) {
                // recursive acquire
                acquireRecursive(session, acquireCount - 1);
            }
            if (!ArenaSupplier.isImplicit(session)) {
                assertThrows(IllegalStateException.class, () -> ArenaSupplier.close(session));
            }
        }
    }

    @Test
    public void testConfinedSessionWithImplicitDependency() {
        Arena root = Arena.ofConfined();
        // Create many implicit sessions which depend on 'root', and let them become unreachable.
        for (int i = 0; i < N_THREADS; i++) {
            keepAlive(Arena.ofAuto(), root);
        }
        // Now let's keep trying to close 'root' until we succeed. This is trickier than it seems: cleanup action
        // might be called from another thread (the Cleaner thread), so that the confined session lock count is updated racily.
        // If that happens, the loop below never terminates.
        while (true) {
            try {
                root.close();
                break; // success!
            } catch (IllegalStateException ex) {
                kickGC();
                for (int i = 0 ; i < N_THREADS ; i++) {  // add more races from current thread
                    try (Arena arena = Arena.ofConfined()) {
                        keepAlive(arena, root);
                        // dummy
                    }
                }
                // try again
            }
        }
    }

    @Test
    public void testConfinedSessionWithSharedDependency() {
        Arena root = Arena.ofConfined();
        List<Thread> threads = new ArrayList<>();
        // Create many implicit sessions which depend on 'root', and let them become unreachable.
        for (int i = 0; i < N_THREADS; i++) {
            Arena arena = Arena.ofShared(); // create session inside same thread!
            keepAlive(arena, root);
            Thread t = new Thread(arena::close); // close from another thread!
            threads.add(t);
            t.start();
        }
        for (int i = 0 ; i < N_THREADS ; i++) { // add more races from current thread
            try (Arena arena = Arena.ofConfined()) {
                keepAlive(arena, root);
                // dummy
            }
        }
        threads.forEach(t -> {
            try {
                t.join();
            } catch (InterruptedException ex) {
                // ok
            }
        });
        // Now let's close 'root'. This is trickier than it seems: releases of the confined session happen in different
        // threads, so that the confined session lock count is updated racily. If that happens, the following close will blow up.
        root.close();
    }

    @Test(dataProvider = "nonCloseableSessions")
    public void testNonCloseableSessions(ArenaSupplier arenaSupplier) {
        var arena = arenaSupplier.get();
        var sessionImpl = ((MemorySessionImpl) arena.scope());
        assertFalse(sessionImpl.isCloseable());
        assertThrows(UnsupportedOperationException.class, () ->
                sessionImpl.close());
    }

    @Test(dataProvider = "allSessionsAndGlobal")
    public void testIsCloseableBy(ArenaSupplier arenaSupplier) {
        var arena = arenaSupplier.get();
        var sessionImpl = ((MemorySessionImpl) arena.scope());
        assertEquals(sessionImpl.isCloseableBy(Thread.currentThread()), sessionImpl.isCloseable());
        Thread otherThread = new Thread();
        boolean isCloseableByOther = sessionImpl.isCloseable() && !"ConfinedSession".equals(sessionImpl.getClass().getSimpleName());
        assertEquals(sessionImpl.isCloseableBy(otherThread), isCloseableByOther);
    }

    /**
     * Test that a thread failing to acquire a scope will not observe it as alive afterwards.
     */
    @Test
    public void testAcquireCloseRace() throws InterruptedException {
        int iteration = 1000;
        AtomicInteger lock = new AtomicInteger();
        boolean[] result = new boolean[1];
        MemorySessionImpl[] scopes = new MemorySessionImpl[iteration];
        for (int i = 0; i < iteration; i++) {
            scopes[i] = MemorySessionImpl.toMemorySession(Arena.ofShared());
        }

        // These two threads proceed the scopes array in a lock-step manner, the first thread wait
        // for the second thread on the lock variable, while the second thread wait for the first
        // thread on the closing of the current scope

        // This thread tries to close the scopes
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < iteration;) {
                MemorySessionImpl scope = scopes[i];
                while (true) {
                    try {
                        scope.close();
                        // Continue to the next iteration after a successful close
                        break;
                    } catch (IllegalStateException e) {
                        // Wait for the release and try again
                    }
                }
                // Wait for the other thread to complete its iteration
                int prev = i;
                while (prev == i) {
                    i = lock.get();
                    Thread.onSpinWait();
                }
            }
        });

        // This thread tries to acquire the scopes, then check if it is alive after an acquire failure
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < iteration;) {
                MemorySessionImpl scope = scopes[i];
                while (true) {
                    try {
                        scope.acquire0();
                    } catch (IllegalStateException e) {
                        // The scope has been closed, proceed to the next iteration
                        if (scope.isAlive()) {
                            result[0] = true;
                        }
                        break;
                    }
                    // Release and try again
                    scope.release0();
                }
                // Proceed to the next iteration
                i = lock.getAndAdd(1) + 1;
            }
        });

        t1.start();
        t2.start();
        t1.join();
        t2.join();
        assertFalse(result[0]);
    }

    private void waitSomeTime() {
        try {
            Thread.sleep(10);
        } catch (InterruptedException ex) {
            // ignore
        }
    }

    private void kickGC() {
        for (int i = 0 ; i < 100 ; i++) {
            byte[] b = new byte[100];
            System.gc();
            Thread.onSpinWait();
        }
    }

    @DataProvider
    static Object[][] drops() {
        return new Object[][] {
                { (Supplier<Arena>) Arena::ofConfined},
                { (Supplier<Arena>) Arena::ofShared},
        };
    }

    private void keepAlive(Arena child, Arena parent) {
        MemorySessionImpl parentImpl = MemorySessionImpl.toMemorySession(parent);
        parentImpl.acquire0();
        addCloseAction(child, parentImpl::release0);
    }

    private void addCloseAction(Arena session, Runnable action) {
        MemorySessionImpl sessionImpl = MemorySessionImpl.toMemorySession(session);
        sessionImpl.addCloseAction(action);
    }

    interface ArenaSupplier extends Supplier<Arena> {

        static void close(Arena arena) {
            MemorySessionImpl.toMemorySession(arena).close();
        }

        static boolean isImplicit(Arena arena) {
            return !MemorySessionImpl.toMemorySession(arena).isCloseable();
        }

        static ArenaSupplier ofAuto() {
            return Arena::ofAuto;
        }

        static ArenaSupplier ofGlobal() {
            return Arena::global;
        }

        static ArenaSupplier ofArena(Supplier<Arena> arenaSupplier) {
            return arenaSupplier::get;
        }
    }

    @DataProvider(name = "sharedSessions")
    static Object[][] sharedSessions() {
        return new Object[][] {
                { ArenaSupplier.ofArena(Arena::ofShared) },
                { ArenaSupplier.ofAuto() },
        };
    }

    @DataProvider(name = "allSessions")
    static Object[][] allSessions() {
        return new Object[][] {
                { ArenaSupplier.ofArena(Arena::ofConfined) },
                { ArenaSupplier.ofArena(Arena::ofShared) },
                { ArenaSupplier.ofAuto() },
        };
    }

    @DataProvider(name = "nonCloseableSessions")
    static Object[][] nonCloseableSessions() {
        return new Object[][] {
                { ArenaSupplier.ofGlobal() },
                { ArenaSupplier.ofAuto() }
        };
    }

    @DataProvider(name = "allSessionsAndGlobal")
    static Object[][] allSessionsAndGlobal() {
        return new Object[][] {
                { ArenaSupplier.ofArena(Arena::ofConfined) },
                { ArenaSupplier.ofArena(Arena::ofShared) },
                { ArenaSupplier.ofAuto() },
                { ArenaSupplier.ofGlobal() },
        };
    }

}
