mbien commented on code in PR #6514:
URL: https://github.com/apache/netbeans/pull/6514#discussion_r1346903220
##########
java/maven/src/org/netbeans/modules/maven/NbMavenProjectImpl.java:
##########
@@ -559,29 +587,123 @@ void stopHardReferencingMavenPoject() {
return newproject;
}
+ /**
+ * Task that potential project reloads should wait on. If set, a {@link
fireProjectReload}(true) will be scheduled only after this blocker finishes.
+ */
+ private RequestProcessor.Task reloadBlocker;
-
+ /**
+ * Schedules project operation that delays potential reloads. If a reload
is posted, it will be performed only after
+ * this operation compeltes (successfully, or erroneously). Multiple
project operations can be scheduled, an eventual project reload
+ * should happen after all those operations complete. It is possible to
postpone project reload indefinitely, avoid unnecessary
+ * operation schedules.
+ *
+ * @param r operation to run
+ * @return controlling task.
+ */
+ public RequestProcessor.Task
scheduleProjectOperation(RequestProcessor.Task t) {
+ if (Boolean.getBoolean("test.reload.sync")) {
+ LOG.log(Level.FINE, "Running the blocking task synchronously
(test.reload.sync set)");
+ t.run();
+ return t;
+ } else {
+ synchronized (this) {
+ if (reloadBlocker == null) {
+ LOG.log(Level.FINER, "Blocking project reload on task
{0}", t);
+ reloadBlocker = t;
+ return t;
+ } else {
Review Comment:
this looks a bit dangerous, the task is already running when passed into
this method, which means that there is a point in time when the task is active
without being marked as blocker.
```
((NbMavenProjectImpl)this.nbproject).scheduleProjectOperation(MavenModelProblemsProvider.RP.post(toRet));
```
Should this method have a RP param and actually schedule the tasks _inside_
the method? (+ throw exception when the task is already running).
##########
java/maven/src/org/netbeans/modules/maven/NbMavenProjectImpl.java:
##########
@@ -559,29 +587,123 @@ void stopHardReferencingMavenPoject() {
return newproject;
}
+ /**
+ * Task that potential project reloads should wait on. If set, a {@link
fireProjectReload}(true) will be scheduled only after this blocker finishes.
+ */
+ private RequestProcessor.Task reloadBlocker;
-
+ /**
+ * Schedules project operation that delays potential reloads. If a reload
is posted, it will be performed only after
+ * this operation compeltes (successfully, or erroneously). Multiple
project operations can be scheduled, an eventual project reload
+ * should happen after all those operations complete. It is possible to
postpone project reload indefinitely, avoid unnecessary
+ * operation schedules.
+ *
+ * @param r operation to run
+ * @return controlling task.
+ */
+ public RequestProcessor.Task
scheduleProjectOperation(RequestProcessor.Task t) {
+ if (Boolean.getBoolean("test.reload.sync")) {
+ LOG.log(Level.FINE, "Running the blocking task synchronously
(test.reload.sync set)");
+ t.run();
+ return t;
+ } else {
+ synchronized (this) {
+ if (reloadBlocker == null) {
+ LOG.log(Level.FINER, "Blocking project reload on task
{0}", t);
+ reloadBlocker = t;
+ return t;
+ } else {
+ // will chain after existing reload blocker AND the new
task.
+ final RequestProcessor.Task t2 = RELOAD_RP.create(() ->
{});
+ LOG.log(Level.FINER, "Creating project blocker {0}, chain
after existing blocker {1}", new Object[] { t2, t });
+ reloadBlocker.addTaskListener((e) -> {
+ t.addTaskListener((e2) -> {
+ synchronized (NbMavenProjectImpl.this) {
+ if (t2 == reloadBlocker) {
+ reloadBlocker = null;
+ }
+ }
+ t2.run();
+ });
+ });
+ reloadBlocker = t2;
+ return t2;
+ }
+ }
+ }
+ }
+
public RequestProcessor.Task fireProjectReload() {
+ return fireProjectReload(false);
+ }
+
+ /**
+ * Schedules project reload. If `waitForBlockers` is true and {@link
#scheduleProjectOperation} registered some task(s), project reload
+ * will be postponed until after those task(s) finish. The returned task
completes after the project reload itself completes (after the potential
+ * delays).
+ * <p>
+ * As a result of project's reload, child projects may be reloaded, but
the returned task does not wait for children reload to complete.
+ *
+ * @param waitForBlockers
+ * @return the task that completes after project reloads.
+ */
+ public RequestProcessor.Task fireProjectReload(boolean waitForBlockers) {
//#227101 not only AWT and project read/write mutex has to be checked,
there are some additional more
//complex scenarios that can lead to deadlock. Just give up and always
fire changes in separate RP.
if (Boolean.getBoolean("test.reload.sync")) {
reloadTask.run();
//for tests just do sync reload, even though silly, even sillier
is to attempt to sync the threads..
} else {
+ RequestProcessor.Task t;
+ synchronized (this) {
+ if (reloadBlocker != null && waitForBlockers) {
+ // avoid holding the lock while potentially executing the
listener in-line
+ t = reloadBlocker;
+ } else {
+ t = null;
+ }
+ }
+ if (t != null) {
+ final RequestProcessor.Task t2 = RELOAD_RP.create(() -> {});
+ LOG.log(Level.FINER, "Scheduling project reload retry after
blocker {0} completes, Returning task {1}", new Object[] { t, t2 });
+ t.addTaskListener((e) -> {
+ synchronized (NbMavenProjectImpl.this) {
+ if (t == reloadBlocker) {
+ reloadBlocker = null;
+ }
+ }
+ fireProjectReload(true).addTaskListener((e2) -> {
+ // mark the t2 task finished.
+ if (!t2.isFinished()) {
+ t2.run();
+ }
+ });
+ });
+ return t2;
+ }
+ LOG.log(Level.FINER, "Scheduling prject reload {0}, no blocker
found.", this);
+ LOG.log(Level.FINER, "Stack trace:", new Throwable());
Review Comment:
potentially worth adding a `if (loggable)` check since stacks are likely not
populated lazily
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists