You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by do...@apache.org on 2001/11/21 12:40:54 UTC

cvs commit: jakarta-avalon-cornerstone/src/java/org/apache/avalon/cornerstone/blocks/scheduler DefaultTimeScheduler.java

donaldp     01/11/21 03:40:54

  Modified:    src/java/org/apache/avalon/cornerstone/blocks/scheduler
                        DefaultTimeScheduler.java
  Log:
  Attempted to fix some synchronization bugs.
  
  It was possible (and likely) that stop()/dispose() would be ignored and the block would continue on running scheduled events.
  
  It was also possible in very rare circumstances for a newly added event to be ignored if it had close to zero time before it was next scheduled to run. I believe it has been fixed.
  
  Revision  Changes    Path
  1.8       +57 -38    jakarta-avalon-cornerstone/src/java/org/apache/avalon/cornerstone/blocks/scheduler/DefaultTimeScheduler.java
  
  Index: DefaultTimeScheduler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-cornerstone/src/java/org/apache/avalon/cornerstone/blocks/scheduler/DefaultTimeScheduler.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- DefaultTimeScheduler.java	2001/11/19 12:27:25	1.7
  +++ DefaultTimeScheduler.java	2001/11/21 11:40:54	1.8
  @@ -36,8 +36,6 @@
       extends AbstractLogEnabled
       implements Block, TimeScheduler, Composable, Initializable, Startable, Disposable, Runnable
   {
  -    private final Object               m_monitor         = new Object();
  -
       private boolean                    m_running;
       private Hashtable                  m_entries;
       private PriorityQueue              m_priorityQueue;
  @@ -69,9 +67,9 @@
        * @param trigger the trigger
        * @param target the target
        */
  -    public void addTrigger( final String name,
  -                            final TimeTrigger trigger,
  -                            final Target target )
  +    public synchronized void addTrigger( final String name,
  +                                         final TimeTrigger trigger,
  +                                         final Target target )
       {
           try { removeTrigger( name ); }
           catch( final NoSuchElementException nse ) {}
  @@ -86,7 +84,7 @@
           {
               if( entry == m_priorityQueue.peek() )
               {
  -                synchronized( m_monitor ) { m_monitor.notify(); }
  +                notifyAll();
               }
           }
           catch( final NoSuchElementException nse )
  @@ -102,7 +100,7 @@
        * @param name the name of the trigger
        * @exception NoSuchElementException if no trigger exists with that name
        */
  -    public void removeTrigger( String name )
  +    public synchronized void removeTrigger( String name )
           throws NoSuchElementException
       {
           //use the kill-o-matic against any entry with same name
  @@ -117,7 +115,7 @@
        * @param name the name of the trigger
        * @exception NoSuchElementException if no trigger exists with that name
        */
  -    public void resetTrigger( String name )
  +    public synchronized void resetTrigger( final String name )
           throws NoSuchElementException
       {
           final TimeScheduledEntry entry = getEntry( name );
  @@ -134,8 +132,8 @@
        * @param clone true if new entry is to be created
        * @return true if added to queue, false if not added
        */
  -    private boolean rescheduleEntry( final TimeScheduledEntry timeEntry,
  -                                       final boolean clone )
  +    private synchronized boolean rescheduleEntry( final TimeScheduledEntry timeEntry,
  +                                                  final boolean clone )
       {
           TimeScheduledEntry entry = timeEntry;
   
  @@ -162,7 +160,7 @@
   
               if( entry == m_priorityQueue.peek() )
               {
  -                synchronized( m_monitor ) { m_monitor.notify(); }
  +                notify();
               }
   
               return true;
  @@ -228,7 +226,7 @@
       public void stop()
       {
           m_running = false;
  -        synchronized( m_monitor ) { m_monitor.notify(); }
  +        notifyAll();
       }
   
       public void run()
  @@ -241,25 +239,36 @@
   
               if( !m_priorityQueue.isEmpty() )
               {
  -                TimeScheduledEntry entry =
  -                    (TimeScheduledEntry)m_priorityQueue.peek();
  -
  -                //if job has been invalidated then remove it and continue
  -                while( !entry.isValid() )
  +                TimeScheduledEntry entry = null;
  +                synchronized( this )
                   {
  -                    m_priorityQueue.pop();
  +                    entry = getNextEntry();
  +                    if( null == entry ) continue;
   
  -                    if ( m_priorityQueue.isEmpty() ) break;
  +                    duration = entry.getNextTime() - System.currentTimeMillis();
   
  -                    entry = (TimeScheduledEntry)m_priorityQueue.peek();
  +                    if( duration < 0 )
  +                    {
  +                        //time to run job so remove it from priority queue
  +                        //and run it
  +                        m_priorityQueue.pop();
  +
  +                        //Note that we need the pop to occur in a 
  +                        //synchronized section while the runEntry
  +                        //does not need to be synchronized
  +                        //hence why there is to if statements
  +                        //structured in this ugly way
  +                    }
                   }
   
  -                if ( m_priorityQueue.isEmpty() )
  +                if( duration < 0 )
  +                {
  +                    runEntry( entry );
  +                    
  +                    rescheduleEntry( entry, false );
                       continue;
  -
  -                duration = entry.getNextTime() - System.currentTimeMillis();
  -
  -                if( 0 == duration )
  +                }                 
  +                else if( 0 == duration )
                   {
                       //give a short duration that will sleep
                       // so that next loop will definetly be below 0.
  @@ -267,25 +276,35 @@
                       //at once
                       duration = 1;
                   }
  -                else if( duration < 0 )
  -                {
  -                    //time to run job so remove it from priority queue
  -                    //and run it
  -                    m_priorityQueue.pop();
  -
  -                    runEntry( entry );
  -
  -                    rescheduleEntry( entry, false );
  -                    continue;
  -                }
               }
   
  -            //wait/sleep until m_monitor is signalled which occurs when
  +            //wait/sleep until monitor is signalled which occurs when
               //next jobs is likely to occur or when a new job gets added to
               //top of heap
  -            try { synchronized( m_monitor ) { m_monitor.wait( duration ); } }
  +            try { synchronized( this ) { wait( duration ); } }
               catch( final InterruptedException ie ) { }
           }
  +    }
  +
  +    private synchronized TimeScheduledEntry getNextEntry()
  +    {
  +        TimeScheduledEntry entry =
  +            (TimeScheduledEntry)m_priorityQueue.peek();
  +        
  +        //if job has been invalidated then remove it and continue
  +        while( !entry.isValid() )
  +        {
  +            m_priorityQueue.pop();
  +            
  +            if ( m_priorityQueue.isEmpty() ) 
  +            {
  +                return null;
  +            }
  +            
  +            entry = (TimeScheduledEntry)m_priorityQueue.peek();
  +        }
  +
  +        return entry;
       }
   }
   
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


[Phoenix] DefaultTimeScheduler synchronization fixes

Posted by Peter Donald <pe...@apache.org>.
Hi,

I just updated the DefaultTimeScheduler with a few synchronization fixes. 
Below is the changelog for commit. I think I got it right but if people who 
were actually using the block could test their applications and make sure I 
didn't break anything that would be great ;)

On Wed, 21 Nov 2001 22:40, donaldp@apache.org wrote:
> donaldp     01/11/21 03:40:54
>
>   Modified:    src/java/org/apache/avalon/cornerstone/blocks/scheduler
>                         DefaultTimeScheduler.java
>   Log:
>   Attempted to fix some synchronization bugs.
>
>   It was possible (and likely) that stop()/dispose() would be ignored and
> the block would continue on running scheduled events.
>
>   It was also possible in very rare circumstances for a newly added event
> to be ignored if it had close to zero time before it was next scheduled to
> run. I believe it has been fixed.

-- 
Cheers,

Pete

---------------------------------------------------
For every complex problem there is a solution that 
is simple, neat and wrong
---------------------------------------------------

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>