Package org.rococoa

Source Code of org.rococoa.NSAutoreleasePoolThreadTest

/*
* Copyright 2007, 2008, 2009 Duncan McGregor
*
* This file is part of Rococoa, a library to allow Java to talk to Cocoa.
*
* Rococoa is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Rococoa 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Rococoa.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.rococoa;

import org.junit.Ignore;
import org.junit.Test;
import org.rococoa.cocoa.foundation.NSAutoreleasePool;
import org.rococoa.test.RococoaTestCase;

import java.lang.ref.WeakReference;
import java.util.concurrent.CyclicBarrier;

/**
* NSAutoreleasePool's behaviour wrt threads is interesting. It seems that if
* the thread that the pool was created on has finished, then draining the pool
* crashes. The tests here document the observed behaviour.
* <p/>
* Our default policy is to release the pool's id in its finalizer - this is equivalent
* to draining it, and will fail if the finalizer is only run after the thread has
* exited. So we need a special case (currently in NSObjectInvocationHandler) to
* not release pools in their finalizer.
* <p/>
* NB - not a RococoaTestCase so we know the state of the pools
*
* @author duncan
*/
public class NSAutoreleasePoolThreadTest {

    static {
        RococoaTestCase.initializeLogging();
    }

    // This is the test that is made pass by marking NSAutoreleasePool as ReleaseInFinalize(false)
    @Test
    public void garbageCollectDrainedPool() throws InterruptedException {
        Thread thread = new Thread("test") {
            public void run() {
                NSAutoreleasePool pool = NSAutoreleasePool.new_();
                pool.drain();
            }
        };
        thread.start();
        thread.join();
        RococoaTestCase.gc();
    }


    @Test
    public void drainPoolAndFinalize() {
        NSAutoreleasePool pool = NSAutoreleasePool.new_();
        pool.drain();
        WeakReference<Object> reference = new WeakReference<Object>(pool);
        pool = null;
        while(reference.get() != null) {
            RococoaTestCase.gc();
        }
        RococoaTestCase.gc();
    }

    @Test
    public void drainPoolAndFinalizeOnAnotherThread() throws InterruptedException {
        Thread thread = new Thread("test") {
            public void run() {
                drainPoolAndFinalize();
            }
        };
        thread.start();
        thread.join();
        RococoaTestCase.gc();
    }

    @Ignore("crashes")
    @Test
    public void cantDrainPoolCreatedOnAFinishedThread() throws InterruptedException {
        final NSAutoreleasePool[] poolHolder = new NSAutoreleasePool[1];
        Thread thread = new Thread("test") {
            public void run() {
                poolHolder[0] = NSAutoreleasePool.new_();
            }
        };
        thread.start();
        thread.join();
        poolHolder[0].drain();
    }

    @Ignore("crashes")
    @Test
    public void drainPoolCreatedOnANotFinishedThread() throws InterruptedException {
        final NSAutoreleasePool[] poolHolder = new NSAutoreleasePool[1];
        final CyclicBarrier beforeDrain = new CyclicBarrier(2);
        final CyclicBarrier afterDrain = new CyclicBarrier(2);
        Thread thread = new Thread("test") {
            public void run() {
                poolHolder[0] = NSAutoreleasePool.new_();
                await(beforeDrain);
                await(afterDrain);
            }
        };
        thread.start();
        await(beforeDrain);
        poolHolder[0].drain();
        await(afterDrain);
        thread.join();
    }

    @Test
    public void drainAlreadyDrainedPoolCreatedOnANotFinishedThread() throws InterruptedException {
        final NSAutoreleasePool[] poolHolder = new NSAutoreleasePool[1];
        final CyclicBarrier beforeDrain = new CyclicBarrier(2);
        final CyclicBarrier afterDrain = new CyclicBarrier(2);
        Thread thread = new Thread("test") {
            public void run() {
                poolHolder[0] = NSAutoreleasePool.new_();
                poolHolder[0].drain();
                await(beforeDrain);
                await(afterDrain);
            }
        };
        thread.start();
        await(beforeDrain);
        poolHolder[0].drain();

        await(afterDrain);
        thread.join();
    }

    private void await(CyclicBarrier barrier) {
        try {
            barrier.await();
        }
        catch(Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

}
TOP

Related Classes of org.rococoa.NSAutoreleasePoolThreadTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.