Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > repaint method and design question

Reply
Thread Tools

repaint method and design question

 
 
conrad
Guest
Posts: n/a
 
      06-29-2008
I have two classes:
one for the GUI the other for various scanning methods
on a file system.

I'm experiencing an issue where, while scanning,
the main pane, if minimized and brought back up,
is blank. So I'm thinking I need to constantly
repaint while scanning?

In terms of design: should I be passing around
GUI objects(instance variables) from my GUI class
to my file system scanning class?

Or should I handle it differently?

--
conrad
 
Reply With Quote
 
 
 
 
Stefan Ram
Guest
Posts: n/a
 
      06-29-2008
conrad <(E-Mail Removed)> writes:
>In terms of design: should I be passing around
>GUI objects(instance variables) from my GUI class
>to my file system scanning class?


If you use standard GUI components they should handle
it all for you.

You supply a model, and according to the observer pattern
your UI delegate will be notified of changes to the model
and will update the view.

When you design custom components you implement (overwrite)
╗paintComponentź. But also in this case, it will be called
by Java, whenever necessary (for example, when an obscured part
of your component becomes visible). Maybe you want to study

http://google.to/search?q=java+custom-painting+tutorial

or

http://google.to/search?q=java+obser...delegate+model

 
Reply With Quote
 
 
 
 
Roedy Green
Guest
Posts: n/a
 
      06-29-2008
On Sat, 28 Jun 2008 17:58:37 -0700 (PDT), conrad <(E-Mail Removed)>
wrote, quoted or indirectly quoted someone who said :

>I'm experiencing an issue where, while scanning,
>the main pane, if minimized and brought back up,
>is blank. So I'm thinking I need to constantly
>repaint while scanning?


I don't know what you meant by "scanning" but if it is as all CPU
intensive or long lasting, you should do it on a separate thread, not
the EDT. See http://mindprod.com/jgloss/swingthreads.html
for details.
--

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
 
Reply With Quote
 
John B. Matthews
Guest
Posts: n/a
 
      06-29-2008
In article <(E-Mail Removed)>,
Roedy Green <(E-Mail Removed)> wrote:

> On Sat, 28 Jun 2008 17:58:37 -0700 (PDT), conrad <(E-Mail Removed)>
> wrote, quoted or indirectly quoted someone who said :
>
> >I'm experiencing an issue where, while scanning,
> >the main pane, if minimized and brought back up,
> >is blank. So I'm thinking I need to constantly
> >repaint while scanning?

>
> I don't know what you meant by "scanning" but if it is as all CPU
> intensive or long lasting, you should do it on a separate thread, not
> the EDT. See http://mindprod.com/jgloss/swingthreads.html
> for details.


Roedy's right. Here's the outline of a simple model that may guide your
re-factoring. It uses a javax.swing.Timer to notify the GUI of interim
results (not compiled):

class Scanner extends Observable implements ActionListener, Runnable {

private int interval = 1000 / 4; // 4 Hz
private Timer timer;
private Results results;

public Scanner() {
super();
timer = new Timer(interval, this);
}

public void run() {
timer.start()
// lengthy code that generates results
timer.stop();
setChanged();
notifyObservers(results);
}

public void actionPerformed(ActionEvent e) {
// interim progress
setChanged();
notifyObservers(results);
}
}

public class ScanView extends JPanel implements Observer {
...
public void update(Observable o, Object arg) {
Results results = (Results) arg;
// fill in GUI components with results
this.repaint();
}
}
....
Scanner scanner = new Scanner();
new Thread((Runnable) scanner).start();

--
John B. Matthews
trashgod at gmail dot com
home dot woh dot rr dot com slash jbmatthews
 
Reply With Quote
 
John B. Matthews
Guest
Posts: n/a
 
      06-30-2008
In article <(E-Mail Removed)>,
"Peter Duniho" <(E-Mail Removed)> wrote:

> On Sun, 29 Jun 2008 10:02:10 -0700, John B. Matthews <(E-Mail Removed)>
> wrote:
>
> >> I don't know what you meant by "scanning" but if it is as all CPU
> >> intensive or long lasting, you should do it on a separate thread, not
> >> the EDT. See http://mindprod.com/jgloss/swingthreads.html
> >> for details.

> >
> > Roedy's right. Here's the outline of a simple model that may guide your
> > re-factoring. It uses a javax.swing.Timer to notify the GUI of interim
> > results (not compiled):

>
> Please correct me if I'm wrong, but I see nothing in the code you posted
> that ensures that the observer notification is done on the EDT. The
> documentation specifically says that there are basically no guarantees as
> to how the observer's update() method is called, never mind that it's
> always called on the EDT (in fact, the docs also say that subclasses of
> the Observable class may "deliver notifications on separate threads").


