Salut,
John ROM wrote:
> Hi,
> attached is a patch I would suggest:
>
> from workerthread you could do:
>
> ctx.incrementRefCount();
>
> new Thread() {
>
> public void run() {
> // your business logic
> //now clean up
> ctx.getController().returnContext(ctx);
> }
> }.start();
Here in your example, you aren't using suspend/resume. Should we
correlate the two concepts or should they be orthodonal?
I suspect doing Ctx.resume() should automatically bump the counter as
100% of the time calling resume means do-not-recycle.
Comment in inle (this is quite good).
>
> # This patch file was generated by NetBeans IDE
> # Following Index: paths are relative to: C:\Projects\griz-last\trunk\modules\grizzly\src\main\java\com\sun\grizzly
> # This patch can be applied using context Tools: Patch action on respective folder.
> # It uses platform neutral UTF-8 encoding and \n newlines.
> # Above lines and this line are ignored by the patching process.
> Index: Context.java
> --- Context.java Base (BASE)
> +++ Context.java Locally Modified (Based On LOCAL)
> @@ -49,12 +49,14 @@
> import com.sun.grizzly.util.AttributeHolder;
> import com.sun.grizzly.util.Copyable;
> import com.sun.grizzly.util.SelectionKeyAttachment;
> +import com.sun.grizzly.util.WorkerThread;
> import java.io.IOException;
> import java.net.SocketAddress;
> import java.nio.ByteBuffer;
> import java.nio.channels.SelectionKey;
> import java.util.HashMap;
> import java.util.Map;
> +import java.util.concurrent.atomic.AtomicInteger;
> import java.util.logging.Level;
>
> /**
> @@ -188,6 +190,12 @@
>
>
> /**
> + * Reference Counter indicating How many Threads share this Context
> + * Starts at one.
> + */
> + private AtomicInteger refCounter=new AtomicInteger(1);
> +
> + /**
> * Constructor
> */
> public Context() {
> @@ -209,8 +217,8 @@
> copyContext.ioEvent = ioEvent;
> copyContext.asyncQueueReader = asyncQueueReader;
> copyContext.asyncQueueWriter = asyncQueueWriter;
> - copyContext.asyncQueueReadable = asyncQueueReadable;
> - copyContext.asyncQueueWritable = asyncQueueWritable;
> + // copyContext.asyncQueueReadable = asyncQueueReadable;
> + // copyContext.asyncQueueWritable = asyncQueueWritable;
Is this a typo?
> }
>
> /**
> @@ -366,6 +374,7 @@
> if (attributes != null) {
> attributes.clear();
> }
> + refCounter.set(1);
> isSuspended = false;
> }
>
> @@ -864,5 +873,26 @@
> recycle();
> getController().returnContext(this);
> }
> + /**
> + * Called by Threads that are not instances of {_at_link WorkerThread} to
> + * ensure that other Threads will not {_at_link #recycle()} this
> + * {_at_link Context}
> + * When done they must return this {_at_link Context} to
> + * {_at_link Controller#returnContext(com.sun.grizzly.Context)
> + *
I think we should say:
"Called bu outer Threads..."
Because may still want to use WorkerThread to handle the Context
manipulation.
> + * @return Current Thread reference count
> + */
> + public void incrementRefCount(){
> + refCounter.incrementAndGet();
> + }
>
> + /**
> + * Decrements the reference count of this Context.
> + * See {_at_link Controller#returnContext(com.sun.grizzly.Context)}
> + * @return return decremented reference count
> + */
> + public int decrementRefCount(){
> + return refCounter.decrementAndGet();
> }
> +
> +}
>
>
>
> # This patch file was generated by NetBeans IDE
> # Following Index: paths are relative to: C:\Projects\griz-last\trunk\modules\grizzly\src\main\java\com\sun\grizzly
> # This patch can be applied using context Tools: Patch action on respective folder.
> # It uses platform neutral UTF-8 encoding and \n newlines.
> # Above lines and this line are ignored by the patching process.
> Index: Controller.java
> --- Controller.java Base (BASE)
> +++ Controller.java Locally Modified (Based On LOCAL)
> @@ -599,10 +599,12 @@
> }
>
> /**
> - * Return a Context to the pool
> + * Return a Context to the pool if it is not shared.
> + *
> * @param ctx - the {_at_link Context}
> */
> public void returnContext(Context ctx){
> + if(ctx.decrementRefCount()>0) return;
Here I recommend we add logging with level set to FINEST. We should see,
when logging turned to FINEST that a Context wasn't recycled.
Great work!
--Jeanfrancois
> ctx.recycle();
> contexts.offer(ctx);
> }
>
>
>
> # This patch file was generated by NetBeans IDE
> # Following Index: paths are relative to: C:\Projects\griz-last\trunk\modules\grizzly\src\test\java\com\sun\grizzly
> # This patch can be applied using context Tools: Patch action on respective folder.
> # It uses platform neutral UTF-8 encoding and \n newlines.
> # Above lines and this line are ignored by the patching process.
> Index: ContextShareTest.java
> --- ContextShareTest.java Locally New
> +++ ContextShareTest.java Locally New
> @@ -0,0 +1,188 @@
> +/*
> + *
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
> + *
> + * Copyright 2007-2008 Sun Microsystems, Inc. All rights reserved.
> + *
> + * The contents of this file are subject to the terms of either the GNU
> + * General Public License Version 2 only ("GPL") or the Common Development
> + * and Distribution License("CDDL") (collectively, the "License"). You
> + * may not use this file except in compliance with the License. You can obtain
> + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
> + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
> + * language governing permissions and limitations under the License.
> + *
> + * When distributing the software, include this License Header Notice in each
> + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
> + * Sun designates this particular file as subject to the "Classpath" exception
> + * as provided by Sun in the GPL Version 2 section of the License file that
> + * accompanied this code. If applicable, add the following below the License
> + * Header, with the fields enclosed by brackets [] replaced by your own
> + * identifying information: "Portions Copyrighted [year]
> + * [name of copyright owner]"
> + *
> + * Contributor(s):
> + *
> + * If you wish your version of this file to be governed by only the CDDL or
> + * only the GPL Version 2, indicate your decision by adding "[Contributor]
> + * elects to include this software in this distribution under the [CDDL or GPL
> + * Version 2] license." If you don't indicate a single choice of license, a
> + * recipient has the option to distribute your version of this file under
> + * either the CDDL, the GPL Version 2 or to extend the choice of license to
> + * its licensees as provided above. However, if you add GPL Version 2 code
> + * and therefore, elected the GPL Version 2 license, then the option applies
> + * only if the new code is made subject to such option by the copyright
> + * holder.
> + *
> + */
> +
> +package com.sun.grizzly;
> +
> +import com.sun.grizzly.filter.ReadFilter;
> +import com.sun.grizzly.utils.ControllerUtils;
> +import com.sun.grizzly.utils.TCPIOClient;
> +import java.io.IOException;
> +import java.util.concurrent.CountDownLatch;
> +import junit.framework.TestCase;
> +
> +/**
> + *
> + * @author John Vieten
> + */
> +public class ContextShareTest extends TestCase {
> +
> + public static final int PORT = 17502;
> +
> +
> + public void testContextStillValid() throws IOException {
> + final ProtocolFilter threadFilter = new ProtocolFilter() {
> +
> + public boolean execute(final Context ctx) throws IOException {
> + final CountDownLatch latch = new CountDownLatch(1);
> +
> + ctx.incrementRefCount();
> +
> + new Thread() {
> +
> + @Override
> + public void run() {
> +
> + ctx.getController().returnContext(ctx);
> + //check ctx still valid
> + assertNotNull(ctx.getSelectionKey());
> + latch.countDown();
> + }
> + }.start();
> + try {
> + latch.await();
> + } catch (Exception e) {
> + }
> +
> + return false;
> +
> + }
> +
> + public boolean postExecute(Context ctx) throws IOException {
> + return true;
> + }
> + };
> +
> + Controller controller = createController(PORT, threadFilter);
> +
> + try {
> + ControllerUtils.startController(controller);
> + sendSomething();
> + sleep(2000);
> + } finally {
> + controller.stop();
> + }
> + }
> +
> + public void testContextRecyled() throws IOException {
> + final ProtocolFilter threadFilter = new ProtocolFilter() {
> +
> + public boolean execute(final Context ctx) throws IOException {
> + ctx.incrementRefCount();
> +
> + new Thread() {
> +
> + @Override
> + public void run() {
> + // wait till workerthread decrements ref count
> +
> +
> + ContextShareTest.this.sleep(1500);
> +
> +
> + ctx.getController().returnContext(ctx);
> + }
> + }.start();
> +
> + return false;
> +
> + }
> +
> + public boolean postExecute(Context ctx) throws IOException {
> + return true;
> + }
> + };
> +
> + Controller controller = createController(PORT, threadFilter);
> +
> + try {
> + ControllerUtils.startController(controller);
> + sendSomething();
> + sleep(2000);
> + } finally {
> + controller.stop();
> + }
> + }
> +
> +
> + private Controller createController(int port, final ProtocolFilter threadFilter) {
> + final ProtocolFilter readFilter = new ReadFilter();
> + TCPSelectorHandler selectorHandler = new TCPSelectorHandler();
> + selectorHandler.setPort(port);
> +
> + final Controller controller = new Controller();
> +
> + controller.setSelectorHandler(selectorHandler);
> +
> + controller.setProtocolChainInstanceHandler(
> + new DefaultProtocolChainInstanceHandler() {
> +
> + @Override
> + public ProtocolChain poll() {
> + ProtocolChain protocolChain = protocolChains.poll();
> + if (protocolChain == null) {
> + protocolChain = new DefaultProtocolChain();
> + protocolChain.addFilter(readFilter);
> + protocolChain.addFilter(threadFilter);
> + }
> + return protocolChain;
> + }
> + });
> +
> + return controller;
> + }
> +
> + private void sendSomething() throws IOException {
> + TCPIOClient client = new TCPIOClient("localhost", PORT);
> + try {
> + client.connect();
> + client.send("Test".getBytes());
> +
> + } finally {
> + client.close();
> + }
> +
> +
> + }
> +
> + private void sleep(long millis) {
> + try {
> + Thread.sleep(millis);
> + } catch (Exception e) {
> + }
> + }
> +}
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: