31 #include <lely/aio/queue.h> 41 ErrorCode(
int errc, uint32_t ac) {
43 return ::std::error_code(errc, ::std::system_category());
45 return static_cast<SdoErrc>(ac);
60 void Submit(RequestBase_& req);
62 ::std::size_t Cancel(RequestBase_* req,
SdoErrc ac);
64 template <
class T,
class U>
65 void OnRequest(uint16_t idx, uint8_t subidx, U&& value);
68 void OnRequest(uint16_t idx, uint8_t subidx);
70 void OnDnCon(
COCSDO*, uint16_t idx, uint8_t subidx, uint32_t ac) noexcept;
73 void OnUpCon(
COCSDO*, uint16_t idx, uint8_t subidx, uint32_t ac,
76 void OnTaskFinished(RequestBase_& op) noexcept;
79 ::std::shared_ptr<COCSDO> sdo;
85 impl->OnRequest<T>(this->idx, this->subidx, this->value);
94 self->con_(self->idx, self->subidx, ErrorCode(self->errc, self->ac));
99 Sdo::UploadRequest<T>::OnRequest(Impl_* impl) noexcept {
100 impl->OnRequest<T>(this->idx, this->subidx);
105 Sdo::UploadRequest<T>::Func_(aio_task* task) noexcept {
106 auto self =
static_cast<Sdo::UploadRequest<T>*
>(task);
109 self->con_(self->idx, self->subidx, ErrorCode(self->errc, self->ac),
110 ::std::move(self->value));
115 Sdo::DownloadRequestWrapper<T>::OnRequest(Impl_* impl) noexcept {
116 impl->OnRequest<T>(this->idx, this->subidx, this->value);
121 Sdo::DownloadRequestWrapper<T>::Func_(aio_task* task) noexcept {
122 auto self =
static_cast<Sdo::DownloadRequestWrapper<T>*
>(task);
124 ::std::function<DownloadSignature> con = ::std::move(self->con_);
125 auto idx =
self->idx;
126 auto subidx =
self->subidx;
127 auto ec = ErrorCode(self->errc, self->ac);
130 if (con) con(idx, subidx, ec);
135 Sdo::UploadRequestWrapper<T>::OnRequest(Impl_* impl) noexcept {
136 impl->OnRequest<T>(this->idx, this->subidx);
141 Sdo::UploadRequestWrapper<T>::Func_(aio_task* task) noexcept {
142 auto self =
static_cast<Sdo::UploadRequestWrapper<T>*
>(task);
144 ::std::function<UploadSignature<T>> con = ::std::move(self->con_);
145 auto idx =
self->idx;
146 auto subidx =
self->subidx;
147 auto ec = ErrorCode(self->errc, self->ac);
148 T value = ::std::move(self->value);
151 if (con) con(idx, subidx, ec, ::std::move(value));
156 Sdo::AsyncDownloadRequest<T>::OnRequest(Impl_* impl) noexcept {
157 impl->OnRequest<T>(this->idx, this->subidx, this->value);
162 Sdo::AsyncDownloadRequest<T>::Func_(aio_task* task) noexcept {
163 auto self =
static_cast<Sdo::AsyncDownloadRequest<T>*
>(task);
165 aio::Promise<::std::error_code> promise = ::std::move(self->promise_);
166 auto ec = ErrorCode(self->errc, self->ac);
169 promise.SetValue(ec);
174 Sdo::AsyncUploadRequest<T>::OnRequest(Impl_* impl) noexcept {
175 impl->OnRequest<T>(this->idx, this->subidx);
180 Sdo::AsyncUploadRequest<T>::Func_(aio_task* task) noexcept {
181 auto self =
static_cast<Sdo::AsyncUploadRequest<T>*
>(task);
183 aio::Promise<::std::tuple<::std::error_code, T>> promise =
184 ::std::move(self->promise_);
185 auto value = ::std::make_tuple(ErrorCode(self->errc, self->ac),
186 ::std::move(self->value));
189 promise.SetValue(value);
192 #ifndef DOXYGEN_SHOULD_SKIP_THIS 195 template class Sdo::DownloadRequest<bool>;
196 template class Sdo::UploadRequest<bool>;
197 template class Sdo::DownloadRequestWrapper<bool>;
198 template class Sdo::UploadRequestWrapper<bool>;
199 template class Sdo::AsyncDownloadRequest<bool>;
200 template class Sdo::AsyncUploadRequest<bool>;
203 template class Sdo::DownloadRequest<int8_t>;
204 template class Sdo::UploadRequest<int8_t>;
205 template class Sdo::DownloadRequestWrapper<int8_t>;
206 template class Sdo::UploadRequestWrapper<int8_t>;
207 template class Sdo::AsyncDownloadRequest<int8_t>;
208 template class Sdo::AsyncUploadRequest<int8_t>;
211 template class Sdo::DownloadRequest<int16_t>;
212 template class Sdo::UploadRequest<int16_t>;
213 template class Sdo::DownloadRequestWrapper<int16_t>;
214 template class Sdo::UploadRequestWrapper<int16_t>;
215 template class Sdo::AsyncDownloadRequest<int16_t>;
216 template class Sdo::AsyncUploadRequest<int16_t>;
219 template class Sdo::DownloadRequest<int32_t>;
220 template class Sdo::UploadRequest<int32_t>;
221 template class Sdo::DownloadRequestWrapper<int32_t>;
222 template class Sdo::UploadRequestWrapper<int32_t>;
223 template class Sdo::AsyncDownloadRequest<int32_t>;
224 template class Sdo::AsyncUploadRequest<int32_t>;
227 template class Sdo::DownloadRequest<uint8_t>;
228 template class Sdo::UploadRequest<uint8_t>;
229 template class Sdo::DownloadRequestWrapper<uint8_t>;
230 template class Sdo::UploadRequestWrapper<uint8_t>;
231 template class Sdo::AsyncDownloadRequest<uint8_t>;
232 template class Sdo::AsyncUploadRequest<uint8_t>;
235 template class Sdo::DownloadRequest<uint16_t>;
236 template class Sdo::UploadRequest<uint16_t>;
237 template class Sdo::DownloadRequestWrapper<uint16_t>;
238 template class Sdo::UploadRequestWrapper<uint16_t>;
239 template class Sdo::AsyncDownloadRequest<uint16_t>;
240 template class Sdo::AsyncUploadRequest<uint16_t>;
243 template class Sdo::DownloadRequest<uint32_t>;
244 template class Sdo::UploadRequest<uint32_t>;
245 template class Sdo::DownloadRequestWrapper<uint32_t>;
246 template class Sdo::UploadRequestWrapper<uint32_t>;
247 template class Sdo::AsyncDownloadRequest<uint32_t>;
248 template class Sdo::AsyncUploadRequest<uint32_t>;
251 template class Sdo::DownloadRequest<float>;
252 template class Sdo::UploadRequest<float>;
253 template class Sdo::DownloadRequestWrapper<float>;
254 template class Sdo::UploadRequestWrapper<float>;
255 template class Sdo::AsyncDownloadRequest<float>;
256 template class Sdo::AsyncUploadRequest<float>;
259 template class Sdo::DownloadRequest<::std::string>;
260 template class Sdo::UploadRequest<::std::string>;
261 template class Sdo::DownloadRequestWrapper<::std::string>;
262 template class Sdo::UploadRequestWrapper<::std::string>;
263 template class Sdo::AsyncDownloadRequest<::std::string>;
264 template class Sdo::AsyncUploadRequest<::std::string>;
267 template class Sdo::DownloadRequest<::std::vector<uint8_t>>;
268 template class Sdo::UploadRequest<::std::vector<uint8_t>>;
269 template class Sdo::DownloadRequestWrapper<::std::vector<uint8_t>>;
270 template class Sdo::UploadRequestWrapper<::std::vector<uint8_t>>;
271 template class Sdo::AsyncDownloadRequest<::std::vector<uint8_t>>;
272 template class Sdo::AsyncUploadRequest<::std::vector<uint8_t>>;
275 template class Sdo::DownloadRequest<::std::basic_string<char16_t>>;
276 template class Sdo::UploadRequest<::std::basic_string<char16_t>>;
277 template class Sdo::DownloadRequestWrapper<::std::basic_string<char16_t>>;
278 template class Sdo::UploadRequestWrapper<::std::basic_string<char16_t>>;
279 template class Sdo::AsyncDownloadRequest<::std::basic_string<char16_t>>;
280 template class Sdo::AsyncUploadRequest<::std::basic_string<char16_t>>;
288 template class Sdo::DownloadRequest<double>;
289 template class Sdo::UploadRequest<double>;
290 template class Sdo::DownloadRequestWrapper<double>;
291 template class Sdo::UploadRequestWrapper<double>;
292 template class Sdo::AsyncDownloadRequest<double>;
293 template class Sdo::AsyncUploadRequest<double>;
300 template class Sdo::DownloadRequest<int64_t>;
301 template class Sdo::UploadRequest<int64_t>;
302 template class Sdo::DownloadRequestWrapper<int64_t>;
303 template class Sdo::UploadRequestWrapper<int64_t>;
304 template class Sdo::AsyncDownloadRequest<int64_t>;
305 template class Sdo::AsyncUploadRequest<int64_t>;
313 template class Sdo::DownloadRequest<uint64_t>;
314 template class Sdo::UploadRequest<uint64_t>;
315 template class Sdo::DownloadRequestWrapper<uint64_t>;
316 template class Sdo::UploadRequestWrapper<uint64_t>;
317 template class Sdo::AsyncDownloadRequest<uint64_t>;
318 template class Sdo::AsyncUploadRequest<uint64_t>;
320 #endif // !DOXYGEN_SHOULD_SKIP_THIS 327 : impl_(new
Impl_(net, dev, num)) {}
331 Sdo& Sdo::operator=(
Sdo&&) =
default;
336 Sdo::Submit(RequestBase_& op) {
342 return impl_->Cancel(&op, ac);
347 return impl_->Cancel(
nullptr, ac);
350 Sdo::Impl_::Impl_(
CANNet* net,
CODev* dev, uint8_t num)
352 aio_queue_init(&queue);
355 Sdo::Impl_::Impl_(
COCSDO* sdo_,
int timeout)
356 : sdo(sdo_, [=](
COCSDO* sdo) { sdo->setTimeout(timeout); }) {
357 aio_queue_init(&queue);
363 Sdo::Impl_::Submit(RequestBase_& req) {
365 req.GetExecutor().OnTaskStarted();
373 bool first = aio_queue_empty(&queue);
374 aio_queue_push(&queue, &req);
375 if (first) req.OnRequest(
this);
380 Sdo::Impl_::Cancel(RequestBase_* req,
SdoErrc ac) {
382 aio_queue_init(&queue_);
384 if (!req || req != aio_queue_front(&queue)) {
385 auto task = aio_queue_pop(&queue);
386 aio_queue_move(&queue_, &queue, req);
387 if (task) aio_queue_push(&queue, task);
388 req = task && !req ?
static_cast<RequestBase_*
>(task) :
nullptr;
392 assert(req == aio_queue_front(&queue));
393 sdo->abortReq(static_cast<uint32_t>(ac));
397 if (req) n += n < ::std::numeric_limits<decltype(n)>::max();
401 template <
class T,
class U>
403 Sdo::Impl_::OnRequest(uint16_t idx, uint8_t subidx, U&& value) {
404 constexpr
auto N = co_type_traits_T<T>::index;
406 auto task = aio_queue_front(&queue);
408 auto& req = *
static_cast<Sdo::RequestBase_*
>(task);
411 if (sdo->dnReq<N, Impl_, &Impl_::OnDnCon>(
412 idx, subidx, ::std::forward<U>(value),
this) == -1) {
420 Sdo::Impl_::OnRequest(uint16_t idx, uint8_t subidx) {
421 auto task = aio_queue_front(&queue);
423 auto& req = *
static_cast<Sdo::RequestBase_*
>(task);
426 if (sdo->upReq<T, Impl_, &Impl_::OnUpCon<T>>(idx, subidx,
this) == -1) {
433 Sdo::Impl_::OnDnCon(COCSDO*, uint16_t idx, uint8_t subidx,
434 uint32_t ac) noexcept {
435 auto task = aio_queue_pop(&queue);
437 auto& req = *
static_cast<Sdo::RequestBase_*
>(task);
449 Sdo::Impl_::OnUpCon(COCSDO*, uint16_t idx, uint8_t subidx, uint32_t ac,
451 auto task = aio_queue_pop(&queue);
453 auto& req = *
static_cast<Sdo::UploadRequestBase_<T>*
>(task);
459 req.value = ::std::move(value);
465 Sdo::Impl_::OnTaskFinished(RequestBase_& req) noexcept {
466 auto exec = req.GetExecutor();
468 exec.OnTaskFinished();
470 auto task = aio_queue_front(&queue);
471 if (task)
static_cast<Sdo::RequestBase_*
>(task)->OnRequest(
this);
The internal implementation of the Client-SDO queue.
int errnum2c(errnum_t errnum)
Transforms a platform-independent error number to a native error code.
Sdo()
Default-constructs an invalid Client-SDO queue.
An opaque CANopen Client-SDO service type.
An opaque CANopen device type.
Resource not available: SDO connection.
inline ::std::shared_ptr< T > make_shared_c(Args &&... args)
Creates an instance of a trivial, standard layout or incomplete C type and wraps it in a std::shared_...
SdoErrc
The SDO abort codes.
~Sdo()
Destructs the Client-SDO queue.
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function...
This header file is part of the C++ CANopen application library; it contains the timeout conversion f...
int ToTimeout(const ::std::chrono::duration< Rep, Period > &d)
Converts a duration to an SDO timeout.
This is the internal header file of the C++ CANopen application library.
::std::size_t Cancel(SdoErrc ac)
Aborts the ongoing and all pending SDO requests.
This header file is part of the CANopen library; it contains the C++ interface of the Client-SDO decl...
Global namespace for the Lely Industries N.V. libraries.
An opaque CAN network interface type.
This header file is part of the C++ CANopen master library; it contains the Client-SDO queue declarat...