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/
SMime.p7s
Description: S/MIME cryptographic signature
_______________________________________________ Cplusplus-sig mailing list [email protected] http://mail.python.org/mailman/listinfo/cplusplus-sig
