Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Frequently Asked Questions

Objects In The Library

In C++CSP there is the ParComm class for parallel communications but what is the difference between that and running processes for doing it in parallel, as I would in JCSP?

Semantically the two methods are equivalent, the ParComm method is just easier to use, faster and less memory hungry. It can also be re-used in a looping process without re-allocating memory every loop.

Why can I not get ParCommItem objects for Barrier and Bucket?

This was considered at some point but normally a barrier and bucket have unit-time behaviour for all syncing/flushing because they build a queue in the same format as the run queue - so putting the processes back on the run queue is a matter of 2 pointer assignments, even for a barrier of size 1 million (or more!). Allowing ParCommItem for Barrier and Bucket objects would involve changing this behaviour to linear-time, i.e. O(n), for the final sync of Barrier and for flushing, so it was decided against.

Race Hazards

Since the library uses co-operative single-threaded multi-tasking, doesn't that mean it is safe to ignore race hazards on shared memory because no two processes will actually be running at the same time?

Theoretically that is potentially true but it is a bad idea for several reasons:

Crashes/Deadlocks etc.

While using the library my program crashes, seemingly while the thread of control was in the library. Is this a bug?

While I would never rule out bugs in the library it is more likely to be a case of misuse of the library. Most commonly, processes that are in different threads using non-thread-safe objects (such as One2OneChannel) or multiple processes using a non-shared channel end, or processes syncing on a barrier they haven't enrolled on. There are probably more ways to make the library crash too. This is intended to be the case -- adding run-time checks for these problems would impact on performance, and as Stroustrup pointed out, you can always build a safe slow interface on top of a fast dangerous one but never the other way round...

My program spits out something about deadlocking and immediately exits -- why?

Deadlock occurs when there are no processes left on the run queue in a thread (and none waiting on timeouts). This should never occur under normal operation, and is definitely a condition that should cause termination. It is usually caused by processes involved in a ring inputting from each other in a circular fashion such that none of the inputs will complete, or processes syncing on a barrier except one that is deadlocked in some other way, or processes inputting from channels that have no outputter at the other end

Why do I get an access violations when trying to access a CSProcess child after Ive run it, or when I try and run processes declared on the stack (as opposed to the heap)

The function calls Parallel, Sequential, spawnProcess, spawnAsNewThread etc all have the same expectation of a process pointer passed to them -- it is a process that has been declared on the heap. This is because the library calls delete on the object once it has finished running. If you wish to return some data once the process has finished running, use channels (rather than trying to store the data in the process class)

Installation/Compilation

The library seems to need the boost libraries. What are they, and where can I get them?

The boost libraries are a collection of brilliant C++ classes. I view them as an expansion to the standard library, filling in holes and providing new things. Boost is a dependency of the C++CSP library. A lot of people find it hard to install boost because it has a complicated build procedure. But: at the time of writing, C++CSP does not the compiled boost library; only the boost headers are needed. This means you don't need to build the boost library. Just download the distribution and copy the boost/ directory of headers contained within to somewhere in your include path. Although on gentoo at least, you can just do "emerge boost", and that works fine.

Does the library have to depend on boost? I was considering C++CSP for an embedded system, but I don't want to have to put boost on too.

As mentioned above, C++CSP only requires the boost header files, not the compiled library. This means that the boost headers are needed at compile-time (presumably on a cross-compiling system), but after it is compiled you don't need to worry about boost.

The library refuses to compile on my machine. Why not?

C++CSP aims to be as portable as it can be but it is possible that either your configuration or your platform has not been tried before and has thrown up an unforeseen problem. Please contact the maintainer with details of the problem, who will be happy to try and rectify the problem or include support for your platform in the library.

The OS and Blocking Calls

How does C++CSP work with blocking system calls if everything lives in one thread - is use of the NET channels required?

Here is a copy and paste from an e-mail that seems to roughly cover the point:

I couldn't find a satisfactory solution to the blocking system calls problem. For simple problems it is possible to just accept the blocking of your thread, but for real concurrent programs - surely what CSP is great for - that's not acceptable. In most programs you inevitably end up having one CSP process that wants to hear from two different blocking system calls and ALT over them, as you want to. Clearly you need to farm out threads/processes to make the call and report back. In the old threads method (now removed), you'd use channels built on semaphores. But to ALT over two semaphore-channels you can't wait() on either one; you must poll the semaphores alternately. Polling semaphores (i.e. not blocking on them) turns out to carry a surprisingly large overhead on both Linux and Windows.

This overhead turned out to be larger than calling select() over two sockets (select() being that rare godsend - an OS call that is the equivalent of the ALT, allowing you to select between many usually blocking socket reads). So even though it seems like the worse idea, I went with having many NET machines (i.e. processes) for proper concurrency rather than multiple threads which were in fact slower. This also allowed me to stop worrying about some of the problems with shared memory between threads (e.g. the process run queue used to have to be in TLS, and added a little bit of overhead for every context switch).

Of course, I wish there was an OS with threads of the right granularity to use as CSP processes (fiber-equivalents being a little too light in that they can't block separately, and threads being too heavy in terms of context switching and inter-thread communication), with good inter-thread communication that supports the ALTing concept. But alas, it seems OS-designers don't have the same views on concurrency as us CSP-lot, though I think it is slowly swinging our way as things like dual-core and multi-processor becomes ever more prevalent. Rant over! ;-)

PThreads

When I try to run a program using C++CSP under GNU/Linux or similar I get a segment violation. In gdb the crash seems to be something to do with pthreads

Ah, pthreads. This is a complex one. The pthreads library is part of the glibc package that comes as standard on all GNU/Linux distributions. It is linked to if any library you link with your program also uses pthreads (such as SDL, among many others). From what I can understand from long trawls through the pthreads code, the situation is thus:

Pthreads needs some way to implement TLS (Thread-Local Storage). So it needs some way to identify between threads when they share the same memory space and execute the same code. The two ways it seems to offer are:

Which option it picks depends on your Linux kernel version. It seems to me that on version 2.3.99 or before it uses the first method, and on version 2.4.00 and onwards it uses the second. However, glibc on certain GNU/Linux distributions seems to not fit with this rule, so I'm not sure any more. The reason the first option conflicts with C++CSP is that C++CSP allocates a new stack for each process, so pthreads can no longer find its identifier at the top of the stack.

If you have this error, the simple solution would be to not compile with pthreads, but I realise this is unavoidable for most purposes. The other option is to maybe upgrade your kernel and recompile glibc. Also not a great option, depending on your situation. If this problem persists for people then it may be time to contact the glibc team for a little help.

The above advice is applicable if you are using the setjmp/longjmp method. If you are using GNU pth as your underlying mechanism, I gather that there are added problems linking GNU pth with pthreads: this mailing listpost shows that there is a conflict involving errno, and this post suggests that the two libraries simply weren't designed to be linked together. These posts are from three years ago however; things may have changed since.


Generated on Wed May 18 22:51:50 2005 for The Kent C++CSP Library by  doxygen 1.4.2