Re: concurrency and starting a synchronized block

2005-02-10 Thread WHIRLYCOTT
I spent a whole bunch of time looking into how various 
caches/collections handled this issue when I was designing Whirlycache 
[1] and the cleanest solution that is available today, as others have 
pointed out, is Doug Lea's util.concurrent package.

The high-level explanation of how Doug Lea's ConcurrentHashMap works is 
that it has 32 internal buckets and a fast hashing algorithm.  It only 
synchronizes internally on the bucket that is being modified, thereby 
leaving the other n buckets free to do whatever they need.  So you can 
conceivably have 32 concurrent threads reading and/or writing depending 
on how the hashing algorithm causes the buckets to be synchronized.

It's a lot faster than a java.util.HashMap when you have many threads 
reading and writing.

I think the 32 fixed bucket size limit was removed when these classes 
were ported to JDK 1.5.

Depending on what you are doing, you basically have 3 choices when 
you're dealing with multithreaded access/modification to a collection:

1) don't synchronize and watch failures happen
2) synchronize on the containing object's monitor:
...
public synchronized whatever(Object arg1) {...}
public synchronized something() {...}
...
3) use more granular synch locks, if possible:
...
private Object whatever = new Object();
private Object something = new Object();
public whatever(Object arg1) {
  synchronized (whatever) {
...
  }
}
public something(Object arg1) {
  synchronized (something) {
...
  }
}
Making the locks more granular can make a huge difference, but it's only 
possible if your particular case will allow for it.  But it's definitely 
worth investigating rather than blindly using 'synchronized' in method 
signatures... which turns out to be not-that-slow anyway.

YMMV.
phil.
[1] http://whirlycache.dev.java.net/
Torsten Curdt wrote:
Guys, forgive me if this too off topic...
...but I thought it is somehow related to
collections that's why I am bringing it up
here anyway. I bet someone of you will know
Consider this code...
 Object o = map.get(key);
 if (o == null) {
   synchronized(map) {
 map.put(key,new Object());
   }
 }
99% of the time the gets on the map are going
to return an object. That's why I would like
to avoid synchronizing the get access.
Now since a put might corrupt the data it
has to be synchronized.
Since the get, the comparison and the put
are not in a synchronized block I might loose
objects ...but for this particular usecase
that's ok.
Now what really got me thinking is the
concurrent sychronized and non-synchronized
access.
What happens when Thread A is in doing a
get while Thread B is entering the
sychronized block for the put?
I assume that since the map object is not
locked it will go straight into the put
and bang ...right?
Somehow this looks like the optimal usecase
for the FastHashMap from collections ...but
since this code needs to be very portable
this might be a problem because of the
double-checked locking idiom.
Another option would be using the StaticBucketMap.
What do you guys think?
If you consider this too OT please reply off list.
cheers
--
Torsten
--
  Whirlycott
  Philip Jacob
  [EMAIL PROTECTED]
  http://www.whirlycott.com/phil/
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: concurrency and starting a synchronized block

2005-02-10 Thread WHIRLYCOTT
Exactly - most books and documentation about resource exclusion about 
this make it abundantly clear that synchronized methods shouldn't call 
each other for this very reason.

Thanks for adding that point.
phil.
Oliver Zeigermann wrote:
On Thu, 10 Feb 2005 13:09:14 -0500, WHIRLYCOTT [EMAIL PROTECTED] wrote:
2) synchronize on the containing object's monitor:
   ...
   public synchronized whatever(Object arg1) {...}
   public synchronized something() {...}
   ...

Blindly doing this can easily lead to deadlocks. Consider thread #1 in
method whatever accesses another synchronized object and needs to wait
for thread #2 to release the lock on it. Now thread #2 tries to access
method something and - of course - needs to wait for thread #1 to
release the lock on that first objec. Now both threads mutually wait
for each other and you have a deadlock.
Oliver
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
--
  Whirlycott
  Philip Jacob
  [EMAIL PROTECTED]
  http://www.whirlycott.com/phil/
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: concurrency and starting a synchronized block

2005-02-10 Thread WHIRLYCOTT
I guess this thread should end soon, but while we're still having some 
fun ... ;)

ConcurrentHashMap can do concurrent put() operations and concurrent 
get() operations... and that's the tricky part.

I just love all that stuff that Doug Lea has done.  For those who 
haven't looked at util.concurrent, I recommend it.  Sounds like others 
do as well.

phil.
Kevin A. Burton wrote:
Torsten Curdt wrote:
Guys, forgive me if this too off topic...
...but I thought it is somehow related to
collections that's why I am bringing it up
here anyway. I bet someone of you will know

Ignore what everyone else says on this list topic.  ha.
Use a ReentrantReadWriteLock from JDK 1.5.  There's a backport to JDK 
1.4 out on the net. Google for backport concurrent oswego or something

Then you can do a
   lock.readLock().lock()
on our gets and then do a writeLock on your puts.  the writeLock will 
backup the readlock but if you only have readlocks they can all happen 
at once.

Normally though its not too big a deal since gets() on a hashtable are 
O(1)

Kevin
--
  Whirlycott
  Philip Jacob
  [EMAIL PROTECTED]
  http://www.whirlycott.com/phil/
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: concurrency and starting a synchronized block

2005-02-10 Thread WHIRLYCOTT
There's also the original version here:
http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html
What does the backport offer that the original util.concurrent lib 
doesn't offer?

phil.
Kevin A. Burton wrote:
WHIRLYCOTT wrote:
I guess this thread should end soon, but while we're still having some 
fun ... ;)

ConcurrentHashMap can do concurrent put() operations and concurrent 
get() operations... and that's the tricky part.

I just love all that stuff that Doug Lea has done.  For those who 
haven't looked at util.concurrent, I recommend it.  Sounds like others 
do as well.

I know... its good stuff.  I blogged about it:
http://www.peerfear.org/rss/permalink/2004/12/19/TheJavaUtilConcurrentPackageAndThreadConcurrency/ 

All the fun toys that are available ;)
Kevin
--
  Whirlycott
  Philip Jacob
  [EMAIL PROTECTED]
  http://www.whirlycott.com/phil/
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: svn commit: r149313 - in jakarta/commons/sandbox/javaflow/trunk/src: java/org/apache/commons/javaflow/ java/org/apache/commons/javaflow/bytecode/bcel/ test/org/apache/commons/javaflow/ test/org/apache/commons/javaflow/testcode/

2005-02-01 Thread WHIRLYCOTT
Torsten Curdt wrote:
Well, the point is that the file writing code is
temporary anyway. I should go away in the near future.
That's why fixing it is not that important.
Yes, I was going to ask about that one... can you let me in on your 
plans for this?  I agree that it should go away, but I haven't spent any 
time rethinking this.

Btw: for some reason I've some problem applying
your patches with eclipse :-/ ...most of the
hunks are not being found.
How goofy.  The subclipse client isn't as painfree as the cvs one from 
what I can tell.  The team synchronizing perspective occasionally 
indicates to me that there differences between local and remote when 
there are none.  I'm not sure what could cause this... will investigate.

phil.
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: [javaflow] test cases in junit?

2005-01-31 Thread WHIRLYCOTT
Torsten Curdt wrote:

* I added a ContinuationException class that can be thrown to clients
using this code instead of stuff like
java.lang.reflect.InvocationTargetException that is dependent on the
underlying bytecode toolkit.

That class was missing in your patch.
Besides I am wondering what you mean
by dependand on the bytecode toolkit?!
There was a note in TODO about investigating using ASM instead of BCEL. 
 Without even looking in detail at ASM, my guess is that it will throw 
different exceptions than BCEL when manipulating the bytecode, etc.  My 
idea was that we could throw a ContinuationException instead of the 
underlying FooException that either BCEL or ASM uses to insulate any 
calling classes from having to change in the event of a switch from BCEL 
to ASM.

Please have a look into the one I've
committed. Continueing from the very
same continuation is totally ok!
Keep the tree of continuations in mind!
Ok, thanks for correcting me.

* In the TODO file, you mention something about removing the Continuable
and ContinuationCapable marker interfaces.  Can you please elaborate on
the reasons behind that?

The Continuable marks classes that should be
rewritten. The ContinuationCapable mark classes
that have been rewritten. IMO this can all go
away.
We could define that on a package scope. E.g.
via regexp.
Going for a decend callflow analyses would even
figure out the needed rewrites by itself. Might
be some work though...
I think I understand the reason why both of these interfaces exist. 
However, if the intent is to be able to use Continuation.suspend() 
within any class without having to implement Continuable on that class, 
then maybe just do away with Continuable and keep ContinuationCapable as 
the marker for that class after it has been rewritten.

What benefit does the regex approach provide?  Callflow analyses seems 
like it could be messy.  And I think just tagging the rewritten class 
with this interface is pretty transparent, no?

