Welcome back.
In part 1 I outlined in broad strokes some of the general defects in our approaches to concurrent development. Parallelism is not a simple thing, or at least as of this writing it’s not. I do not profess to have the answers; if I did I would be retired to an island someplace, contemplating my next Mai-tai. However, if I cannot provide answers I can provide questions and sometimes getting the right answer is a matter of simply asking the right question. Before we start though I want to make one thing clear: I will be working from the conceptual position that making better versions of existing methodologies will not take us where we need to be; otherwise, obviously we would be there by now. That said, using existing technology in a new and perhaps unorthodox way is definitely inbounds. Finally, each suggested thought path can and probably will be revisited and refined as a better understanding of the other problem domains become clearer.
So here we go.
First, to figure out how to get there we need to describe the destination so I will sum an initial assessment of what would be utopian, at least from my perspective:
The Goal (version 1.0):
1. Hardware neutrality: This solution should be applicable to anything from a cellphone to a mainframe. This means memory constraints in some cases, endian issues in other cases, lack of floating point and other low-level functionality. This may mean that thread and process constructs work differently. This may also mean that memory and I/O work differently. The low-level C runtimes help with this but only to an extent.
2. Platform (OS) neutrality. That means it will be coded for, project-managed, built the same and run the same on all platforms. This will also mean that memory and processes management is guaranteed to work differently. For the purposes of this exploration let us assume that we need to exist in three worlds: Windows, Linux and a typical embedded OS, in this case the default game OS that runs on the Playstation 3. I selected the first two because I know them best, and the latter because it represents a sufficiently “alien” environment both in terms of hardware and software. For as much as we think of Windows and Linux as being different, they are vastly more similar than what lives on the Playstation. Thus, if we want an environment to test our solutions, these three will do. The Playstation environment still gives us a stand-in for any of a hundred other type of device from PDA to a cell phone. For larger memory systems things like ACE can help but as soon as it gets too close to “alien” metal, it becomes a $100 solution for a $10 budget.
3. Memory neutrality: Few assumptions will be made about the amount and locality of available memory. Data may be all or partially remote. You may have a megabyte or a gigabyte of memory directly available to you (you being the task at hand). For now we will consider locally available memory limitations of 256K in some cases and 256 megs of memory in others.
4. Programmer neutrality. In the end, this may be the hardest thing of all. By programmer neutrality I mean you cannot assume the programmer has the chops for doing intelligent concurrent development. This isn’t a slam against anyone although only the completely naive would consider concurrent development “easy”; it’s just easy to get wrong. Intel knows this and that is why they made the Thread Building Blocks or TBB. TBB helps the developer in at least two ways: it provides the developer more intuitive ways to build out concurrent tasking and by provided (some) thread-safe mechanisms for data storage. The problem of TBB is that it is a good idea simply not taken far enough; if you stray too far from x86, and specifically the shared memory model, you are done for. Intel cannot be blamed for this or any shortcomings here; not only are they they first to pioneer this concept (which is far too long in coming) but they are also not limiting it to the x86 which is commendable since they invented the x86.
What we need then is something that accomplishes all of these things; the hardware neutrality of the C runtime, the services (OS) neutrality of ACE, the memory neutrality currently fulfilled with…nothing and the programmer neutrality of TBB.
With this framework the developer should be able to approach the problem to solve *as* a problem to solve, not a program to write or a system to “design”. The problem should then auto-decompose into units of execution that can as easily be solved by a single core processor with 256 megs of RAM as 256 cell phones with a single megabyte of RAM each.
Given this set of requirements we need to solve the problem starting at the programmer (#4) first and let that drive the rest. While I don’t necessarily subscribe to the whole XP development model, the reliance on a simple test-driven development process has proven it’s value time and time again. We will attempt to use it here to drive this process but as soon as it starts to get in the way of what we are trying to accomplish or if something more applicable becomes available, we will use that.
The test-driven model works generally like this:
1. You have a problem to solve (program to write). Using the simplest program ever, Hello world…
2. You write a high-level program to solve the business end of things, making up data structures and functions as you go. Naturally, as written this will not compile since there is nothing behind it but it *does* allow you to express the problem and shake out missing requirements. This high-level program would be nothing more than a “main()” that might look like:
void main(void)
{
print_message("Hello World");
}
3. You have now accomplished phase 1 of the test-driven development process. Once your program is written, it will serve as a test harness for the rest of your code and you fill in functionality until the application actually compiles. In this case, the above will not compile because it does not have a print_message() function. The next step is to stub in code until the program actually builds (but obviously does not run or more to the point, run (correctly) so we update our app to look like:
void print_message(char *ptrMsg)
{
}
void main(void)
{
print_message("Hello World");
}
4. Well, now our application compiles, the next step in the test-driven development process accomplished. This may seem like an insignificant step but a powerful and non-obvious mission this performs is that it shakes out any unnecessary coding/API calls. Instead of writing a whole library of IO and text manipulation functions, I have the one single bit of functionality I need to accomplish the task at-hand: print a message. This is very important and keeps you from coding 900 extra functions that you don’t need even if you think you might need them “some day”. Anyhow, you now have an app that compiles but doesn’t pass the “test” of printing your message. This is the final step. So, you add the needed functionality to your app so it becomes:
void print_message(char *ptrMsg)
{
printf(ptrMsg);
}
void main(void)
{
print_message("Hello World");
}
5. Bingo, the final phase of the test-driven development process has been accomplished: the program compiles, runs and performs the single task we needed: it printed a message. And nothing else.
While the actual program was a do-nothing example, it serves to demonstrate how we will approach the rest of this in the coming articles. This is important because test-driven development works the way that I think that we need to which is to start by thinking differently about the way we approach expressing problems as programs. I am going close for now so that I can think up a good test problem to use as the model to work out the rest of what we hope to accomplish. At a high level, it will need to work on all platforms, work in all memory conditions, and be solvable by a single processor, multiple processors on a single machine or multiple machines in a network. Finally, the “how” of this should be transparent to the developer. Consider these requirements for the requirements.
Until next time…
JeffC at JBCobb.net

Related Articles
3 users responded in this post
Two things: 1. Sorry about the bad code formatting; will work on this for more complex code dumps and 2 am turning on commments on a trial basis. If I get flooded with Viagra ads will make it by registration only.
Jeff
Gregory…
After this soaks in, I am sure what you have here is really brilliant….
Gregory: Tks for reading. At work I need to be smart so this area is just my mental playground. Most of it will probably prove to be complete bullshit but hey, I pay the tab on the IP and run the server, doing so on my own time so what the hell.
I just see a near future where with the right kind of framework, anything that can communicate and computer will donate cycles and hence problems will get solved that cannot currently be solved.
I also see that there needs to be a new balance struck between ease of use WRT application framework and the adaptability of underlying thread management systems.
The thing is, none of this is supposed to be brilliant. This is just me doing some what-if stuff…
Again, Tks for reading if you are not a bot.
JeffC
Leave A Reply