mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #12319 from maciejbocianski/fix_userallocatedevent_imp
Fix userallocatedevent imppull/12617/head
commit
d5f034b637
|
@ -1003,14 +1003,14 @@ static void test_equeue_user_allocated_event_post()
|
|||
|
||||
uint8_t touched = 0;
|
||||
user_allocated_event e1 = { { 0, 0, 0, NULL, NULL, NULL, 0, -1, NULL, NULL }, 0 };
|
||||
user_allocated_event e2 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
|
||||
user_allocated_event e3 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
|
||||
user_allocated_event e4 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
|
||||
user_allocated_event e2 = { { 0, 0, 0, NULL, NULL, NULL, 10, 10, NULL, NULL }, 0 };
|
||||
user_allocated_event e3 = { { 0, 0, 0, NULL, NULL, NULL, 10, 10, NULL, NULL }, 0 };
|
||||
user_allocated_event e4 = { { 0, 0, 0, NULL, NULL, NULL, 10, 10, NULL, NULL }, 0 };
|
||||
user_allocated_event e5 = { { 0, 0, 0, NULL, NULL, NULL, 0, -1, NULL, NULL }, 0 };
|
||||
|
||||
TEST_ASSERT_NOT_EQUAL(0, equeue_call(&q, simple_func, &touched));
|
||||
TEST_ASSERT_EQUAL_INT(0, equeue_call(&q, simple_func, &touched));
|
||||
TEST_ASSERT_EQUAL_INT(0, equeue_call(&q, simple_func, &touched));
|
||||
TEST_ASSERT_NOT_EQUAL(0, equeue_call_every(&q, 10, simple_func, &touched));
|
||||
TEST_ASSERT_EQUAL_INT(0, equeue_call_every(&q, 10, simple_func, &touched));
|
||||
TEST_ASSERT_EQUAL_INT(0, equeue_call_every(&q, 10, simple_func, &touched));
|
||||
|
||||
equeue_post_user_allocated(&q, simple_func, &e1.e);
|
||||
equeue_post_user_allocated(&q, simple_func, &e2.e);
|
||||
|
@ -1018,8 +1018,9 @@ static void test_equeue_user_allocated_event_post()
|
|||
equeue_post_user_allocated(&q, simple_func, &e4.e);
|
||||
equeue_post_user_allocated(&q, simple_func, &e5.e);
|
||||
equeue_cancel_user_allocated(&q, &e3.e);
|
||||
equeue_cancel_user_allocated(&q, &e3.e);
|
||||
|
||||
equeue_dispatch(&q, 1);
|
||||
equeue_dispatch(&q, 11);
|
||||
|
||||
TEST_ASSERT_EQUAL_UINT8(1, touched);
|
||||
TEST_ASSERT_EQUAL_UINT8(1, e1.touched);
|
||||
|
@ -1028,13 +1029,16 @@ static void test_equeue_user_allocated_event_post()
|
|||
TEST_ASSERT_EQUAL_UINT8(1, e4.touched);
|
||||
TEST_ASSERT_EQUAL_UINT8(1, e5.touched);
|
||||
|
||||
equeue_dispatch(&q, 10);
|
||||
e3.e.target = 10; // set target as it's modified by equeue_call
|
||||
e3.e.period = 10; // set period as it's reset by equeue_cancel
|
||||
equeue_post_user_allocated(&q, simple_func, &e3.e);
|
||||
equeue_dispatch(&q, 101);
|
||||
|
||||
TEST_ASSERT_EQUAL_UINT8(1, touched);
|
||||
TEST_ASSERT_EQUAL_UINT8(11, touched);
|
||||
TEST_ASSERT_EQUAL_UINT8(1, e1.touched);
|
||||
TEST_ASSERT_EQUAL_UINT8(1, e2.touched);
|
||||
TEST_ASSERT_EQUAL_UINT8(0, e3.touched);
|
||||
TEST_ASSERT_EQUAL_UINT8(1, e4.touched);
|
||||
TEST_ASSERT_EQUAL_UINT8(11, e2.touched);
|
||||
TEST_ASSERT_EQUAL_UINT8(10, e3.touched);
|
||||
TEST_ASSERT_EQUAL_UINT8(11, e4.touched);
|
||||
TEST_ASSERT_EQUAL_UINT8(1, e5.touched);
|
||||
|
||||
equeue_destroy(&q);
|
||||
|
|
|
@ -363,14 +363,18 @@ void mixed_dynamic_static_events_queue_test()
|
|||
|
||||
EventTest e1_test;
|
||||
Event<void()> e1 = queue.event(&e1_test, &EventTest::f0);
|
||||
e1.delay(10);
|
||||
e1.period(10);
|
||||
int id1 = e1.post();
|
||||
TEST_ASSERT_NOT_EQUAL(0, id1);
|
||||
EventTest e2_test;
|
||||
Event<void()> e2 = queue.event(&e2_test, &EventTest::f1, 3);
|
||||
e2.period(10);
|
||||
int id2 = e2.post();
|
||||
TEST_ASSERT_NOT_EQUAL(0, id2);
|
||||
EventTest e3_test;
|
||||
Event<void()> e3 = queue.event(&e3_test, &EventTest::f5, 1, 2, 3, 4, 5);
|
||||
e3.period(10);
|
||||
int id3 = e3.post();
|
||||
TEST_ASSERT_NOT_EQUAL(0, id3);
|
||||
|
||||
|
@ -391,8 +395,11 @@ void mixed_dynamic_static_events_queue_test()
|
|||
TEST_ASSERT_EQUAL(false, ue0.try_call());
|
||||
ue1.call_on(&queue);
|
||||
TEST_ASSERT_EQUAL(false, ue1.try_call());
|
||||
ue2.period(10);
|
||||
ue2.call_on(&queue);
|
||||
TEST_ASSERT_EQUAL(false, ue2.try_call());
|
||||
ue3.period(10);
|
||||
ue3.delay(50);
|
||||
ue3.call_on(&queue);
|
||||
TEST_ASSERT_EQUAL(false, ue3.try_call());
|
||||
ue4.call_on(&queue);
|
||||
|
@ -401,21 +408,36 @@ void mixed_dynamic_static_events_queue_test()
|
|||
ue4.cancel();
|
||||
e2.cancel();
|
||||
|
||||
queue.dispatch(1);
|
||||
queue.dispatch(101);
|
||||
|
||||
TEST_ASSERT_EQUAL(true, touched);
|
||||
TEST_ASSERT_EQUAL(1, ue1_test.counter);
|
||||
TEST_ASSERT_EQUAL(3, ue2_test.counter);
|
||||
TEST_ASSERT_EQUAL(15, ue3_test.counter);
|
||||
TEST_ASSERT_EQUAL(33, ue2_test.counter);
|
||||
TEST_ASSERT_EQUAL(90, ue3_test.counter);
|
||||
TEST_ASSERT_EQUAL(0, ue4_test.counter);
|
||||
TEST_ASSERT_EQUAL(1, e1_test.counter);
|
||||
TEST_ASSERT_EQUAL(10, e1_test.counter);
|
||||
TEST_ASSERT_EQUAL(0, e2_test.counter);
|
||||
TEST_ASSERT_EQUAL(15, e3_test.counter);
|
||||
TEST_ASSERT_EQUAL(165, e3_test.counter);
|
||||
|
||||
// user allocated event have to be canceled(removed from the queue) before destruction
|
||||
// cancel all periodic user events
|
||||
ue2.cancel();
|
||||
ue3.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static EventQueue g_queue(0);
|
||||
static auto ue0 = g_queue.make_user_allocated_event(func0);
|
||||
static EventTest test1;
|
||||
static auto ue1 = make_user_allocated_event(&test1, &EventTest::f0);
|
||||
static EventTest test2;
|
||||
static auto ue2 = g_queue.make_user_allocated_event(&test2, &EventTest::f1, 3);
|
||||
static EventTest test3;
|
||||
static auto ue3 = make_user_allocated_event(&test3, &EventTest::f5, 1, 2, 3, 4, 5);
|
||||
static EventTest test4;
|
||||
static auto ue4 = g_queue.make_user_allocated_event(&test4, &EventTest::f5, 1, 2, 3, 4, 5);
|
||||
|
||||
|
||||
/** Test that static queue executes user allocated events.
|
||||
*
|
||||
|
@ -429,15 +451,20 @@ void static_events_queue_test()
|
|||
Event<void()> e0 = g_queue.event(func0);
|
||||
TEST_ASSERT_EQUAL(0, e0.post());
|
||||
|
||||
auto ue0 = g_queue.make_user_allocated_event(func0);
|
||||
EventTest test1;
|
||||
auto ue1 = make_user_allocated_event(&test1, &EventTest::f0);
|
||||
EventTest test2;
|
||||
auto ue2 = g_queue.make_user_allocated_event(&test2, &EventTest::f1, 3);
|
||||
EventTest test3;
|
||||
auto ue3 = make_user_allocated_event(&test3, &EventTest::f5, 1, 2, 3, 4, 5);
|
||||
EventTest test4;
|
||||
auto ue4 = g_queue.make_user_allocated_event(&test4, &EventTest::f5, 1, 2, 3, 4, 5);
|
||||
ue0.delay(100);
|
||||
ue0.period(200);
|
||||
|
||||
ue1.delay(100);
|
||||
ue1.period(200);
|
||||
|
||||
ue2.delay(100);
|
||||
ue2.period(200);
|
||||
|
||||
ue3.delay(100);
|
||||
ue3.period(200);
|
||||
|
||||
ue4.delay(100);
|
||||
ue4.period(200);
|
||||
|
||||
ue0.call();
|
||||
TEST_ASSERT_EQUAL(false, ue0.try_call());
|
||||
|
@ -449,16 +476,26 @@ void static_events_queue_test()
|
|||
TEST_ASSERT_EQUAL(false, ue3.try_call());
|
||||
ue4.call();
|
||||
ue4.cancel();
|
||||
ue4.cancel();
|
||||
TEST_ASSERT_EQUAL(true, ue4.try_call());
|
||||
g_queue.cancel(&ue4);
|
||||
g_queue.cancel(&ue4);
|
||||
|
||||
g_queue.dispatch(1);
|
||||
g_queue.dispatch(400);
|
||||
|
||||
TEST_ASSERT_EQUAL(1, test1.counter);
|
||||
TEST_ASSERT_EQUAL(3, test2.counter);
|
||||
TEST_ASSERT_EQUAL(15, test3.counter);
|
||||
TEST_ASSERT_EQUAL(2, test1.counter);
|
||||
TEST_ASSERT_EQUAL(6, test2.counter);
|
||||
TEST_ASSERT_EQUAL(30, test3.counter);
|
||||
TEST_ASSERT_EQUAL(0, test4.counter);
|
||||
|
||||
ue4.delay(1);
|
||||
TEST_ASSERT_EQUAL(true, ue4.try_call());
|
||||
g_queue.dispatch(1);
|
||||
|
||||
TEST_ASSERT_EQUAL(2, test1.counter);
|
||||
TEST_ASSERT_EQUAL(6, test2.counter);
|
||||
TEST_ASSERT_EQUAL(30, test3.counter);
|
||||
TEST_ASSERT_EQUAL(15, test4.counter);
|
||||
}
|
||||
|
||||
// Test setup
|
||||
|
|
|
@ -1072,14 +1072,14 @@ TEST_F(TestEqueue, test_equeue_user_allocated_event_post)
|
|||
|
||||
uint8_t touched = 0;
|
||||
user_allocated_event e1 = { { 0, 0, 0, NULL, NULL, NULL, 0, -1, NULL, NULL }, 0 };
|
||||
user_allocated_event e2 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
|
||||
user_allocated_event e3 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
|
||||
user_allocated_event e4 = { { 0, 0, 0, NULL, NULL, NULL, 1, -1, NULL, NULL }, 0 };
|
||||
user_allocated_event e2 = { { 0, 0, 0, NULL, NULL, NULL, 10, 10, NULL, NULL }, 0 };
|
||||
user_allocated_event e3 = { { 0, 0, 0, NULL, NULL, NULL, 10, 10, NULL, NULL }, 0 };
|
||||
user_allocated_event e4 = { { 0, 0, 0, NULL, NULL, NULL, 10, 10, NULL, NULL }, 0 };
|
||||
user_allocated_event e5 = { { 0, 0, 0, NULL, NULL, NULL, 0, -1, NULL, NULL }, 0 };
|
||||
|
||||
EXPECT_NE(0, equeue_call(&q, simple_func, &touched));
|
||||
EXPECT_EQ(0, equeue_call(&q, simple_func, &touched));
|
||||
EXPECT_EQ(0, equeue_call(&q, simple_func, &touched));
|
||||
EXPECT_NE(0, equeue_call_every(&q, 10, simple_func, &touched));
|
||||
EXPECT_EQ(0, equeue_call_every(&q, 10, simple_func, &touched));
|
||||
EXPECT_EQ(0, equeue_call_every(&q, 10, simple_func, &touched));
|
||||
|
||||
equeue_post_user_allocated(&q, simple_func, &e1.e);
|
||||
equeue_post_user_allocated(&q, simple_func, &e2.e);
|
||||
|
@ -1087,8 +1087,9 @@ TEST_F(TestEqueue, test_equeue_user_allocated_event_post)
|
|||
equeue_post_user_allocated(&q, simple_func, &e4.e);
|
||||
equeue_post_user_allocated(&q, simple_func, &e5.e);
|
||||
equeue_cancel_user_allocated(&q, &e3.e);
|
||||
equeue_cancel_user_allocated(&q, &e3.e);
|
||||
|
||||
equeue_dispatch(&q, 1);
|
||||
equeue_dispatch(&q, 11);
|
||||
|
||||
EXPECT_EQ(1, touched);
|
||||
EXPECT_EQ(1, e1.touched);
|
||||
|
@ -1097,14 +1098,17 @@ TEST_F(TestEqueue, test_equeue_user_allocated_event_post)
|
|||
EXPECT_EQ(1, e4.touched);
|
||||
EXPECT_EQ(1, e5.touched);
|
||||
|
||||
equeue_dispatch(&q, 10);
|
||||
e3.e.target = 10; // set target as it's modified by equeue_call
|
||||
e3.e.period = 10; // set period as it's reset by equeue_cancel
|
||||
equeue_post_user_allocated(&q, simple_func, &e3.e);
|
||||
equeue_dispatch(&q, 101);
|
||||
|
||||
EXPECT_EQ(1, touched);
|
||||
EXPECT_EQ(1, e1.touched);
|
||||
EXPECT_EQ(1, e2.touched);
|
||||
EXPECT_EQ(0, e3.touched);
|
||||
EXPECT_EQ(1, e4.touched);
|
||||
EXPECT_EQ(1, e5.touched);
|
||||
EXPECT_EQ(11, touched);
|
||||
EXPECT_EQ(1 , e1.touched);
|
||||
EXPECT_EQ(11, e2.touched);
|
||||
EXPECT_EQ(10 , e3.touched);
|
||||
EXPECT_EQ(11, e4.touched);
|
||||
EXPECT_EQ(1 , e5.touched);
|
||||
|
||||
equeue_destroy(&q);
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ public:
|
|||
* @param f Function to execute when the event is dispatched
|
||||
* @param args Arguments to bind to the callback
|
||||
*/
|
||||
constexpr UserAllocatedEvent(F f, ArgTs... args) : _e(get_default_equeue_event()), _c(f, args...), _equeue(), _post_ref()
|
||||
constexpr UserAllocatedEvent(F f, ArgTs... args) : _e(get_default_equeue_event()), _c(f, args...), _delay(), _period(-1), _equeue(), _post_ref()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ public:
|
|||
* @param f Function to execute when the event is dispatched
|
||||
* @param args Arguments to bind to the callback
|
||||
*/
|
||||
constexpr UserAllocatedEvent(EventQueue *queue, F f, ArgTs... args) : _e(get_default_equeue_event()), _c(f, args...), _equeue(&queue->_equeue), _post_ref()
|
||||
constexpr UserAllocatedEvent(EventQueue *queue, F f, ArgTs... args) : _e(get_default_equeue_event()), _c(f, args...), _delay(), _period(-1), _equeue(&queue->_equeue), _post_ref()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -215,7 +215,7 @@ public:
|
|||
void delay(int delay)
|
||||
{
|
||||
MBED_ASSERT(!_post_ref);
|
||||
equeue_event_delay(&_e + 1, delay);
|
||||
_delay = delay;
|
||||
}
|
||||
|
||||
/** Configure the period of an event
|
||||
|
@ -225,7 +225,7 @@ public:
|
|||
void period(int period)
|
||||
{
|
||||
MBED_ASSERT(!_post_ref);
|
||||
equeue_event_period(&_e + 1, period);
|
||||
_period = period;
|
||||
}
|
||||
|
||||
/** Cancels posted event
|
||||
|
@ -243,7 +243,7 @@ public:
|
|||
*/
|
||||
bool cancel()
|
||||
{
|
||||
return equeue_cancel_user_allocated(_equeue, &_e);
|
||||
return _post_ref > 0 ? equeue_cancel_user_allocated(_equeue, &_e) : false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -251,6 +251,8 @@ private:
|
|||
friend class EventQueue;
|
||||
struct equeue_event _e;
|
||||
C _c;
|
||||
int _delay;
|
||||
int _period;
|
||||
struct equeue *_equeue;
|
||||
uint8_t _post_ref;
|
||||
|
||||
|
@ -260,17 +262,22 @@ private:
|
|||
return false;
|
||||
}
|
||||
core_util_atomic_incr_u8(&_post_ref, 1);
|
||||
equeue_event_delay(&_e + 1, _delay);
|
||||
equeue_event_period(&_e + 1, _period);
|
||||
equeue_post_user_allocated(_equeue, &EventQueue::function_call<C>, &_e);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool post_on(EventQueue *queue)
|
||||
{
|
||||
MBED_ASSERT(queue);
|
||||
if (_post_ref) {
|
||||
return false;
|
||||
}
|
||||
_equeue = &(queue->_equeue);
|
||||
core_util_atomic_incr_u8(&_post_ref, 1);
|
||||
equeue_event_delay(&_e + 1, _delay);
|
||||
equeue_event_period(&_e + 1, _period);
|
||||
equeue_post_user_allocated(_equeue, &EventQueue::function_call<C>, &_e);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,12 @@
|
|||
// check if the event is allocaded by user - event address is outside queues internal buffer address range
|
||||
#define EQUEUE_IS_USER_ALLOCATED_EVENT(e) ((q->buffer == NULL) || ((uintptr_t)(e) < (uintptr_t)q->buffer) || ((uintptr_t)(e) > ((uintptr_t)q->slab.data)))
|
||||
|
||||
// for user allocated events use event id to track event state
|
||||
enum {
|
||||
EQUEUE_USER_ALLOCATED_EVENT_STATE_INPROGRESS = 1,
|
||||
EQUEUE_USER_ALLOCATED_EVENT_STATE_DONE = 0 // event canceled or dispatching done
|
||||
};
|
||||
|
||||
// calculate the relative-difference between absolute times while
|
||||
// correctly handling overflow conditions
|
||||
static inline int equeue_tickdiff(unsigned a, unsigned b)
|
||||
|
@ -229,7 +235,9 @@ void equeue_dealloc(equeue_t *q, void *p)
|
|||
e->dtor(e + 1);
|
||||
}
|
||||
|
||||
if (!EQUEUE_IS_USER_ALLOCATED_EVENT(e)) {
|
||||
if (EQUEUE_IS_USER_ALLOCATED_EVENT(e)) {
|
||||
e->id = EQUEUE_USER_ALLOCATED_EVENT_STATE_DONE;
|
||||
} else {
|
||||
equeue_mem_dealloc(q, e);
|
||||
}
|
||||
}
|
||||
|
@ -402,6 +410,7 @@ void equeue_post_user_allocated(equeue_t *q, void (*cb)(void *), void *p)
|
|||
unsigned tick = equeue_tick();
|
||||
e->cb = cb;
|
||||
e->target = tick + e->target;
|
||||
e->id = EQUEUE_USER_ALLOCATED_EVENT_STATE_INPROGRESS;
|
||||
|
||||
equeue_enqueue(q, e, tick);
|
||||
equeue_sema_signal(&q->eventsema);
|
||||
|
@ -424,7 +433,7 @@ bool equeue_cancel(equeue_t *q, int id)
|
|||
|
||||
bool equeue_cancel_user_allocated(equeue_t *q, void *e)
|
||||
{
|
||||
if (!e) {
|
||||
if (!e || ((struct equeue_event *)e)->id == EQUEUE_USER_ALLOCATED_EVENT_STATE_DONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -506,7 +515,9 @@ void equeue_dispatch(equeue_t *q, int ms)
|
|||
e->target += e->period;
|
||||
equeue_enqueue(q, e, equeue_tick());
|
||||
} else {
|
||||
equeue_incid(q, e);
|
||||
if (!EQUEUE_IS_USER_ALLOCATED_EVENT(e)) {
|
||||
equeue_incid(q, e);
|
||||
}
|
||||
equeue_dealloc(q, e + 1);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue