Package com.mchange.v2.async

Source Code of com.mchange.v2.async.RoundRobinAsynchronousRunner$RunnableQueueView

/*
* Distributed as part of c3p0 v.0.9.1.1
*
* Copyright (C) 2005 Machinery For Change, Inc.
*
* Author: Steve Waldman <swaldman@mchange.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1, as
* published by the Free Software Foundation.
*
* This software 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 this software; see the file LICENSE.  If not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/


package com.mchange.v2.async;

import com.mchange.v2.log.*;
import com.mchange.v2.util.ResourceClosedException;

/**
* A class that provides for effecient asynchronous execution
* of multiple tasks that may block, but that do not contend
* for the same locks. The order in which tasks will be executed
* is not guaranteed.
*/
public class RoundRobinAsynchronousRunner implements AsynchronousRunner, Queuable
{
    private final static MLogger logger = MLog.getLogger( RoundRobinAsynchronousRunner.class );

    //MT: unchanging, individual elements are thread-safe
    final RunnableQueue[] rqs;

    //MT: protected by this' lock
    int task_turn = 0;

    //MT: protected by this' lock
    int view_turn = 0;

    public RoundRobinAsynchronousRunner( int num_threads, boolean daemon )
    {
  this.rqs = new RunnableQueue[ num_threads ];
  for(int i = 0; i < num_threads; ++i)
      rqs[i] = new CarefulRunnableQueue( daemon, false );
    }

    public synchronized void postRunnable(Runnable r)
    {
  try
      {
    int index = task_turn;
    task_turn = (task_turn + 1) % rqs.length;
    rqs[index].postRunnable( r );

    /* we do this "long-hand" to avoid bad fragility if an exception */
    /* occurs in postRunnable, causing the mod step of the original  */
    /* concise code to get skipped, and leading (if                  */
    /* task_turn == rqs.length - 1 when the exception occurs) to an  */
    /* endless cascade of ArrayIndexOutOfBoundsExceptions.           */
    /* we might alternatively have just put the mod step into a      */
    /* finally block, but that's too fancy.                          */
    /* thanks to Travis Reeder for reporting this problem.           */

    //rqs[task_turn++].postRunnable( r );
    //task_turn %= rqs.length;
      }
  catch ( NullPointerException e )
      {
    //e.printStackTrace();
    if ( Debug.DEBUG )
        {
      if ( logger.isLoggable( MLevel.FINE ) )
          logger.log( MLevel.FINE, "NullPointerException while posting Runnable -- Probably we're closed.", e );
        }
    this.close( true );
    throw new ResourceClosedException("Attempted to use a RoundRobinAsynchronousRunner in a closed or broken state.");
      }
    }

    public synchronized RunnableQueue asRunnableQueue()
    {
  try
      {
    int index = view_turn;
    view_turn = (view_turn + 1) % rqs.length;
    return new RunnableQueueView( index );
   
    /* same explanation as above */
   
    //RunnableQueue out = new RunnableQueueView( view_turn++ );
    //view_turn %= rqs.length;
    //return out;
      }
  catch ( NullPointerException e )
      {
    //e.printStackTrace();
    if ( Debug.DEBUG )
        {
      if ( logger.isLoggable( MLevel.FINE ) )
          logger.log( MLevel.FINE, "NullPointerException in asRunnableQueue() -- Probably we're closed.", e );
        }
    this.close( true );
    throw new ResourceClosedException("Attempted to use a RoundRobinAsynchronousRunner in a closed or broken state.");
      }
    }

    public synchronized void close( boolean skip_remaining_tasks )
    {
  for (int i = 0, len = rqs.length; i < len; ++i)
      {
    attemptClose( rqs[i], skip_remaining_tasks );
    rqs[i] = null;
      }
    }

    public void close()
    { close( true ); }

    static void attemptClose(RunnableQueue rq, boolean skip_remaining_tasks)
    {
  try { rq.close( skip_remaining_tasks ); }
  catch ( Exception e )
      {
    //e.printStackTrace();
    if ( logger.isLoggable( MLevel.WARNING ) )
        logger.log( MLevel.WARNING, "RunnableQueue close FAILED.", e );
      }
    }

    class RunnableQueueView implements RunnableQueue
    {
  final int rq_num;

  RunnableQueueView( int rq_num )
  { this.rq_num = rq_num; }

  public void postRunnable(Runnable r)
  { rqs[ rq_num ].postRunnable( r ); }
 
  public void close( boolean skip_remaining_tasks )
  { }
 
  public void close()
  { /* ignore */ }
    }
}
TOP

Related Classes of com.mchange.v2.async.RoundRobinAsynchronousRunner$RunnableQueueView

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.