phil.
--
  Whirlycott
  Philip Jacob
  [EMAIL PROTECTED]
  http://www.whirlycott.com/phil/
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: svn commit: r149313 - in jakarta/commons/sandbox/javaflow/trunk/src: java/org/apache/commons/javaflow/ java/org/apache/commons/javaflow/bytecode/bcel/ test/org/apache/commons/javaflow/ test/org/apache/commons/javaflow/testcode/

2005-01-31 Thread WHIRLYCOTT
 thrown when a continuable class 
+ * is used incorrectly (i.e. without the ContinuationClassLoader).
+ * @throws Exception
+ */
+public void testIncorrectUsageWithNormalClassLoader() throws Exception {
+log.debug(Testing incorrect use of continuation...);
+boolean exceptionThrown = false;
+try {
+final Calculator c = new Calculator();
+c.main();
+} catch (final Exception e) {
+log.debug(Catching a  + e);
+assertTrue(e instanceof IllegalStateException);
+exceptionThrown = true;
+}
+assertTrue(exceptionThrown);
+}
+
+
+/**
  * The junit tests are preferred over running this main() method.
  * @param args
  * @throws Exception
@@ -89,5 +111,6 @@
 public static void main(final String[] args) throws Exception {
 final ContinuationClassLoaderTestCase t = new ContinuationClassLoaderTestCase();
 t.testCalculator();
+t.testIncorrectUsageWithNormalClassLoader();
 }
 }

Modified: jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/ContinuationCompilingClassLoaderTestCase.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/ContinuationCompilingClassLoaderTestCase.java?view=diffr1=149312r2=149313
==
--- jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/ContinuationCompilingClassLoaderTestCase.java (original)
+++ jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/ContinuationCompilingClassLoaderTestCase.java Mon Jan 31 14:53:31 2005
@@ -22,15 +22,19 @@
 import org.apache.commons.logging.LogFactory;
 import org.apache.jci.CompilingClassLoader;
 
+import junit.framework.TestCase;
+
 
 /**
  * @author tcurdt
  *
  */
