Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4306192

Access to EventQueue functions too limited

XMLWordPrintable

    • generic
    • generic



      Name: krT82822 Date: 01/20/2000


      (see also 4212687)

      1.2.2-W on Solaris (based on follow-up email from user)
      Classic VM (build JDK-1.2.1-A, native threads) [on win32]

      Actually I think this is a bug and not an enhancement since I can't get my job
      done with the existing event class methods.

      I'm trying to scan the event queue for a special character that tells the
      application to interrupt a paint. Normally I would paint to an offscreen
      buffer in another thread so that I can still get events from the main event
      thread. This is not possible in our environment because many users use
      remote displays to view the graphic output. Java's graphics performance when
      using remote displays is awful. So I'm stuck painting without buffers in the
      main event thread...

      Now the problem... The current EventQueue implementation will only let me look
      at the first event on the queue for a given event type. To see following
      events I must call getFirstEvent to pop the first event off of the stack.
      Remember, I'm only trying to look at the events... If I take an event off
      the stack, I must added [add it?] back in. The problem is that if I remove any events
      off the stack, then I have to remove them all and then repost them; otherwise
      the order of the queue will change. Further more, I have to lock the queue so
      that more events are not added by another thread while I'm trying to restore
      the queue. This is the big problem. You can not lock the queue AND call
      postEvent without sometimes hitting a deadlock.

      The code below shows internal Java code getting around this:

      [ from EventDispatchThread.java: --eval1127@eng]

      // fix 4122683, 4128923
      // Post an empty event to ensure getNextEvent is unblocked
      //
              // We have to use postEventPrivate instead of postEvent because
              // EventQueue.pop calls EventDispatchThread.stopDispatching.
              // Calling SunToolkit.flushPendingEvents in this case could
              // lead to deadlock.
      theQueue.postEventPrivate(new EmptyEvent());

      Unfortunately I have no access to the private postEventPrivate method.

      ---------------

      % grep postEventPrivate Event*java | more

      EventDispatchThread.java: // We have to use postEventPrivate instead of postEvent because
      EventDispatchThread.java: theQueue.postEventPrivate(new EmptyEvent());

      EventQueue.java: postEventPrivate(theEvent);
      EventQueue.java: final void postEventPrivate(AWTEvent theEvent) { // <<<<-----------
      EventQueue.java: nextQueue.postEventPrivate(theEvent);
      EventQueue.java: newEventQueue.postEventPrivate(getNextEvent());
      EventQueue.java: previousQueue.postEventPrivate(getNextEvent());


      ---------------

      This whole mess also could have be avoided if my extend EventQueue class
      could override the postEvent and watch events as they come in. This
      unfortunately doesn't work either because most events seem to be posted
      to the hidden private port function.

      Below is most of my code

      public class XstrEventQueue extends EventQueue
      {
         private static XstrEventQueue eventQueue_d = null;
         private static long timestamp = -1;
         private static boolean checkInterrupt_d = false;
         private static volatile boolean interFound_d = false;
         
         static class DummyEvent extends AWTEvent {
            public long timestamp_d;
            DummyEvent(long time)
            {
               super(new Object(), AWTEvent.RESERVED_ID_MAX+1);
               timestamp_d = time;
            }
         }


         XstrEventQueue() {super();}

         static void overrideSystemQueue()
            {
               if (eventQueue_d == null)
               {
                  EventQueue eq =
      xStream.getFrame().getToolkit().getSystemEventQueue();
                  eventQueue_d = new XstrEventQueue();
                  eq.push(eventQueue_d);
               }
            }
         
         static public boolean check_for_interrupt()
            {
               if (interFound_d) return true;
               if (!checkInterrupt_d) return false;
               
               AWTEvent ev;
               
               synchronized(eventQueue_d)
               {
                  // Try a simple test for the first key hit
                  ev = eventQueue_d.peekEvent(KeyEvent.KEY_TYPED);
                  if (graphicEvent(ev))
                  {
                     interFound_d = true;
                     return true;
                  }
                  
                  // Remove all the events so we can scan them
                  
                  // Removing the last event from the queue will block until a
                  // new event has been added. Unfortunately you can't tell if
                  // an event is the last on the queue without popping it off.
                  // We will add a dummy event to the end of the queue to avoid
                  // the block.
                  DummyEvent de = new DummyEvent(++timestamp);
                  eventQueue_d.postEvent(de);
               
                  try {
                     ev = eventQueue_d.getNextEvent();
                  }
                  catch (Exception e) {return false;}

                  Vector events = new Vector(100,50);
                  while (true)
                  {
                     // See if this event is the dummy event we just added
                     if (ev instanceof DummyEvent) {}
                     else events.add(ev);
                  
                     try {
                        // Look ahead to see if the next event is the dummy event that
                        // we posted at the start. If so then we can stop.
                        ev = eventQueue_d.peekEvent();
                        if (ev instanceof DummyEvent)
                        {
                           de = (DummyEvent)ev;
                           if (de.timestamp_d == timestamp) break;
                        }
                        
                        ev = eventQueue_d.getNextEvent();
                     }
                     catch (Exception e) {break;}
                  }
                  
                  // Now scan the events for an interrupt
                  int i;
                  int size = events.size();
                  for (i = 0; i < size; i++)
                  {
                     ev = (AWTEvent) events.get(i);
                     if (graphicEvent(ev))
                     {
                        interFound_d = true;
                        break;
                     }
                  }
                  
                  // push the events back onto the queue
                  for (i = 0; i < size; i++)
                  {
      // *** Deadlock can occur here, The code has to be inside the synchronzied
      section so
      // that new events don't get posted while I'm trying to repost.
                     ev = (AWTEvent) events.get(i);
                     eventQueue_d.postEvent(ev);
                  }
               
                  events.clear();
                  events = null;
                  return interFound_d;
               }
            }
      }

      -------------------

      1/20/2000 eval1127@eng -- asked user to definitely test against 1.2.2 (since this report was originally filed against 1.2.1-A); feedback (1.2.2-W, not 1.2.2-001):


      Actually my mail was not quite accurate. I gave you my PC version. I'm
      actually running "1.2.2-W, green threads" on Solaris.

      I have removed my postEvent code from the synchronized block. Now the
      code hangs every once and a while calling nextEvent. My code tries to
      post a dummy event to keep from hanging. I'm not sure what is going on.

      As far as an enhancement goes... the best thing for me is to have all of
      the postEvent methods available for overriding. The I could just look at
      the events as they come in. Currently Java uses some backdoor post
      function that I can't override. (My extended postEvent never got any
      events, even though some 100 events were on the queue).


      (Review ID: 100202)
      ======================================================================

            art Artem Ananiev (Inactive)
            kryansunw Kevin Ryan (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: