Class IOThreadStorage
Synopsis
#include <lib/inc/drogon/IOThreadStorage.h>
template <typename C>
class IOThreadStorage : public trantor::NonCopyable
Description
Utility class for thread storage handling.
Thread storage allows the efficient handling of reusable data without thread synchronisation. For instance, such a thread storage would be useful to store database connections.
Example usage:
struct MyThreadData {
int threadLocal = 42;
std::string something = "foo";
};
class MyController : public HttpController<MyController> {
public:
METHOD_LIST_BEGIN
ADD_METHOD_TO(MyController::endpoint, "/some/path", Get);
METHOD_LIST_END
void login(const HttpRequestPtr &req,
std::function<void (const HttpResponsePtr &)> &&callback) {
assert(storage_->threadLocal == 42);
// handle the request
}
private:
IOThreadStorage<MyThreadData> storage_;
};
Inheritance
Ancestors: trantor::NonCopyable
Methods
IOThreadStorage | ||
getThreadData overload | Get the thread storage asociate with the current thread. | |
init | ||
operator* overload | ||
operator-> overload | ||
setThreadData overload | Sets the thread data for the current thread. |
Source
Lines 59-160 in lib/inc/drogon/IOThreadStorage.h.
template <typename C>
class IOThreadStorage : public trantor::NonCopyable
{
public:
using ValueType = C;
using InitCallback = std::function<void(ValueType &, size_t)>;
template <typename... Args>
IOThreadStorage(Args &&... args)
{
static_assert(std::is_constructible<C, Args &&...>::value,
"Unable to construct storage with given signature");
size_t numThreads = app().getThreadNum();
#ifdef _WIN32
assert(numThreads > 0 && numThreads != size_t(-1));
#else
assert(numThreads > 0 &&
numThreads != std::numeric_limits<size_t>::max());
#endif
// set the size to numThreads+1 to enable access to this in the main
// thread.
storage_.reserve(numThreads + 1);
for (size_t i = 0; i <= numThreads; ++i)
{
storage_.emplace_back(std::forward<Args>(args)...);
}
}
void init(const InitCallback &initCB)
{
for (size_t i = 0; i < storage_.size(); ++i)
{
initCB(storage_[i], i);
}
}
/**
* @brief Get the thread storage asociate with the current thread
*
* This function may only be called in a request handler
*/
inline ValueType &getThreadData()
{
size_t idx = app().getCurrentThreadIndex();
assert(idx < storage_.size());
return storage_[idx];
}
inline const ValueType &getThreadData() const
{
size_t idx = app().getCurrentThreadIndex();
assert(idx < storage_.size());
return storage_[idx];
}
/**
* @brief Sets the thread data for the current thread
*
* This function may only be called in a request handler
*/
inline void setThreadData(const ValueType &newData)
{
size_t idx = app().getCurrentThreadIndex();
assert(idx < storage_.size());
storage_[idx] = newData;
}
inline void setThreadData(ValueType &&newData)
{
size_t idx = app().getCurrentThreadIndex();
assert(idx < storage_.size());
storage_[idx] = std::move(newData);
}
inline ValueType *operator->()
{
size_t idx = app().getCurrentThreadIndex();
assert(idx < storage_.size());
return &storage_[idx];
}
inline ValueType &operator*()
{
return getThreadData();
}
inline const ValueType *operator->() const
{
size_t idx = app().getCurrentThreadIndex();
assert(idx < storage_.size());
return &storage_[idx];
}
inline const ValueType &operator*() const
{
return getThreadData();
}
private:
std::vector<ValueType> storage_;
};