26#if !LELY_NO_COAPP_MASTER && !LELY_NO_THREADS
46 Impl_(
const Impl_&) =
delete;
47 Impl_& operator=(
const Impl_&) =
delete;
58 ::std::atomic_flag shutdown{
false};
65 ::std::atomic_flag joined{
false};
90 return impl_->stopped.get_future();
98 }
catch (const ::std::system_error& e) {
101 ec = ::std::make_error_code(::std::errc::operation_canceled);
107 ::std::error_code ec;
109 if (ec) throw ::std::system_error(ec,
"USleep");
115 auto f =
master.AsyncWait(::std::chrono::microseconds(usec), &wait);
118 if (!f.is_ready())
master.CancelWait(*wait);
127 thread(&Impl_::Start, this)
133 [](
void* arg)
noexcept {
143LoopDriver::Impl_::~Impl_() {
149LoopDriver::Impl_::Start() {
150 auto& loop = self->GetLoop();
151 auto exec = self->GetExecutor();
161 self->master.Erase(*self);
173LoopDriver::Impl_::Shutdown() {
174 if (!shutdown.test_and_set()) {
176 self->master.Erase(*self);
178 self->GetLoop().stop();
183LoopDriver::Impl_::Join() {
184 if (!joined.test_and_set()) {
An asynchronous CANopen master.
uint8_t id() const noexcept final
Returns the node-ID.
BasicDriver(ev_exec_t *exec, BasicMaster &master, uint8_t id)
Creates a new driver for a remote CANopen node and registers it with the master.
BasicMaster & master
A reference to the master with which this driver is registered.
A CANopen driver running its own dedicated event loop in a separate thread.
void USleep(uint_least64_t usec)
Runs the event loop for usec microseconds.
T Wait(SdoFuture< T > f)
Waits for the specified future to become ready by running pending tasks on the dedicated event loop o...
LoopDriver(AsyncMaster &master, uint8_t id)
Creates a new CANopen driver and starts a new event loop in a separate thread to execute event handle...
void Join()
Stops the dedicated event loop of the driver and waits until the thread running the event loop finish...
ev::Future< void, void > AsyncStoppped() noexcept
Returns a future which becomes ready once the dedicated event loop of the driver is stopped and the t...
ev::Loop & GetLoop() noexcept
Returns a reference to the dedicated event loop of the driver.
~LoopDriver()
Stops the event loop and terminates the thread in which it was running before destroying the driver.
result_type & get()
Returns the result of a ready future.
::std::size_t wait(ev_future_t *future)
The exception thrown when retrieving the result of a future which is not ready or does not contain a ...
A refence to an I/O context. This class is a wrapper around #io_ctx_t*.
value_type & value()
Returns a reference to the value if *this contains a value, and throws an exception if *this contains...
This is the internal header file of the C++ CANopen application library.
#define IO_SVC_INIT(vptr)
The static initializer for io_svc.
void throw_errc(int errc=get_errc())
Throws an std::system_error exception corresponding to the specified or current (thread-specific) nat...
This header file is part of the C++ CANopen application library; it contains the declarations for the...
The namespace for the C++ CANopen application library.
ev::Future< T, ::std::exception_ptr > SdoFuture
A helper alias template for the type of future used to retrieve the result of an asynchronous SDO req...
The virtual table of an I/O service.
A wait operation suitable for use with a timer queue.
The internal implementation of lely::canopen::LoopDriver.
This header file is part of the C11 and POSIX compatibility library; it includes <threads....
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
Creates a new thread executing func(arg).
int thrd_join(thrd_t thr, int *res)
Joins the thread identified by thr with the current thread by blocking until the other thread has ter...
@ thrd_success
Indicates that the requested operation succeeded.