Programming with meta-data, an example for concurrency
November 1st, 2007 at 1:02 pm by Arjen van SchieAbout a month ago I obtained my master of science degree from the university of amsterdam after fulfilling a graduation assignment at LogicaCMGs Working Tomorrow graduation program. The subject of my research was concurrency and parallel programming for multi-core CPUs. The goal of this project was to find a partial solution for lowering the complexity of implementing concurrency in Java source-code. More about the importance of lower complexity and the role of multi-core for software development can be found here.
One of the accomplishments of this research (click here for the full thesis) was the insight to see concurrency as a form of meta-data for a method or module. For example, if a heavy calculation should be executed asynchronously, then the fact that it ’should run asynchronously’ is a property of that method and should therefore be separated from the implementation of the algorithm of the calculation.
Java by itself is not so powerful when it comes to meta-programming, but when combined with AspectJ some very interesting possibilities come to life. In my research assignment it was chosen to realize three concurrency concerns into a meta-data format with the use of annotations.
The following code examples will give a brief view on the differences between the normal approach and the meta-data approach.
java:

aspectj:

Both examples will do exactly the same, but in the AspectJ version the code related to concurrency is hidden behind the annotation (and implemented with AspectJ). This example clearly shows that the code for the functionality is clean and separated from the code for the implementation of concurrency..
This clean separation is also confirmed by a ‘case study’ with software metrics for modularity, encapsulation and complexity. As an example the implementation of these three concerns with meta-data, made it possible to shrink the implementation of Azureus Vuze with more then 10.000 lines of code and gave a big improvement on the Coupling Between Objects metric.
The conclusion of my research is that the implementation of concurrency in source-code is less complex when done with metaprogramming then with the normal object-oriented approach based on the software-metric case studies.
.
Note: Of course this approach of ‘concurrency as meta-data’ might not hold for all possible concurrency concerns, but for the ones investigated it did a good job and the concerns selected are pretty common among programs implementing concurrency.
Popularity: 311 points


November 1st, 2007 at 2:54 pm
Hi Arjan,
Using metadata for concurrent programming can be a way to reduce concurrency control related complexity. But just adding metadata for asynchronous calls probably is not enough:
1) you want to control the number of threads that are executing an asynchronous task. If this doesn’t happen, a system won’t degrade gracefully . And you don’t want to use a single ‘threadpool’ for all asynchronous calls, but probably a threadpool per method or per object that contains the asynchronous calls. Annotations could play a big part in some part of the confguration, but I guess you need some configuration in another location (the Spring applicationcontext is my preferred location for these environmental issues).
2) you want to control the number of unprocessed asynchronous tasks. If you don’t control this, a system won’t degrade gracefully (out of memory for example). So you want to have some sort of bounded queue where calls can be placed. But what happens when the queue is full? Are you going to block or are you going to throw an error? If you are going to block, you probably want to do it with a timeout. This could be added in the annotation; every call has the same timeout, but this also can be done by adding a timeout parameter in the method call itself (this gives more flexibility). In either way: you also need to make clear to the client that the call has failed; maybe a return value or a timeout error (my preferred solution). If you do want to block, you want your threads to be responsive to interrupts, so it is best that your asynchronous call also throws an interrupted exception.
3) when the environment goes does, and calls still are made, the threadpool probably isn’t going to execute the incoming asynchronous calls. So your asynchronous call also needs to throw some sort of rejected execution exception to indicate this situation.
Nice to see you have finished your study
November 1st, 2007 at 3:19 pm
Peter I absolutely agree with you on the role of threadpools, but there’s also a limit as to what one can mention in just one blog-article
This example is just a snipped of the solution I created for my thesis. The full implementation also supports parameters for stuff like deamon-behavior, which could be extended to support timeout-related things.
On the other hand the full solution also contains an aspectj based mechanism to coordinate the threads to threadpools, with pools of different priorities and sizes, from within one module. And with this realizes a central supervision and control of threads and threadpool behavior, which is a big gain compared to the default scattered implementation.
So some of your remarks on this post are cleared up in the full thesis…