I appreciate your critical analysis! This is an outline of an approach
I've used (successfully) several times for simulations in which a view
displays the interim results calculated by an asynchronously running
model. I'm sure I've overlooked a critical caveat or two

My proposed Scanner implements Runnable, so it's a separate thread. I
recall reading the "separate threads" warning, but I understood the
warning to refer to notification order not being preserved across
threads. Timer(int, ActionListener) ensures that notification is done on
the EDT, but I'm not sure that is required. More importantly, the
Observer is running on the EDT, as it extends an AWT Component.

> Since the notification happens in response to the timer event, and since
> that event happens on the EDT, as long as the base Observable class always
> executes notifications on the same thread on which notifyObservers() is
> called, you're safe. But the docs don't restrict the Observable class in
> this way. I personally wouldn't depend on the current implementation to
> never change, unless there was some specific Java documentation that
> promises that the Observable class will never change in this respect.


The javax.swing.Timer I proposed runs on a separate thread; only it's
action handler executes on the EDT. One _could_ put drawing code in the
handler, but sending a notification instead keeps the model and view
separate. I thinka java.util.Timer would do as well.

> As long as I'm replying, I'll also point out that your sample code
> conveniently skips demonstrating any of the synchronization code that
> would be required in order to successfully respond to the timer while the
> other thread is busily working on the time-consuming operation. This code
> could in fact be included, yes...but it would not be an insignificant
> change. In fact, it's arguably "the hard part" of the whole sample.


Yes, a caveat is warranted: The data structure that the model is
updating must be consistent for a given instant of simulated time, or
the view must receive a consistent copy/snapshot. In the OP's case, it
wouldn't do to have the scanner updating the same TableModel used by the
view!

> Personally, I'd skip the timer altogether, and simply update the UI at
> convenient intervals throughout processing based simply on progress (say,
> every N files, where N is selected based on how long each file would take
> to process). Then just use invokeAndWait() or invokeLater() directly from
> the processing thread to call code that would update the GUI. This allows
> the processing thread to package up the interesting data synchronously
> without any actual explicit synchronization overhead, and send it off to
> the GUI via the EDT, taking advantage of the EDT's own built-in
> synchronization mechanisms.


This approach makes better sense than mine for the OP's file scanning
operation. Of course, the scanner thread still has to decide when it has
useful, self-consistent, interim results. My approach may be more suited
to watching a numerical simulation evolve, where there's no _a_priori_
way to know a preferred update point, other than "periodically".

> Just my two cents.


Worth much more! What, with compound interest and the price of copper,
etc.

--
John B. Matthews
trashgod at gmail dot com
home dot woh dot rr dot com slash jbmatthews
 
Reply With Quote
 
John B. Matthews
Guest
Posts: n/a
 
      07-01-2008
In article <(E-Mail Removed)>,
"Peter Duniho" <(E-Mail Removed)> wrote:

> On Mon, 30 Jun 2008 15:32:07 -0700, John B. Matthews <(E-Mail Removed)>
> wrote:
>
> > [...]
> > My proposed Scanner implements Runnable, so it's a separate thread. I
> > recall reading the "separate threads" warning, but I understood the
> > warning to refer to notification order not being preserved across
> > threads.

>
> Well, IMHO the docs are ambiguous. To me, the important part is that they
> go out of their way to say that one should not rely on the notification
> being done on a particular thread. The warning is in the context of
> dealing with sub-classes of Observable, and so there _could_ be an
> implication that as long as the sub-class doesn't change the default
> implementation, the notification will be done on the same thread on which
> notifyObservers() is called.


Yes, the subclass that implements Observable should behave correctly,
but I read the paragraph about notification order as a warning to
Observers that an Observable may change the order and thread.

> But that's an assumption, and as we all know, assumptions are not nearly
> as valuable as things printed in black and white.


Agreed!

> > Timer(int, ActionListener) ensures that notification is done on
> > the EDT,

>
> Now this is exactly what I'm talking about. The Swing Timer class
> does ensure that the Action event itself happens on the EDT.
> However, there's nothing about Timer that guarantees that when you
> call notifyObservers(), the notification itself happens on the same
> thread on which that method was called.
>
> For example, one implementation could create a copy of the observer
> list and then ship that off to yet another thread to process the
> list asynchronously.
>
> I don't even know for sure that the _current_ implementation keeps
> the notification on the same thread as which notifyObservers() was
> called (though I do agree it's likely, I haven't bothered to check
> it myself, and the fact is it could be implementation-dependent),
> but it does seem to me that the docs don't promise that even if it's
> true now, it always will be true.


