Thursday, April 24, 2008

Multi-Threading Suneido - Thread Specific Storage

Back to work on multi-threading Suneido. After frittering away my last session, I figured I'd "park downhill" and decided at the end of that session that the next thing I'd work on was replacing my home brew thread specific storage with ACE_TSS. With a clear task I wasted less time.

ACE_TSS is a template class used like: ACE_TSS<mystruct> mytss;

which is then accessed like: mytss->member

It overloads operator-> to do its stuff.

In order to keep ACE specific code as limited as possible I defined functions to access my thread specific storage. For example:

Proc*& tss_proc() { return tss->proc; }

The '&' is needed so the functions can be used as lvalues like:

tss_proc() = newvalue;

Unfortunately, this meant replacing all the instances of proc with tss_proc() but I could use the compiler to do the heavy lifting by removing proc and seeing where I got compile errors.

I could have kept the name as proc, but changing it made the transition clearer, and it doesn't hurt to make it clear in the code that it is thread-specific.

For my current, non-ACE version of Suneido I simply defined the functions to access my home brew thread specific storage.

In the process I discovered that part of the old thread specific storage code was broken. It hadn't caused problems because it was code to clear unused memory during garbage collection, so it just meant the garbage collection was a little less efficient. I fixed it for the current version, but I don't know how to implement it for real threads so it's a good thing it's not critical!

The only real problem I ran into was that the Boehm garbage collector does not appear to "see" the ACE thread specific storage. That's probably fixable but it would require digging into how ACE_TSS is implemented. And that would be platform specific. Yuck. Instead I was able to make the thread specific storage simply point to data that would be seen by the garbage collector. I'll just have to be careful I don't forget about this issue in the future.

As far as I can tell, it's all working, both the current version and the ACE version. Next I have to start tackling the crux of the problem - locking global data structures. I think I'll start with the symbol table and the global values table. These are fairly loosely coupled and shouldn't be too hard to handle. That should give me a little experience to help tackle the hard parts like the database.

PS. I started this session using NetBeans but I gave up part way through and went back to using Scite. This was partly because I haven't got NetBeans set up to build, which meant I had to compile in a separate command line window, which meant there was no easy way to click on the errors and go to that part of the source. (which I can do in Scite, although it's mostly a straight editor). I could have messed around with getting the build environment set up, but then I would have ended up like last time, with no real work accomplished.

Another thing I found disappointing in NetBeans is that it didn't seem to have the kind of powerful tools that I want/expect from an IDE. For instance, there didn't seem to be any way to find all the uses of a function or variable. Maybe I just missed it. But I wouldn't be surprised if it wasn't there, C++ tends to get second-class support in primarily Java IDE's. The Eclipse CDT used to be fairly minimal too, but I think they're supposed to have made significant improvements in the latest version. I'll have to go back and take another stab at trying to use it.

A final annoyance in NetBeans was that it didn't treat underscores as word characters. e.g. if you choose "Whole Words" and search for "proc" you find "tss_proc". I looked through the configuration options but couldn't find anywhere to change this. It seems odd because that's not C++ specific. If anyone knows how to "fix" this, let me know.

No comments: