26 #include <lely/aio/detail/timespec.hpp> 44 if (mutex) mutex->
lock();
48 if (mutex) mutex->
unlock();
51 void operator()(::std::error_code ec) noexcept;
52 void operator()(::std::error_code ec,
int result) noexcept;
54 int OnNext(
const timespec* tp) noexcept;
55 int OnSend(
const can_msg* msg) noexcept;
60 TimerBase::WaitOperation wait_op;
64 CanBusBase::Info info CAN_MSG_INFO_INIT;
67 CanBusBase::ReadOperation read_op;
69 BasicLockable* mutex{
nullptr};
71 unique_c_ptr<CANNet> net;
76 : impl_(new
Impl_(this, timer, bus, mutex)) {}
78 IoContext::~IoContext() =
default;
82 return impl_->timer.GetExecutor();
87 return impl_->net.get();
92 net()->setTime(aio::detail::ToTimespec(impl_->timer.GetClock().GetTime()));
95 IoContext::Impl_::Impl_(
IoContext* self_, TimerBase& timer_, CanBusBase& bus_,
99 wait_op(::
std::ref(*this)),
101 read_op(&msg, &info, ::
std::ref(*this)),
105 net->setTime(aio::detail::ToTimespec(timer.GetClock().GetTime()));
109 net->setNextFunc<Impl_, &Impl_::OnNext>(
this);
112 net->setSendFunc<Impl_, &Impl_::OnSend>(
this);
115 timer.SubmitWait(wait_op);
118 bus.SubmitRead(read_op);
122 IoContext::Impl_::operator()(::std::error_code ec) noexcept {
124 ::std::lock_guard<Impl_> lock(*
this);
127 timer.SubmitWait(wait_op);
131 IoContext::Impl_::operator()(::std::error_code ec,
int result) noexcept {
133 ::std::lock_guard<Impl_> lock(*
this);
136 }
else if (!result) {
137 if (info.state != state) {
138 ::std::swap(info.state, state);
139 self->OnCanState(static_cast<CanState>(state),
140 static_cast<CanState>(info.state));
142 if (info.error != error) {
144 self->OnCanError(static_cast<CanError>(error));
148 bus.SubmitRead(read_op);
152 IoContext::Impl_::OnNext(
const timespec* tp) noexcept {
153 timer.SetTime(TimerBase::time_point(aio::detail::FromTimespec(*tp)));
158 IoContext::Impl_::OnSend(
const can_msg* msg) noexcept {
161 ::std::error_code ec;
162 if (!bus.Write(*msg, ec)) {
A CAN or CAN FD format frame.
unique_c_ptr< T > make_unique_c(Args &&... args)
Creates an instance of a trivial, standard layout or incomplete C type and wraps it in a lely::unique...
#define CAN_MSG_INIT
The static initializer for can_msg.
virtual void unlock()=0
Releases the lock held by the execution agent. Throws no exceptions.
This header file is part of the CAN library; it contains the C++ interface of the CAN network interfa...
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
CANNet * net() const noexcept
Returns a pointer to the internal CAN network interface from <lely/can/net.hpp>.
void SetTime()
Update the CAN network time.
The internal implementation of the I/O context.
virtual void lock()=0
Blocks until a lock can be obtained for the current execution agent (thread, process, task).
The type of objects thrown as exceptions to report a system error with an associated error code...
This header file is part of the C++ CANopen application library; it contains the I/O context declarat...
An abstract interface conforming to the BasicLockable concept.
This is the internal header file of the C++ CANopen application library.
void unlock() override
Releases the lock held by the execution agent. Throws no exceptions.
Global namespace for the Lely Industries N.V. libraries.
An opaque CAN network interface type.
void lock() override
Blocks until a lock can be obtained for the current execution agent (thread, process, task).
aio::ExecutorBase GetExecutor() const noexcept
Returns the executor used to process I/O events on the CAN bus.
IoContext(aio::TimerBase &timer, aio::CanBusBase &bus, BasicLockable *mutex=nullptr)
Creates a new I/O context.