I don't think it matters as long as the Observer respects the
order/thread warning above. In particular, my proposed Observer's
update(Observable, Object) method ends with repaint(). The hidden
assumption is that repaint() must be invoked from a JComponent, which
uses the RepaintManager to run from the EDT:

<http://java.sun.com/products/jfc/tsc...ex.html#paint_
process>

> > but I'm not sure that is required. More importantly, the
> > Observer is running on the EDT, as it extends an AWT Component.

>
> It depends on what you mean by "is running on the EDT". It's true
> that your Observer-implementing class is a Swing (not just AWT)
> component. But that doesn't guarantee that code in that class is
> run on the EDT. In fact, that's the whole issue: it _is_ a Swing
> component and so when you execute Swing-dependent code in the class,
> you have to go out of your way to ensure that happens on the EDT.


Good point! I should have said JComponent.

> If that's what you meant, then yes...I agree. But if your statement was
> intended to mean that because you've sub-classed JFrame, you're assured
> that calls to your sub-class are always on the EDT, that would be wrong.


Yes, for JFrame. I proposed JPanel, which is a JComponent, but your
point is well taken.

> > The javax.swing.Timer I proposed runs on a separate thread; only
> > it's action handler executes on the EDT. One _could_ put drawing
> > code in the handler, but sending a notification instead keeps the
> > model and view separate. I thinka java.util.Timer would do as well.

>
> See above. I agree that the Timer Action event is raised on the EDT,
> but that doesn't necessarily guarantee that the Observer's update()
> method is called on the EDT. There's a missing link between your
> actionPerformed() method being called, and the Observer's update()
> method being called that involves ambiguously defined behavior on
> the part of the Java run-time.


As long as the Observer's update() repaints a lightweight container, I
don't think it matters if the notification doesn't come from the EDT.

> >> As long as I'm replying, I'll also point out that your sample code
> >> conveniently skips demonstrating any of the synchronization code
> >> that would be required in order to successfully respond to the
> >> timer while the other thread is busily working on the
> >> time-consuming operation. This code could in fact be included,
> >> yes...but it would not be an insignificant change. In fact, it's
> >> arguably "the hard part" of the whole sample.

> >
> > Yes, a caveat is warranted: The data structure that the model is
> > updating must be consistent for a given instant of simulated time,
> > or the view must receive a consistent copy/snapshot. In the OP's
> > case, it wouldn't do to have the scanner updating the same
> > TableModel used by the view!

>
> Well, more specifically, since you know that the Timer Action event
> will be raised on the EDT, and you also know that the scanning work
> is done on a thread other than the EDT, you are assured that you
> need some kind of synchronization mechanism. Even if this is as
> simple as having the scanning thread making immutable copies of its
> progress at regular intervals and assigned references to the data to
> a volatile variable, _some_ sort of effort needs to be made to keep
> things synchronized.


Agreed, although there are stochastic models where no synchronization at
all gives satisfactory results.

> >> Personally, I'd skip the timer altogether, and simply update the
> >> UI at convenient intervals throughout processing based simply on
> >> progress (say, every N files, where N is selected based on how
> >> long each file would take to process). Then just use
> >> invokeAndWait() or invokeLater() directly from the processing
> >> thread to call code that would update the GUI. This allows the
> >> processing thread to package up the interesting data synchronously
> >> without any actual explicit synchronization overhead, and send it
> >> off to the GUI via the EDT, taking advantage of the EDT's own
> >> built-in synchronization mechanisms.

> >
> > This approach makes better sense than mine for the OP's file
> > scanning operation. Of course, the scanner thread still has to
> > decide when it has useful, self-consistent, interim results. My
> > approach may be more suited to watching a numerical simulation
> > evolve, where there's no _a_priori_ way to know a preferred update
> > point, other than "periodically".

>
> Agreed...to the extent that it might be difficult to determine what a
> "preferred update point" is, a timer-based approach might work
> better. I'm not sure that that applies to a numerical simulation,
> but that's only because of the broadness of that genre of
> algorithms. Some numerical simulations lend themselves just fine to
> predictable update points, others might not.
>
> Note, however, that the more likely that an algorithm is specifically
> in need of a timer-based approach, the more complex the
> synchronization mechanism will have to be (i.e. just copying
> immutable results to a volatile variable won't do, since if you
> could do that, it'd imply that you do in fact have predictable
> update points ).


Don't similar synchronization problems attend to using the invoke*
utilities?

> >> Just my two cents.

> >
> > Worth much more! What, with compound interest and the price of copper,
> > etc.

>
> Thanks.


--
John B. Matthews
trashgod at gmail dot com
home dot woh dot rr dot com slash jbmatthews
 
Reply With Quote
 
John B. Matthews
Guest
Posts: n/a
 
      07-02-2008
In article <(E-Mail Removed)>,
Lew <(E-Mail Removed)> wrote:

