Hi John,
John ROM wrote:
> Hi Jeanfrancois,
>
> I tried some changes which worked for me.
> The grizzly worker Thread must call Context.blockRecycle(true);
> before ist gives the new Thread the context.
>
> I also put synchronized on resume() and isSuspended() because I saw a race condition with ContextTask.recycle()
>
> I show you the code just as an example what works for me:
Why do we need to synchronize here? I think as soon as you invoke the
suspend method, the developer should take care of making a single thread
is manipulating the new object.
Also I'm afraid that not recycling the Context can be problematic as
those instance will be wasted. Can you explain what you are doing to see
the concurrency issues? Sorry for asking so many questions :-)
A+
-- Jeanfrancois
>
> Index: Context.java
> --- Context.java Base (BASE)
> +++ Context.java Locally Modified (Based On LOCAL)
> @@ -49,6 +49,8 @@
> 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;
> @@ -186,7 +188,13 @@
> */
> private boolean isSuspended = false;
>
> + /**
> + * Can this Context be recycled
> + */
> + private boolean blockRecycle;
>
> +
> +
> /**
> * Constructor
> */
> @@ -807,11 +815,11 @@
>
> /**
> * Return <tt>true</tt> if this Context has been suspended by
> - * invoking {_at_link suspend}. When suspended, invoking {_at_link Context#recycle}
> + * invoking {_at_link #suspend}. When suspended, invoking {_at_link Context#recycle}
> * will throw an {_at_link IllegalStateException}
> * @return <tt>true</tt> if this Context has been suspended
> */
> - public boolean isSuspended(){
> + public synchronized boolean isSuspended(){
> return isSuspended;
> }
>
> @@ -828,10 +836,11 @@
> *
> * If the Context hasn't been suspended, calling that method has no effet.
> */
> - public void resume(){
> + public synchronized void resume(){
> if (!isSuspended) return;
> isSuspended = false;
> selectorHandler.register(key, SelectionKey.OP_READ);
> + if(blockRecycle) return;
> recycle();
> getController().returnContext(this);
> }
> @@ -847,12 +856,25 @@
> *
> * If the Context hasn't been suspended, calling that method has no effet.
> */
> - public void cancel(){
> + public synchronized void cancel(){
> if (!isSuspended) return;
> isSuspended = false;
> selectorHandler.getSelectionKeyHandler().cancel(key);
> + if(blockRecycle) return;
> recycle();
> getController().returnContext(this);
> }
>
> + /**
> + * A Thread that for example calls {_at_link #suspend()} might not want that a call to
> + * {_at_link #resume()} recycles this {_at_link com.sun.grizzly.Context}. Therefore
> + * a caller can block the recyling and do it later itself
> + *
> + * @param block
> + */
> + public void blockRecycle(boolean block) {
> + this.blockRecycle=block;
> }
> +
> +
> +}
>
>
> Index: ContextTask.java
> --- ContextTask.java Base (BASE)
> +++ ContextTask.java Locally Modified (Based On LOCAL)
> @@ -59,6 +59,7 @@
> }
>
> public void recycle() {
> + context.blockRecycle(false);
> // Do not recycle when suspended.
> if (context.isSuspended()){
> return;
>
>
> Many Greetings
> John