-public final class ContinuationCompilingClassLoaderTestCase {
+public final class ContinuationCompilingClassLoaderTestCase extends TestCase {
+
 private final static Log log = LogFactory.getLog(ContinuationCompilingClassLoaderTestCase.class);
 
-private void testReloading() throws Exception {
+public void testReloading() throws Exception {
+/*
 final CompilingClassLoader cl = new ContinuationCompilingClassLoader(
 this.getClass().getClassLoader(),
 new File(/home/tcurdt/dev/jci/classes)
@@ -50,7 +54,7 @@
 
 Thread.sleep(2000);
 }
-
+  */  
 }
 
 public static void main(String[] args) throws Exception {

Modified: jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/testcode/Calculator.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/testcode/Calculator.java?view=diffr1=149312r2=149313
==
--- jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/testcode/Calculator.java (original)
+++ jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/testcode/Calculator.java Mon Jan 31 14:53:31 2005
@@ -28,18 +28,33 @@
  */
 public final class Calculator implements Continuable, Serializable {
 
-/**
- * Logger.
- */
 private static final Log log = LogFactory.getLog(Calculator.class);
+
+private int global = 0;
+private int local = 0;
 
 public void main() {
 
-log.debug(Calculator1);
+int l = 0;
+
+log.debug(Start of Calculator: g= + global +  l= + local);
+
+global++;
+local = ++l;
 
-Continuation.suspend();
+log.debug(Calculator Step 1: g= + global +  l= + local);
 
-log.debug(Calculator2);
+Continuation.suspend();
 
+log.debug(Calculator Step 2: g= + global +  l= + local);
+
+global++;
+local = ++l;
+
+log.debug(End of Calculator: g= + global +  l= + local);
+}
+
+public String toString() {
+return  + global + . + local;
 }
 }


-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
--
  Whirlycott
  Philip Jacob
  [EMAIL PROTECTED]
  http://www.whirlycott.com/phil/
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Re: [javaflow] test cases in junit?

2005-01-30 Thread WHIRLYCOTT
Ok, here's a start, anyway.
Some notes:
* The simplelog setup wasn't working at all for me for anything less 
than info, so I added log4j into the project.xml.  Works fine now.  Not 
sure if you were having a similar problem?  junit is also added to 
project.xml.

* There are some references to /home/tcurdt in .classpath.  I didn't 
touch them.  Does this even belong in svn?

* I added a ContinuationException class that can be thrown to clients 
using this code instead of stuff like 
java.lang.reflect.InvocationTargetException that is dependent on the 
underlying bytecode toolkit.

* Added some serialVersionUID fields to Serializable classes.
* The test case causes an exception to be thrown and tests for it, so be 
aware of that when you see the stacktrace in the output.

* In the TODO file, you mention something about removing the Continuable 
and ContinuationCapable marker interfaces.  Can you please elaborate on 
the reasons behind that?

Just starting off small for now - more soon.
phil.
Torsten Curdt wrote:
Any objections to receiving test cases using junit?

Phil, of course not! :)
...actually it was my plan using junit for that.
cheers
--
Torsten
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
--
  Whirlycott
  Philip Jacob
  [EMAIL PROTECTED]
  http://www.whirlycott.com/phil/
Index: C:/Documents and Settings/pjacob/My 
Documents/workspace/javaflow/.classpath
===
--- C:/Documents and Settings/pjacob/My Documents/workspace/javaflow/.classpath 
(revision 149125)
+++ C:/Documents and Settings/pjacob/My Documents/workspace/javaflow/.classpath 
(working copy)
@@ -8,5 +8,7 @@
classpathentry kind=var 
path=MAVEN_REPO/commons-logging/jars/commons-logging-api-1.0.4.jar/
classpathentry kind=var 
path=MAVEN_REPO/commons-logging/jars/commons-logging-1.0.4.jar/
classpathentry kind=var path=MAVEN_REPO/ant/jars/ant-1.5.3-1.jar/
+   classpathentry kind=var 
path=MAVEN_REPO/junit/jars/junit-3.8.1.jar/
+   classpathentry kind=var 
path=MAVEN_REPO/log4j/jars/log4j-1.2.8.jar/
classpathentry kind=output path=bin/
 /classpath
Index: C:/Documents and Settings/pjacob/My 
Documents/workspace/javaflow/project.xml
===
--- C:/Documents and Settings/pjacob/My 
Documents/workspace/javaflow/project.xml(revision 149125)
+++ C:/Documents and Settings/pjacob/My 
Documents/workspace/javaflow/project.xml(working copy)
@@ -68,6 +68,18 @@
  artifactIdant/artifactId
  version1.5.3-1/version
/dependency
+   
+   dependency
+ groupIdjunit/groupId
+ artifactIdjunit/artifactId
+ version3.8.1/version
+   /dependency
+   
+   dependency
+ groupIdlog4j/groupId
+ artifactIdlog4j/artifactId
+ version1.2.8/version
+   /dependency
 
   /dependencies
 /project
Index: C:/Documents and Settings/pjacob/My 
Documents/workspace/javaflow/src/test/org/apache/commons/javaflow/ContinuationClassLoaderTestCase.java
===
--- C:/Documents and Settings/pjacob/My 
Documents/workspace/javaflow/src/test/org/apache/commons/javaflow/ContinuationClassLoaderTestCase.java
  (revision 149125)
+++ C:/Documents and Settings/pjacob/My 
Documents/workspace/javaflow/src/test/org/apache/commons/javaflow/ContinuationClassLoaderTestCase.java
  (working copy)
@@ -18,6 +18,8 @@
 import java.lang.reflect.Method;
 import java.util.Map;
 
+import junit.framework.TestCase;
+
 import org.apache.commons.javaflow.utils.ReflectionUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -27,40 +29,70 @@
  * @author tcurdt
  *
  */
-public final class ContinuationClassLoaderTestCase {
+public final class ContinuationClassLoaderTestCase extends TestCase {
 
+/**
+ * Logger.
+ */
 private final static Log log = 
LogFactory.getLog(ContinuationClassLoaderTestCase.class);
 
-private void testCalculator() throws Exception {
+public void testCalculator() throws Exception {
+log.debug(Doing testCalculator());
+
+final String calculatorTestClass = 
org.apache.commons.javaflow.testcode.Calculator;
+
 final ClassLoader cl = new 
ContinuationClassLoader(getClass().getClassLoader());
-final Class clazz = 
cl.loadClass(org.apache.commons.javaflow.testcode.Calculator);
+final Class clazz = cl.loadClass(calculatorTestClass);
+assertNotNull(clazz);
  
-final Map m = ReflectionUtils.discoverMethods(clazz);
+//This map contains methods indexed by their names (Strings).
+final Map methods = ReflectionUtils.discoverMethods(clazz

[javaflow] test cases in junit?

2005-01-29 Thread WHIRLYCOTT
Torsten -
Any objections to receiving test cases using junit?
phil.
--
  Whirlycott
  Philip Jacob
  [EMAIL PROTECTED]
  http://www.whirlycott.com/phil/
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]