> John B. Matthews wrote:
> > I don't think it matters as long as the Observer respects the
> > order/thread warning above. In particular, my proposed Observer's
> > update(Observable, Object) method ends with repaint(). The hidden
> > assumption is that repaint() must be invoked from a JComponent, which
> > uses the RepaintManager to run from the EDT:

>
> I see nothing in the Javadocs for JComponent#repaint() that indicates
> that the method is thread safe.


Yes, the SDN article is referenced in Component, and perhaps elsewhere.

> But you showed us
> > <http://java.sun.com/products/jfc/tsc...ng/index.html#
> > paint_process>

>
> which explains that repaint() is thread safe.


Only for JComponents: "JComponent.repaint() registers an asynchronous
repaint request to the component's RepaintManager, which uses
invokeLater() to queue a Runnable to later process the request on the
event dispatching thread."

> This worries me, as I had thought the Javadocs to be normative.


A linked article is less dispositive, I suppose, but not entirely
unreliable

> > ... there are stochastic models where no synchronization at
> > all gives satisfactory results.

>
> How do variable values communicate across threads in that case?
>
> Or by "stochastic" do you mean that it doesn't matter, because the
> results are intended to be random?


Yes, the results evolve in apparent random order: many kinds of
fractals; diffusion limited aggregation, which has a fractal character;
any iteration over a set of lattice points in which you don't care that
some points are from iteration n-1 and some from iteration n.

> I really do wonder how one handles the memory-model concerns in that
> "stochastic models" scenario. Would you be so gracious as to explain?


My point was only that sometimes it doesn't matter if the model is
changing under you. When it matters, you have to synchronize access, of
course. Sorry if I seemed to be arguing to the contrary.

Oh, and I hope I am always gracious!

--
John B. Matthews
trashgod at gmail dot com
home dot woh dot rr dot com slash jbmatthews
 
Reply With Quote
 
John B. Matthews
Guest
Posts: n/a
 
      07-02-2008
In article <(E-Mail Removed)>,
"Peter Duniho" <(E-Mail Removed)> wrote:

> On Tue, 01 Jul 2008 12:57:37 -0700, John B. Matthews <(E-Mail Removed)>
> wrote:
>
> > Yes, the subclass that implements Observable should behave correctly,

>
> Define "correctly". The point of the statements in the documentation
> is that the Observable class is not under any restriction regarding
> how it deals with notification. That's my point. There's a whole
> range of what can be considered "correct", including any variety of
> implementations that don't allow you assume that the Observer's
> update() method is called on the EDT.


I think we agree on this for subclasses.

> > but I read the paragraph about notification order as a warning to
> > Observers that an Observable may change the order and thread.

>
> Yes, it may. And IMHO this can include the base Observable class.


I must demur: "The default implementation provided in the Observable
class will notify Observers in the order in which they registered
interest..." tells me that order is preserved if my subclass doesn't
change it. If I do change it, Observers must accept that.

The phrases "...this notification mechanism is has nothing to do with
threads..." and "Each observer has its update method called..." tell me
that my subclass will execute the update() method of a registered
Observer even if they're in different threads, and Observers have to
accept what that implies.

> > [...]
> >> I don't even know for sure that the _current_ implementation keeps
> >> the notification on the same thread as which notifyObservers()
> >> was called (though I do agree it's likely, I haven't bothered to
> >> check it myself, and the fact is it could be
> >> implementation-dependent), but it does seem to me that the docs
> >> don't promise that even if it's true now, it always will be true.

> >
> > I don't think it matters as long as the Observer respects the
> > order/thread warning above. In particular, my proposed Observer's
> > update(Observable, Object) method ends with repaint(). The hidden
> > assumption is that repaint() must be invoked from a JComponent,
> > which uses the RepaintManager to run from the EDT:
> >
> > <http://java.sun.com/products/jfc/tsc...g/index.html#p
> > aint_ process>

>
> Unfortunately, the documentation is not clear as to whether repaint()
> can be called from a thread other than the EDT. Just because it
> queues a Runnable to the EDT, that doesn't necessarily mean that it
> doesn't itself need to be also called from the EDT.


Well, the article claims "JComponent.repaint() registers an asynchronous
repaint request to the component's RepaintManager, which uses
invokeLater() to queue a Runnable," which is precisely the approach you
proposed earlier.

> More significantly, even if repaint() is legal to be called from any
> thread, not just the EDT, in presenting a code example we should be
> VERY explicit that we are relying on that specific behavior. Other
> interactions with a component (AWT or Swing) could easily still be
> required to be done on the EDT, even if the repaint() method need not
> be (and to be clear: I remain unconvinced that the documentation
> promises that to be true).
>
> A naïve reader of the code example might incorrectly extrapolate from
> the lack of special handling for repaint() that no special handling
> is needed generally.


I agree. The scheme relies on repainting JComponents, and then only if
the SDN article is dispositive. It's a hidden assumption that I should
document.

> >> > but I'm not sure that is required. More importantly, the
> >> > Observer is running on the EDT, as it extends an AWT Component.
> >>
> >> It depends on what you mean by "is running on the EDT". It's true
> >> that your Observer-implementing class is a Swing (not just AWT)
> >> component. But that doesn't guarantee that code in that class is
> >> run on the EDT. In fact, that's the whole issue: it _is_ a Swing
> >> component and so when you execute Swing-dependent code in the
> >> class, you have to go out of your way to ensure that happens on
> >> the EDT.

> >
> > Good point! I should have said JComponent.

>
> That's not what I am talking about. Whether you're talking Swing or
> EDT, you need to make sure you are making calls to the component on
> the EDT.


I agree. The Observer's update() method should defer drawing, but it can
get interim results and update component data models, e.g. a
BufferedImage or a TableModel. It then calls repaint() to schedule the
screen update on the EDT.

> >> If that's what you meant, then yes...I agree. But if your statement was
> >> intended to mean that because you've sub-classed JFrame, you're assured
> >> that calls to your sub-class are always on the EDT, that would be wrong.

> >
> > Yes, for JFrame. I proposed JPanel, which is a JComponent, but your
> > point is well taken.

>
> Again, for what I'm talking about, whether you are using JFrame or JPanel
> doesn't matter. You still have the same "must be on EDT" requirement.
>
> >> > The javax.swing.Timer I proposed runs on a separate thread; only
> >> > it's action handler executes on the EDT. One _could_ put drawing
> >> > code in the handler, but sending a notification instead keeps the
> >> > model and view separate. I thinka java.util.Timer would do as well.
> >>
> >> See above. I agree that the Timer Action event is raised on the EDT,
> >> but that doesn't necessarily guarantee that the Observer's update()
> >> method is called on the EDT. There's a missing link between your
> >> actionPerformed() method being called, and the Observer's update()
> >> method being called that involves ambiguously defined behavior on
> >> the part of the Java run-time.

> >
> > As long as the Observer's update() repaints a lightweight container, I
> > don't think it matters if the notification doesn't come from the EDT.

>
> Well, I haven't seen any documentation that promises that. It could be
> true, but I have no reason at the moment to believe that. But again, the
> repaint() method is a very specific method; there is no general promise
> that when interacting with an AWT or Swing component from the Observer's
> update() method, it doesn't matter if the notification doesn't come from
> the EDT. In many other scenarios, it definitely would matter.
>
> Even if we grant that repaint() has special rules (and again, I'm not
> convinced we should), the more general rule still needs to be followed for
> other kinds of calls to the component. Presumably, if you're updating the
> GUI, you will in fact find such calls, and they will need to be executed
> on the EDT.


I welcome your skepticism, but the documentation for Component.repaint()
makes repeated reference to the SDN article, and the article mentions
calling paint() from the EDT as step one for both AWT and Swing
components.

> > [...]
> >> Note, however, that the more likely that an algorithm is
> >> specifically in need of a timer-based approach, the more complex
> >> the synchronization mechanism will have to be (i.e. just copying
> >> immutable results to a volatile variable won't do, since if you
> >> could do that, it'd imply that you do in fact have predictable
> >> update points ).

> >
> > Don't similar synchronization problems attend to using the invoke*
> > utilities?

>
> I don't really know what you mean here. By design, invokeLater() and
> invokeAndWait() address synchronization issues related specifically
> to those methods.


I see the run() method getting called from the EDT, but with no special
synchronization, other than being added to the end of the queue.

> The code being invoked does need to deal with synchronization,
> possibly. But when I write code like this, typically the only data
> being used in the invoked code is the bare minimum data required to
> update the GUI. In particular, the extraction of the relevant
> information from my model has already been done, on the same thread
> that's processing the model, and copied to some specific place used
> by the invoked code (sometimes this is as simple as a "final" local
> variable used in an anonymous class).
>
> In this paradigm, because only one thread is ever actually using the
> model itself (the processing thread for the model), no
> synchronization issues exist with respect to the model, and the
> invoke*() methods automatically deal with synchronization issues
> that may exist with respect to the component itself.


Is the model also running on the EDT?

> As I said, I'm not sure I understand your question. But my first
> impression of what you're asking leads me to answer "no, similar
> problems do not exist".


I appreciate your patience helping me vet the approach. It's immensely
helpful in understanding it's limitations.

--
John B. Matthews
trashgod at gmail dot com
home dot woh dot rr dot com slash jbmatthews
 
Reply With Quote
 
