Hi, Am 13.06.2010 16:30, schrieb Alexei Sheplyakov:
I'm afraid you've missed the point. I wanted to explain that one of the essential mechanisms used by GiNaC (memory management) is not thread safe, therefore all setups (except using GiNaC from one thread) are unsafe.
this I don't believe yet. Maybe I am wrong, but the setup as he described it has no (and will not have any) sharing of subexpressions between threads.
I just think using GiNaC from several threads is more dangerous than Russian roulette :)
oh, please wait, reconsider! Your opinion might backfire someday ... ;-)
1. Automatic evaluation is not thread safe.
yes, but ...
Have a look at ex::construct_from_basic (which is basically the core of automatic evaluation). That code does
318 // If the original object is not referenced but heap-allocated, 319 // it means that eval() hit case b) above. The original object is 320 // no longer needed (it evaluated into something different), so we 321 // delete it (because nobody else will). 322 if ((other.get_refcount() == 0)&& (other.flags& status_flags::dynallocated)) 323 delete&other; // yes, you can apply delete to a const pointer 324
The reference counting is not thread safe, so the object can be deleted while it's used by another thread.
... all objects in his setup are 100% private to each thread. So I don't see a problem.
2. GiNaC smart pointers are not thread safe. In theory it can be fixed by using atomic integers for reference counting, and locking in makewritable().
3. GiNaC uses STL containers to store sums and products. STL containers are not thread safe at all.
4. Subs() uses writable access (let_op()), and has no locking at all.
Same box.
I didn't mention refcounting, because I think in his setup it doesn't cause a problem, or does it?.
No matter what your setup is, you're going to use the automatic evaluation (otherwise you don't need GiNaC at all). And it's not thread safe (due to reference counting, data structures, etc). So the only safe setup is using GiNaC from one thread.
I think the only problem (in his setup) is a possible call to the gcd code.
I'm afraid locks will ruin any performance gains. I mean, if you need to take a lock every time you need to add two and integers or allocate several bytes of RAM, you can't achive any reasonable performance.
You were right if you made ginac thread-safe in a naive way, i.e. many locks protecting refcounting, functions, etc. While I don't know about cln, yet, in ginac it can be done in a smarter way. Instead of making ginac absolutely thread-safe in any use-case, one can enable the user to specify data/expression segments to which certain expressions, symbols or whatever should belong. Then, ginac ensures that it is thread-safe between these different segments. Some extra functions to let the user share or transport data between the segments need to be implemented and voila. That is just a rough idea, but the threading overhead would be minimized to keep it attractive. Regards, Jens