[C++-sig] question on boost.python exception mechanisms
Niall Douglas
s_sourceforge at nedprod.com
Thu Apr 18 02:40:49 CEST 2013
On 17 Apr 2013 at 17:13, Holger Joukl wrote:
> // the global per-thread exception storage
> boost::unordered_map<pthread_t, boost::exception_ptr> exception_map;
You can't assume pthread_t is of integral type. You can a thread_t
(from C11) I believe. You may not care on your supported platforms
though.
> throw std::runtime_error("throwing up");
If you're going to use Boost's exception_ptr implementation, you
really ought to throw using Boost's exception throw macro. Otherwise
stuff become unreliable.
> void guarded_callback_with_exception(cb_arg_t arg) {
> std::cout << "--> guarded exception-throwing CPP callback" << arg <<
> std::endl;
> try {
> throw std::runtime_error("throwing up");
> } catch (...) {
> std::cout << "storing exception in exception map" << std::endl;
> pthread_t current_thread = pthread_self();
> exception_map[current_thread] = boost::current_exception();
> exception_map.erase(current_thread);
> //global_exception_holder = boost::current_exception();
> }
> std::cout << "<-- guarded exception-throwing CPP callback" << arg <<
> std::endl;
> }
If you're just going to do this, I'd suggest you save yourself some
hassle and look into packaged_task which is a std::function combined
with a std::future. It takes care of the exception trapping and
management for you. Do bear in mind there is absolutely no reason you
can't use a future within a single thread to traverse some state over
third party binary blob code, indeed I do this in my own code at
times e.g. if Qt, which doesn't like exceptions, stands between my
exception throwing code at the end of a Qt signal and my code which
called Qt.
> pthread_t current_thread = pthread_self();
> if (exception_map.find(current_thread) != exception_map.end()) {
> try {
> std::cout << "rethrowing exception from exception map" <<
> std::endl;
> boost::rethrow_exception(exception_map[current_thread]);
> } catch (const std::exception& exc) {
> std::cout << "caught callback exception: " << exc.what() <<
> std::endl;
> }
> }
Why not using thread local storage?
> Which doesn't respect call function depth (how would I do that?)
Keep a count of nesting levels, so if a callback calls a callback
which calls a callback etc.
> and doesn't use a queue; I suppose you mean using the lockfree queue for
> threadsafe
> access to the hash table.
Maybe a hash table of lockfree queues. Depends on your needs.
> I think I don't even need that for my use case as I basically
> - call dispatch on a Boost.Python wrapped object
> - which invokes the C libs dispatcher function
> - which invokes the registered callbacks (these will usually be implemented
> in Python)
>
> i.e. the same thread that produced the exception will need to handle it.
Another possibly useful idea is to have the C libs dispatcher
dispatch packaged_task's into a per-thread lock free queue which you
then dispatch on control return when the C library isn't in the way
anymore. Call it deferred callbacks :)
> Thanks for the valuable hints!
You're welcome.
Niall
--
Any opinions or advice expressed here do NOT reflect those
of my employer BlackBerry Inc.
Work Portfolio: http://careers.stackoverflow.com/nialldouglas/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SMime.p7s
Type: application/x-pkcs7-signature
Size: 6061 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20130417/4c04ee5b/attachment-0001.bin>
More information about the Cplusplus-sig
mailing list