John B. Matthews
Guest
Posts: n/a
 
      07-02-2008
In article <(E-Mail Removed)>,
Lew <(E-Mail Removed)> wrote:

> John B. Matthews wrote:
> > Yes, the SDN article is referenced in Component, and perhaps elsewhere.

>
> I finally figured that out, after spending some quality time with the
> Javadocs.
>
> It doesn't help that some of that outrigger documentation has been
> superseded,
> but the docs don't reflect the new knowledge.
>
> >>> ... there are stochastic models where no synchronization at
> >>> all gives satisfactory results.

>
> Lew wrote:
> >> How do variable values communicate across threads in that case?
> >>
> >> Or by "stochastic" do you mean that it doesn't matter, because the
> >> results are intended to be random?

>
> John:
> > Yes, the results evolve in apparent random order: many kinds of
> > fractals; diffusion limited aggregation, which has a fractal character;
> > any iteration over a set of lattice points in which you don't care that
> > some points are from iteration n-1 and some from iteration n.

>
> But without synchronization, the display thread might only see
> iteration zero forever.


In practice I haven't seen this. The model, an Observable, executes the
view's update(Observable Object) method, and the view either asks the
model for data or receives it as a parameter. For some models, the data
may be no more than a reference to an array of primitive types, which
the model continues to update even as the view accesses it to compose,
for example, a BufferedImage.

> >> I really do wonder how one handles the memory-model concerns in
> >> that "stochastic models" scenario. Would you be so gracious as to
> >> explain?

>
> > My point was only that sometimes it doesn't matter if the model is
> > changing under you. When it matters, you have to synchronize
> > access, of

>
> But don't model changes by very necessity have to be communicated
> somewhere, eventually? Absent synchronization, either via the
> 'synchronized' keyword or via any of the several other mechanisms
> that Java provides, there is no guarantee in the memory model that
> those changes would ever escape to another thread that needs them.


I can see this for more complex, non-thread-safe data structures. I
imagine a Vector, which is synchronized, or one of the
Collections.synchronized[Collection|List|Map|etc.] would do as well.

> And if another thread doesn't need them, then it's not a
> multithreaded scenario.
>
> I'm not sure failing to communicate model state actually contributes
> to the stochasticism.


Yes, the model is intended to be stochastic, not factitious

> > Sorry if I seemed to be arguing to the contrary.

>
> You are not.
>
> > Oh, and I hope I am always gracious!

>
> You are so.


--
John B. Matthews
trashgod at gmail dot com
home dot woh dot rr dot com slash jbmatthews
 
Reply With Quote
 
John B. Matthews
Guest
Posts: n/a
 
      07-02-2008
In article <(E-Mail Removed)>,
"Peter Duniho" <(E-Mail Removed)> wrote:

> On Tue, 01 Jul 2008 22:07:16 -0700, John B. Matthews <(E-Mail Removed)>
> wrote:
>
> > [...]
> >> > but I read the paragraph about notification order as a warning
> >> > to Observers that an Observable may change the order and thread.
> >>
> >> Yes, it may. And IMHO this can include the base Observable class.

> >
> > I must demur: "The default implementation provided in the
> > Observable class will notify Observers in the order in which they
> > registered interest..." tells me that order is preserved if my
> > subclass doesn't change it. If I do change it, Observers must
> > accept that.

>
> Nothing I wrote has anything to do with the _order_ in which
> observers are notified.


Ah, I misunderstood. I thought you were saying that the base Observable
class might change the order, when the documentation says the opposite.
I understand that subclasses may do so.

> > The phrases "...this notification mechanism is has nothing to do
> > with threads..." and "Each observer has its update method
> > called..." tell me that my subclass will execute the update()
> > method of a registered Observer even if they're in different
> > threads, and Observers have to accept what that implies.

>
> What you wrote supports my point. Yet, you seem to be including it
> with the intent to refute my point.
>
> I can only conclude that either you misunderstand my point, or you
> misunderstand the implications of "will execute the update() method
> of a registered Observer even if they're in different threads".


Yes, I misunderstood your point.

> On a slight tangent: it's not really clear from the above quote that
> you understand an important point about threading. Specifically, an
> _object_ is not on a specific thread. The _execution_ of some code
> is on a specific thread. A given class can have code that is
> executed on arbitrarily many threads. There is no connection
> between a given object and a given thread, except whatever
> connection is part of the actual explicit implementation.
>
> If you're confused about this, that could explain some of the
> disconnect here.


Of course, I don't know what I don't know, but I think I understand
Lew helpfully pointed out my ambiguous antecedent, so let me restate:

Starting a new thread for a Runnable [e.g. new Thread((Runnable)
scanner).start()] causes the Runnable's run() method to begin executing
on a new thread. Invoking notifyObservers() causes the registered
Observer's update() method to execute on that same thread, even though
other methods in the Observable may be executing on another thread. In
particular, an Observable that extends JPanel (or some other top-level
container) may have (at most) one method executing on the EDT.

I think this is the genesis of your welcomed criticism of my approach.

> > [...]
> >> Unfortunately, the documentation is not clear as to whether
> >> repaint() can be called from a thread other than the EDT. Just
> >> because it queues a Runnable to the EDT, that doesn't necessarily
> >> mean that it doesn't itself need to be also called from the EDT.

> >
> > Well, the article claims "JComponent.repaint() registers an
> > asynchronous repaint request to the component's RepaintManager,
> > which uses invokeLater() to queue a Runnable," which is precisely
> > the approach you proposed earlier.

>
> No, it's not.
>
> To be clear: Lew has helped by pointing out _some_ documentation
> (such as it is) that explains that the repaint() method can be
> successfully called from a thread other than the EDT thread. So
> we've got that point out of the way.
>
> But, the approach I proposed has nothing to do with whether the
> _painting_ of the control is done on the EDT or not (and in fact, I
> take as granted that it is, whatever else the implementation may be,
> since that's a requirement of AWT and Swing).
>
> So, the fact that when you call repaint(), that ultimately queues a
> Runnable to the event queue that will eventually do the actual
> repainting of the controls has absolutely nothing to do with how
> data is synchronized between the processing thread and the GUI (EDT)
> thread.


I agree.

> >> More significantly, even if repaint() is legal to be called from any
> >> thread, not just the EDT, in presenting a code example we should be
> >> VERY explicit that we are relying on that specific behavior. Other
> >> interactions with a component (AWT or Swing) could easily still be
> >> required to be done on the EDT, even if the repaint() method need not
> >> be (and to be clear: I remain unconvinced that the documentation
> >> promises that to be true).
> >>
> >> A naïve reader of the code example might incorrectly extrapolate from
> >> the lack of special handling for repaint() that no special handling
> >> is needed generally.

> >
> > I agree. The scheme relies on repainting JComponents, and then only if
> > the SDN article is dispositive. It's a hidden assumption that I should
> > document.

>
> Well, more importantly, you gloss over the real work: actually taking the
> model data and using it to update the GUI. The repaint() method itself
> doesn't do anything except actually redraw the GUI. For that to be a
> useful operation, you have to first _change_ the GUI so that when it
> redraws, the state of the GUI is actually different, reflecting the
> current state of processing.
>
> So yes, while the lack of a guarantee that the update() method is called
> on the EDT doesn't hurt us with respect to calling repaint() (sort
> of...see * below), it certainly would if you actually meant to _do_
> anything with the GUI that presents the current state of processing.
>
> (*) Note my comments in my reply to Lew regarding the thread safety of
> calling repaint(). The docs do explain that you can call repaint() from a
> thread other than the EDT. But they also say that any method that's
> thread-safe will specifically say so, and repaint() doesn't say so. This
> means that while it's legal to call repaint() from a non-EDT thread, you
> are still required to address synchronization yourself, since repaint()
> isn't a thread-safe method.
>
> In other words, you're really only safe calling repaint() in one respect.
> There's another, arguably more important respect, in which calling it from
> another thread without synchronization is _not_ safe.


Permit me to defer comment to that part of the thread.

> > [...]
> >> That's not what I am talking about. Whether you're talking Swing or
> >> EDT, you need to make sure you are making calls to the component on
> >> the EDT.

> >
> > I agree. The Observer's update() method should defer drawing,

>
> It does, by virtue of the repaint() method deferring actual drawing.
>
> > but it can
> > get interim results and update component data models, e.g. a
> > BufferedImage or a TableModel. It then calls repaint() to schedule the
> > screen update on the EDT.

>
> But those "component data models" need to be synchronized. If you are not
> executing your code on the EDT, then they may be being used by code
> running on the EDT at the same time you are modifying them. And that's on
> top of the fact that Swing does not automatically handle cross-thread
> updates to data models for GUI components.
>
> For example (from
> http://java.sun.com/javase/6/docs/ap...y.html#threadi
> ng):
>
> ...if a TableModel is attached to a JTable, the TableModel
> should only be modified on the event dispatching thread.
> If you modify the model on a separate thread you run the
> risk of exceptions and possible display corruption
>
> Conversely, if you _are_ executing your code on the EDT, then the data
> model from which you're getting your actual information (that is, the
> processing thread's model data structure) is what needs to be synchronized.
>
> The bottom line is that you have a processing thread that's generating
> data, but you can only display data on the EDT, which is by definition
> going to be a different thread from the processing thread. You _must_
> address synchronization of those threads any time you want data to flow
> from one thread to the other. And the only way to present the results of
> the processing (interim results or otherwise) to the user is to have data
> flow from one thread to the other.
>
> On top of all this, the Observable class doesn't give us any assurance
> that Observer implementers are going to be called on the same thread on
> which Observable.notifyObservers() is called. So your Observer
> implementer cannot make the assumption that it's update() method is called
> on the EDT, even if you call notifyObservers() on the EDT.
>
> And finally (to conclude this particular logical progression), since your
> Observer implementation cannot make the assumption that its update()
> method is called on the EDT, it must itself explicitly ensure that any
> interaction it has with Swing is done on the EDT, except possibly for
> things that are explicitly documented as not needing that (in this case,
> that would be the repaint() method, but not any of the other things you
> might do in order to update the GUI).


These point are well taken, and thank you for pointing out the
TableModel caveat. I've been modifying a BufferedImage's
WriteableRaster, so any problems may have been more in-apparent than
impossible.

> > [...]
> >> Even if we grant that repaint() has special rules (and again, I'm not
> >> convinced we should), the more general rule still needs to be followed
> >> for
> >> other kinds of calls to the component. Presumably, if you're updating
> >> the
> >> GUI, you will in fact find such calls, and they will need to be executed
> >> on the EDT.

> >
> > I welcome your skepticism, but the documentation for Component.repaint()
> > makes repeated reference to the SDN article, and the article mentions
> > calling paint() from the EDT as step one for both AWT and Swing
> > components.

>
> As I noted above, I concede the point that repaint() itself may be called
> from a thread other than the EDT. However, please note:
>
> -- that doesn't help with any of the other methods that you'll need to
> call in order to update the GUI, and
> -- since repaint() isn't documented as being thread-safe, you still
> have a synchronization issue even with that method
>
> >> > [...]
> >> >> Note, however, that the more likely that an algorithm is
> >> >> specifically in need of a timer-based approach, the more complex
> >> >> the synchronization mechanism will have to be (i.e. just copying
> >> >> immutable results to a volatile variable won't do, since if you
> >> >> could do that, it'd imply that you do in fact have predictable
> >> >> update points ).
> >> >
> >> > Don't similar synchronization problems attend to using the invoke*
> >> > utilities?
> >>
> >> I don't really know what you mean here. By design, invokeLater() and
> >> invokeAndWait() address synchronization issues related specifically
> >> to those methods.

> >
> > I see the run() method getting called from the EDT, but with no special
> > synchronization, other than being added to the end of the queue.

>
> You see which "run() method" getting called from the EDT? How _isn't_
> making sure some code is executed on the same thread as some other code
> not obviously synchronizing those two pieces of code?
>
> >> The code being invoked does need to deal with synchronization,
> >> possibly. But when I write code like this, typically the only data
> >> being used in the invoked code is the bare minimum data required to
> >> update the GUI. In particular, the extraction of the relevant
> >> information from my model has already been done, on the same thread
> >> that's processing the model, and copied to some specific place used
> >> by the invoked code (sometimes this is as simple as a "final" local
> >> variable used in an anonymous class).
> >>
> >> In this paradigm, because only one thread is ever actually using the
> >> model itself (the processing thread for the model), no
> >> synchronization issues exist with respect to the model, and the
> >> invoke*() methods automatically deal with synchronization issues
> >> that may exist with respect to the component itself.

> >
> > Is the model also running on the EDT?

>
> No, not the model I'm referring to. As I said, "only one thread is ever
> actually using the model itself (the processing thread for the model)".
> Since by definition, the processing thread is not the EDT, obviously the
> model is not "running on the EDT" (inasmuch as the model could be
> "running" on any thread...I wouldn't describe it that way, but rather as
> simply the _processing thread_ is what's "running", and it modifies the
> model as it runs; that's a bit of a semantic nit-pick though).


Yes, I confounded the model as a class with the model's run() method.

On reflection, I see the clear contract the invokeLater() and
invokeAndWait() methods offer with respect to the EDT, and my approach
may have too many limitations.

--
John B. Matthews
trashgod at gmail dot com
home dot woh dot rr dot com slash jbmatthews
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Force Refresh / Repaint of Page Control in Design Mode (IDE) ?? philaphan80@yahoo.com ASP .Net 0 06-01-2007 02:23 PM
Runtime.exec() and a repaint problem with JEditorPane Steve Sobol Java 0 01-10-2006 03:54 AM
Repaint method Robert Javascript 2 12-16-2005 11:02 AM
Help with repaint() and init()... michael.rygh@gmail.com Java 2 12-12-2005 10:49 PM
differences among validate(), revalidate() and repaint() ? Abs Java 0 05-24-2004 02:48 PM



Advertisments