From: Wolfgang Bangerth Date: Wed, 24 Apr 2024 19:56:08 +0000 (-0600) Subject: Add ThreadLocalStorage::get_for_thread(). X-Git-Tag: v9.6.0-rc1~340^2~3 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=afda888dccbf0bb177227caeb4bba9c8d20cd49c;p=dealii.git Add ThreadLocalStorage::get_for_thread(). --- diff --git a/include/deal.II/base/thread_local_storage.h b/include/deal.II/base/thread_local_storage.h index 5919e6b187..7abd759db0 100644 --- a/include/deal.II/base/thread_local_storage.h +++ b/include/deal.II/base/thread_local_storage.h @@ -24,6 +24,7 @@ # include # include # include +# include # include # include # include @@ -175,6 +176,23 @@ namespace Threads T & get(bool &exists); + /** + * If the thread with given `id` has an object currently stored, then return + * it by value via the `std::optional` object. If the indicated thread does + * not have an object stored, return an empty `std::optional`. + * + * Note that in the successful case, this function returns a *copy* of + * the object, unlike get() which returns a reference to it. This is + * because when you call get(), you are calling it from the current + * thread (i.e., the thread that "owns" the object), and so all accesses + * are by definition not concurrent. On the other hand, if you are asking + * about the object owned by a different thread, that other thread might + * concurrently be accessing it and that might cause race conditions. + * To avoid these, the function here returns a copy. + */ + std::optional + get_for_thread(const std::thread::id &id) const; + /** * Conversion operator that simply converts the thread-local object to the * data type that it stores. This function is equivalent to calling the @@ -440,6 +458,23 @@ namespace Threads } + template + std::optional + ThreadLocalStorage::get_for_thread(const std::thread::id &id) const + { + // Take a shared ("reader") lock for lookup: + std::shared_lock lock(insertion_mutex); + + // Then see whether we can find the indicated object; if so, copy it, + // otherwise return an empty std::optional. + const auto it = data.find(id); + if (it != data.end()) + return it->second; + else + return {}; + } + + template inline T & ThreadLocalStorage::get()