AWS SDK for C++

AWS SDK for C++ Version 1.11.808

Loading...
Searching...
No Matches
AWSClientAsyncCRTP.h
1
6#pragma once
7
8#include <aws/core/client/AWSAsyncOperationTemplate.h>
9#include <aws/core/utils/logging/ErrorMacros.h>
10#include <aws/core/utils/component-registry/ComponentRegistry.h>
11
12namespace Aws
13{
14namespace Http { class HttpRequest; }
15namespace Utils {
16 namespace Stream { class HttpWriteDataStreamBuf; }
17 namespace Threading { class Executor; }
18}
19namespace Client
20{
21 class AsyncCallerContext;
22 template <typename OutcomeT, typename ClientT, typename AWSEndpointT, typename RequestT, typename HandlerT>
23 class BidirectionalEventStreamingTask;
24
28 template<typename T>
29 struct AWS_CORE_LOCAL IsEventStreamOperation : IsEventStreamOperation<decltype(&T::operator())> {};
30
31 template<typename ReturnT, typename ClassT, typename RequestT>
32 struct AWS_CORE_LOCAL IsEventStreamOperation<ReturnT(ClassT::*)(RequestT) const>
33 {
34 static const bool value = !std::is_const<typename std::remove_reference<RequestT>::type>::value;
35 };
36
37 template<typename ReturnT, typename ClassT>
38 struct AWS_CORE_LOCAL IsEventStreamOperation<ReturnT(ClassT::*)() const>
39 {
40 static const bool value = false;
41 };
42
43
48 template <typename AwsServiceClientT>
50 {
51 public:
53 : m_isInitialized(true),
55 {
56 AwsServiceClientT* pThis = static_cast<AwsServiceClientT*>(this);
57 Aws::Utils::ComponentRegistry::RegisterComponent(AwsServiceClientT::GetServiceName(),
58 pThis,
59 &AwsServiceClientT::ShutdownSdkClient);
60
61 }
62
64 : m_isInitialized(other.m_isInitialized.load()),
66 {
67 AwsServiceClientT* pThis = static_cast<AwsServiceClientT*>(this);
68 Aws::Utils::ComponentRegistry::RegisterComponent(AwsServiceClientT::GetServiceName(),
69 pThis,
70 &AwsServiceClientT::ShutdownSdkClient);
71 }
72
74 {
75 if (&other != this)
76 {
77 ShutdownSdkClient(static_cast<AwsServiceClientT*>(this));
79 m_isInitialized = other.m_isInitialized.load();
80 }
81
82 return *this;
83 }
84
86 {
87 AwsServiceClientT* pClient = static_cast<AwsServiceClientT*>(this);
89 }
90
97 static void ShutdownSdkClient(void* pThis, int64_t timeoutMs = -1)
98 {
99 AwsServiceClientT* pClient = reinterpret_cast<AwsServiceClientT*>(pThis);
100 AWS_CHECK_PTR(AwsServiceClientT::GetServiceName(), pClient);
101 if(!pClient->m_isInitialized)
102 {
103 return;
104 }
105
106 std::unique_lock<std::mutex> lock(pClient->m_shutdownMutex);
107
108 pClient->m_isInitialized = false;
109 if (pClient->GetHttpClient().use_count() == 1)
110 {
111 pClient->DisableRequestProcessing();
112 }
113
114 if (timeoutMs == -1)
115 {
116 timeoutMs = pClient->m_clientConfiguration.requestTimeoutMs;
117 }
118 pClient->m_shutdownSignal.wait_for(lock,
119 std::chrono::milliseconds(timeoutMs),
120 [&](){ return pClient->m_operationsProcessed.load() == 0; });
121
122 if (pClient->m_operationsProcessed.load())
123 {
124 AWS_LOGSTREAM_FATAL(AwsServiceClientT::GetAllocationTag(), "Service client "
125 << AwsServiceClientT::GetServiceName() << " is shutting down while async tasks are present.");
126 }
127
128 pClient->m_clientConfiguration.executor.reset();
129 pClient->m_clientConfiguration.retryStrategy.reset();
130 pClient->m_endpointProvider.reset();
131 }
132
137 template<typename RequestT, typename HandlerT, typename OperationFuncT, typename std::enable_if<!IsEventStreamOperation<OperationFuncT>::value, int>::type = 0>
138 void SubmitAsync(OperationFuncT operationFunc,
139 const RequestT& request,
140 const HandlerT& handler,
141 const std::shared_ptr<const Aws::Client::AsyncCallerContext>& context = nullptr) const
142 {
143 const AwsServiceClientT* clientThis = static_cast<const AwsServiceClientT*>(this);
144 Aws::Client::MakeAsyncOperation(operationFunc, clientThis, request, handler, context, clientThis->m_clientConfiguration.executor.get());
145 }
146
152 template<typename RequestT, typename HandlerT, typename OperationFuncT, typename std::enable_if<IsEventStreamOperation<OperationFuncT>::value, int>::type = 0>
153 void SubmitAsync(OperationFuncT operationFunc,
154 RequestT& request, // note non-const ref
155 const HandlerT& handler,
156 const std::shared_ptr<const Aws::Client::AsyncCallerContext>& context = nullptr) const
157 {
158 const AwsServiceClientT* clientThis = static_cast<const AwsServiceClientT*>(this);
159 Aws::Client::MakeAsyncStreamingOperation(operationFunc, clientThis, request, handler, context, clientThis->m_clientConfiguration.executor.get());
160 }
161
166 template<typename HandlerT, typename OperationFuncT>
167 void SubmitAsync(OperationFuncT operationFunc,
168 const HandlerT& handler,
169 const std::shared_ptr<const Aws::Client::AsyncCallerContext>& context = nullptr) const
170 {
171 const AwsServiceClientT* clientThis = static_cast<const AwsServiceClientT*>(this);
172 Aws::Client::MakeAsyncOperation(operationFunc, clientThis, handler, context, clientThis->m_clientConfiguration.executor.get());
173 }
174
179 template<typename RequestT, typename OperationFuncT, typename std::enable_if<!IsEventStreamOperation<OperationFuncT>::value, int>::type = 0>
180 auto SubmitCallable(OperationFuncT operationFunc,
181 const RequestT& request) const
182 -> std::future<decltype((static_cast<const AwsServiceClientT*>(nullptr)->*operationFunc)(request))>
183 {
184 const AwsServiceClientT* clientThis = static_cast<const AwsServiceClientT*>(this);
185 return Aws::Client::MakeCallableOperation(AwsServiceClientT::GetAllocationTag(), operationFunc, clientThis, request, clientThis->m_clientConfiguration.executor.get());
186 }
187
193 template<typename RequestT, typename OperationFuncT, typename std::enable_if<IsEventStreamOperation<OperationFuncT>::value, int>::type = 0>
194 auto SubmitCallable(OperationFuncT operationFunc, /*note non-const ref*/ RequestT& request) const
195 -> std::future<decltype((static_cast<const AwsServiceClientT*>(nullptr)->*operationFunc)(request))>
196 {
197 const AwsServiceClientT* clientThis = static_cast<const AwsServiceClientT*>(this);
198 return Aws::Client::MakeCallableStreamingOperation(AwsServiceClientT::GetAllocationTag(), operationFunc, clientThis, request, clientThis->m_clientConfiguration.executor.get());
199 }
200
206 template<typename OperationFuncT>
207 auto SubmitCallable(OperationFuncT operationFunc) const
208 -> std::future<decltype((static_cast<const AwsServiceClientT*>(nullptr)->*operationFunc)())>
209 {
210 const AwsServiceClientT* clientThis = static_cast<const AwsServiceClientT*>(this);
211 return Aws::Client::MakeCallableOperation(AwsServiceClientT::GetAllocationTag(), operationFunc, clientThis, clientThis->m_clientConfiguration.executor.get());
212 }
213 protected:
214 template <typename OutcomeT, typename ClientT, typename AWSEndpointT, typename RequestT, typename HandlerT>
215 friend class BidirectionalEventStreamingTask; // allow BidirectionalEventStreamingTask to access m_isInitialized
216
217 template <typename ClientT, typename OutcomeT, typename RequestT, typename EncoderStreamT,
218 typename HandlerT, typename StreamReadyHandlerT>
220 const ClientT*, RequestT&, std::shared_ptr<RequestT>, std::shared_ptr<EncoderStreamT>,
221 std::shared_ptr<Aws::Utils::Stream::HttpWriteDataStreamBuf>, const std::shared_ptr<Aws::Http::HttpRequest>&,
223 const StreamReadyHandlerT&, const HandlerT&, const std::shared_ptr<const Aws::Client::AsyncCallerContext>&);
224
225 std::atomic<bool> m_isInitialized;
226 mutable std::atomic<size_t> m_operationsProcessed;
227 mutable std::condition_variable m_shutdownSignal;
228 mutable std::mutex m_shutdownMutex;
229
230 // TODO: track scheduled tasks
231 // std::atomic<size_t> m_operationsScheduled;
232 };
233} // namespace Client
234} // namespace Aws
ClientWithAsyncTemplateMethods & operator=(const ClientWithAsyncTemplateMethods &other)
auto SubmitCallable(OperationFuncT operationFunc, const RequestT &request) const -> std::future< decltype((static_cast< const AwsServiceClientT * >(nullptr) -> *operationFunc)(request))>
auto SubmitCallable(OperationFuncT operationFunc, RequestT &request) const -> std::future< decltype((static_cast< const AwsServiceClientT * >(nullptr) -> *operationFunc)(request))>
void SubmitAsync(OperationFuncT operationFunc, RequestT &request, const HandlerT &handler, const std::shared_ptr< const Aws::Client::AsyncCallerContext > &context=nullptr) const
void SubmitAsync(OperationFuncT operationFunc, const RequestT &request, const HandlerT &handler, const std::shared_ptr< const Aws::Client::AsyncCallerContext > &context=nullptr) const
void SubmitAsync(OperationFuncT operationFunc, const HandlerT &handler, const std::shared_ptr< const Aws::Client::AsyncCallerContext > &context=nullptr) const
ClientWithAsyncTemplateMethods(const ClientWithAsyncTemplateMethods &other)
static void ShutdownSdkClient(void *pThis, int64_t timeoutMs=-1)
friend void SubmitBidirectionalStreamingRequest(const ClientT *, RequestT &, std::shared_ptr< RequestT >, std::shared_ptr< EncoderStreamT >, std::shared_ptr< Aws::Utils::Stream::HttpWriteDataStreamBuf >, const std::shared_ptr< Aws::Http::HttpRequest > &, Aws::Utils::Threading::Executor *, const StreamReadyHandlerT &, const HandlerT &, const std::shared_ptr< const Aws::Client::AsyncCallerContext > &)
auto SubmitCallable(OperationFuncT operationFunc) const -> std::future< decltype((static_cast< const AwsServiceClientT * >(nullptr) -> *operationFunc)())>
auto AWS_CORE_LOCAL MakeCallableOperation(const char *ALLOCATION_TAG, OperationFuncT &&operationFunc, const ClientT *clientThis, const RequestT &request, ExecutorT *pExecutor) -> std::future< decltype((clientThis-> *operationFunc)(request))>
void AWS_CORE_LOCAL MakeAsyncOperation(OperationFuncT &&operationFunc, const ClientT *clientThis, const RequestT &request, const HandlerT &handler, const HandlerContextT &context, ExecutorT *pExecutor)
void AWS_CORE_LOCAL MakeAsyncStreamingOperation(OperationFuncT &&operationFunc, const ClientT *clientThis, RequestT &request, const HandlerT &handler, const HandlerContextT &context, ExecutorT *pExecutor)
auto AWS_CORE_LOCAL MakeCallableStreamingOperation(const char *ALLOCATION_TAG, OperationFuncT &&operationFunc, const ClientT *clientThis, RequestT &request, ExecutorT *pExecutor) -> std::future< decltype((clientThis-> *operationFunc)(request))>
AWS_CORE_API void DeRegisterComponent(void *pClient)
AWS_CORE_API void RegisterComponent(const char *clientName, void *pClient, ComponentTerminateFn terminateMethod)