mirror of https://github.com/ARMmbed/mbed-os.git
657 lines
16 KiB
C++
657 lines
16 KiB
C++
/*
|
|
* Copyright (c) 2018-2019, Arm Limited and affiliates.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef MBED_TASK_H
|
|
#define MBED_TASK_H
|
|
|
|
#include "events/EventQueue.h"
|
|
#include "drivers/internal/TaskBase.h"
|
|
#include "platform/mbed_assert.h"
|
|
#include "platform/Callback.h"
|
|
|
|
namespace events {
|
|
/** \addtogroup events-internal-api
|
|
* \ingroup mbed-os-internal
|
|
* @{
|
|
*/
|
|
|
|
|
|
template<typename F, typename A1 = void, typename A2 = void, typename A3 = void, typename A4 = void, typename A5 = void>
|
|
struct AllArgs;
|
|
|
|
template<typename B0>
|
|
struct AllArgs<B0> {
|
|
typedef AllArgs<B0> Self;
|
|
B0 b0;
|
|
|
|
AllArgs(B0 b0 = B0()): b0(b0) {}
|
|
|
|
template <typename T, typename _>
|
|
struct Operations {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
s->b0();
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
typedef Operations<B0, void> ops;
|
|
};
|
|
|
|
template<typename B0, typename B1>
|
|
struct AllArgs<B0, B1> {
|
|
typedef AllArgs<B0, B1> Self;
|
|
B0 b0;
|
|
B1 b1;
|
|
|
|
AllArgs(B0 b0 = B0(), B1 b1 = B1()): b0(b0), b1(b1) {}
|
|
|
|
template <typename T, typename _>
|
|
struct Operations {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
s->b0(s->b1);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T *, R(U::*)()> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))();
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T, R(U::*)() const> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))();
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T, R(U::*)() volatile> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))();
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T, R(U::*)() const volatile> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))();
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
typedef Operations<B0, B1> ops;
|
|
};
|
|
|
|
template<typename B0, typename B1, typename B2>
|
|
struct AllArgs<B0, B1, B2> {
|
|
typedef AllArgs<B0, B1, B2> Self;
|
|
B0 b0;
|
|
B1 b1;
|
|
B2 b2;
|
|
|
|
|
|
AllArgs(B0 b0 = B0(), B1 b1 = B1(), B2 b2 = B2()): b0(b0), b1(b1), b2(b2) {}
|
|
|
|
template <typename T, typename _>
|
|
struct Operations {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
s->b0(s->b1, s->b2);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T *, R(U::*)(B2)> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))(s->b2);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T, R(U::*)(B2) const> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))(s->b2);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T, R(U::*)(B2) volatile> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))(s->b2);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T, R(U::*)(B2) const volatile> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))(s->b2);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
typedef Operations<B0, B1> ops;
|
|
};
|
|
|
|
template<typename B0, typename B1, typename B2, typename B3>
|
|
struct AllArgs<B0, B1, B2, B3> {
|
|
typedef AllArgs<B0, B1, B2, B3> Self;
|
|
B0 b0;
|
|
B1 b1;
|
|
B2 b2;
|
|
B3 b3;
|
|
|
|
|
|
AllArgs(B0 b0 = B0(), B1 b1 = B1(), B2 b2 = B2(), B3 b3 = B3()): b0(b0), b1(b1), b2(b2), b3(b3) {}
|
|
|
|
template <typename T, typename _>
|
|
struct Operations {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
s->b0(s->b1, s->b2, s->b3);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T *, R(U::*)(B2, B3)> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))(s->b2, s->b3);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T, R(U::*)(B2, B3) const> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))(s->b2, s->b3);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T, R(U::*)(B2, B3) volatile> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))(s->b2, s->b3);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T, R(U::*)(B2, B3) const volatile> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))(s->b2, s->b3);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
typedef Operations<B0, B1> ops;
|
|
};
|
|
|
|
template<typename B0, typename B1, typename B2, typename B3, typename B4>
|
|
struct AllArgs<B0, B1, B2, B3, B4> {
|
|
typedef AllArgs<B0, B1, B2, B3, B4> Self;
|
|
B0 b0;
|
|
B1 b1;
|
|
B2 b2;
|
|
B3 b3;
|
|
B4 b4;
|
|
|
|
|
|
AllArgs(B0 b0 = B0(), B1 b1 = B1(), B2 b2 = B2(), B3 b3 = B3(), B4 b4 = B4()): b0(b0), b1(b1), b2(b2), b3(b3), b4(b4) {}
|
|
|
|
template <typename T, typename _>
|
|
struct Operations {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
s->b0(s->b1, s->b2, s->b3, s->b4);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T *, R(U::*)(B2, B3, B4)> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))(s->b2, s->b3, s->b4);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T, R(U::*)(B2, B3, B4) const> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))(s->b2, s->b3, s->b4);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T, R(U::*)(B2, B3, B4) volatile> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))(s->b2, s->b3, s->b4);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T, R(U::*)(B2, B3, B4) const volatile> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))(s->b2, s->b3, s->b4);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
typedef Operations<B0, B1> ops;
|
|
};
|
|
|
|
template<typename B0, typename B1, typename B2, typename B3, typename B4, typename B5>
|
|
struct AllArgs {
|
|
typedef AllArgs<B0, B1, B2, B3, B4, B5> Self;
|
|
B0 b0;
|
|
B1 b1;
|
|
B2 b2;
|
|
B3 b3;
|
|
B4 b4;
|
|
B5 b5;
|
|
|
|
|
|
AllArgs(B0 b0 = B0(), B1 b1 = B1(), B2 b2 = B2(), B3 b3 = B3(), B4 b4 = B4(), B5 b5 = B5()): b0(b0), b1(b1), b2(b2), b3(b3), b4(b4), b5(b5) {}
|
|
|
|
template <typename T, typename _>
|
|
struct Operations {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
s->b0(s->b1, s->b2, s->b3, s->b4, s->b5);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T *, R(U::*)(B2, B3, B4, B5)> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))(s->b2, s->b3, s->b4, s->b5);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T, R(U::*)(B2, B3, B4, B5) const> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))(s->b2, s->b3, s->b4, s->b5);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T, R(U::*)(B2, B3, B4, B5) volatile> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))(s->b2, s->b3, s->b4, s->b5);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
template <typename T, typename R, typename U>
|
|
struct Operations<T, R(U::*)(B2, B3, B4, B5) const volatile> {
|
|
static void copy(void *_dest, void *_src)
|
|
{
|
|
new (_dest) Self(*(Self *)_src);
|
|
}
|
|
|
|
static void call(void *data)
|
|
{
|
|
Self *s = static_cast<Self *>(data);
|
|
((s->b0)->*(s->b1))(s->b2, s->b3, s->b4, s->b5);
|
|
s->~Self();
|
|
}
|
|
};
|
|
|
|
typedef Operations<B0, B1> ops;
|
|
};
|
|
|
|
|
|
template <typename F>
|
|
class Task;
|
|
|
|
template <typename R>
|
|
class Task<R()>: public TaskBase {
|
|
public:
|
|
|
|
Task(TaskQueue *q = NULL, mbed::Callback<R()> cb = mbed::Callback<R()>())
|
|
: TaskBase(q), _args(cb)
|
|
{
|
|
}
|
|
|
|
Task &operator=(mbed::Callback<R()> cb)
|
|
{
|
|
_args.b0 = cb;
|
|
return *this;
|
|
}
|
|
|
|
void call()
|
|
{
|
|
post();
|
|
}
|
|
|
|
protected:
|
|
|
|
virtual uint32_t size()
|
|
{
|
|
return sizeof(_args);
|
|
}
|
|
|
|
virtual run_callback_t start(void *data, uint32_t max_size)
|
|
{
|
|
All::ops::copy(data, (void *)&_args);
|
|
return &All::ops::call;
|
|
}
|
|
|
|
private:
|
|
typedef AllArgs<mbed::Callback<R()> > All;
|
|
All _args;
|
|
};
|
|
|
|
template <typename R, typename A0>
|
|
class Task<R(A0)>: public TaskBase {
|
|
public:
|
|
|
|
Task(TaskQueue *q = NULL, mbed::Callback<R(A0)> cb = mbed::Callback<R(A0)>())
|
|
: TaskBase(q), _args(cb)
|
|
{
|
|
}
|
|
|
|
Task &operator=(mbed::Callback<R(A0)> cb)
|
|
{
|
|
_args.b0 = cb;
|
|
return *this;
|
|
}
|
|
|
|
void call(A0 a0)
|
|
{
|
|
_args.b1 = a0;
|
|
post();
|
|
}
|
|
|
|
protected:
|
|
|
|
virtual uint32_t size()
|
|
{
|
|
return sizeof(_args);
|
|
}
|
|
|
|
virtual run_callback_t start(void *data, uint32_t max_size)
|
|
{
|
|
All::ops::copy(data, (void *)&_args);
|
|
return &All::ops::call;
|
|
}
|
|
|
|
private:
|
|
typedef AllArgs<mbed::Callback<R(A0)>, A0> All;
|
|
All _args;
|
|
};
|
|
|
|
/** Task
|
|
*
|
|
* Representation of a postable task
|
|
*/
|
|
template <typename R, typename A0, typename A1>
|
|
class Task<R(A0, A1)>: public TaskBase {
|
|
public:
|
|
|
|
/**
|
|
* Construct a new task
|
|
*
|
|
* @param q TaskQueue to post to
|
|
* @param cb Callback to run
|
|
*/
|
|
Task(TaskQueue *q = NULL, mbed::Callback<R(A0, A1)> cb = mbed::Callback<R(A0, A1)>())
|
|
: TaskBase(q), _args(cb)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Set the callback of this task
|
|
*
|
|
* @param cb Callback to run
|
|
*/
|
|
Task &operator=(mbed::Callback<R(A0, A1)> cb)
|
|
{
|
|
_args.b0 = cb;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Post this task for execution
|
|
*
|
|
* The number of arguments to call should match
|
|
* the type of the callback. For example Task<void(int, int)>
|
|
* expects two integers as arguments to call, while Task<void()>
|
|
* expects no arguments.
|
|
*
|
|
* @param a0 First callback parameter
|
|
* @param a1 Second callback parameter
|
|
*/
|
|
void call(A0 a0, A1 a1)
|
|
{
|
|
_args.b1 = a0;
|
|
_args.b2 = a1;
|
|
post();
|
|
}
|
|
|
|
protected:
|
|
|
|
virtual uint32_t size()
|
|
{
|
|
return sizeof(_args);
|
|
}
|
|
|
|
virtual run_callback_t start(void *data, uint32_t max_size)
|
|
{
|
|
All::ops::copy(data, (void *)&_args);
|
|
return &All::ops::call;
|
|
}
|
|
|
|
private:
|
|
typedef AllArgs<mbed::Callback<R(A0, A1)>, A0, A1> All;
|
|
All _args;
|
|
};
|
|
|
|
/** @}*/
|
|
|
|
}
|
|
|
|
#endif
|