Update of /cvsroot/freenet/freenet/src/freenet/thread
In directory sc8-pr-cvs1:/tmp/cvs-serv9418
Modified Files:
QThreadFactory.java
Log Message:
Minor changes, theoretical bug fix.
If there were very few active threads,
it used to delete threads below 2*absoluteminimum.
getThread was missing a synchronize(thread), which
was the reason we needed that timed wait which
was deleted last revision.
Index: QThreadFactory.java
===================================================================
RCS file: /cvsroot/freenet/freenet/src/freenet/thread/QThreadFactory.java,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -r1.40 -r1.41
--- QThreadFactory.java 10 Oct 2003 19:15:36 -0000 1.40
+++ QThreadFactory.java 14 Oct 2003 16:38:34 -0000 1.41
@@ -86,8 +86,9 @@
doLog = false;
int allowed;
countLock.snap(snap);
- // start with a maximal allowed value.
- allowed = Math.max((int)(snap.active *
MAXIMUM_AVAILABLE_RATIO),2 * MINIMUM_AVAILABLE_ABS);
+ // Start with a maximal allowed value.
+ allowed = Math.max((int)(snap.active *
MAXIMUM_AVAILABLE_RATIO),
+ 2 *
MINIMUM_AVAILABLE_ABS);
// Repeatedly remove a thread from the stack and
signal it to die.
// But if all of the threads have meanwhile started
jobs, then
// do nothing, and the loop will terminate with
snap.available == 0
@@ -98,11 +99,14 @@
// but it can never make
headLock.pop() be null.
headLock.pop().die();
}
- // Let there be up to maximum threads sitting
- // around, I think this will reduce thread flux
- // a lot which should help CPU usage further
+ // Let there be up to relative maximum threads
+ // sitting around. This will reduce thread flux a
+ // lot which should help CPU usage further. But
+ // don't let it go below 2 * absolute minimum.
allowed =
- Math.max((int) (snap.active *
MAXIMUM_AVAILABLE_RATIO), allowed);
+ Math.max((int) (snap.active *
MAXIMUM_AVAILABLE_RATIO),
+ Math.max(allowed, //
allowed must not decrease.
+ 2 *
MINIMUM_AVAILABLE_ABS));
}
if (logDEBUG && doLog)
Core.logger.log(this,"Thread creation thread
past destruction loop" +
@@ -169,9 +173,13 @@
} else {
thread = headLock.pop(); // thread cannot be null.
}
- thread.next = null;
- thread.job = job;
- thread.start();
+ // synchronize so that getThread can't sneak in between
+ // test for job == null and this.wait() in thread.run().
+ synchronized (thread) {
+ thread.next = null;
+ thread.job = job;
+ thread.notify();
+ }
countLock.mightNotify();
return thread;
@@ -196,19 +204,24 @@
return job;
}
- public final synchronized void start() {
- this.notify();
- }
-
public final void run() {
while (alive.state()) {
synchronized (this) {
while (alive.state() && job == null) {
+ // If getThread didn't synchronize
(thread),
+ // it could sneak in here and change
job and
+ // issue it's notify after the test
but before
+ // the wait.
try {
- //There is no need to timeout this wait, getThread()
- //is the only way to get a thread, and it does
- //thread.start() which will awaken the thread, and
- //thread.die() also awakens the thread.
+ // There is no need to timeout this wait,
+ // so long as getThread()
synchronizes.
+ // getThread() is the only way
to get a
+ // thread. It synchronizes
(thread), then
+ // changes thread.job, and
only then does
+ // thread.notify().
thread.die() also
+ // synchronizes, then changes
+ // alive.state(), and only
then does
+ // thread.notify().
this.wait();
}
catch (InterruptedException e) {}
@@ -310,17 +323,21 @@
// thread hasn't been removed yet.
private int available = 0;
+ // take a snapshot
synchronized void snap(CountSnap snap) {
snap.active = active;
snap.available = available;
}
+ // free a thread, then take a snapshot.
synchronized void snapFree(CountSnap snap) {
available++; // thread was already pushed onto stack.
snap.active = active;
snap.available = available;
}
+ // maybe take a thread, then take a snapshot.
+ // return true if got a thread.
synchronized boolean snapTake(CountSnap snap) {
boolean gotOne = false;
if (available >= 1) { // There is at least one on stack.
_______________________________________________
cvs mailing list
[EMAIL PROTECTED]
http://dodo.freenetproject.org/cgi-bin/mailman/listinfo/cvs