diff --git a/usb/device/utilities/events/PolledQueue.cpp b/usb/device/utilities/events/PolledQueue.cpp new file mode 100644 index 0000000000..562f5f345d --- /dev/null +++ b/usb/device/utilities/events/PolledQueue.cpp @@ -0,0 +1,91 @@ +/* events + * Copyright (c) 2018 ARM Limited + * + * 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. + */ +#include "events/PolledQueue.h" + +#include "events/mbed_events.h" +#include "platform/Callback.h" + + +PolledQueue::PolledQueue(mbed::Callback cb): _cb(cb) +{ + +} + +PolledQueue::~PolledQueue() +{ + +} + +void PolledQueue::dispatch() +{ + core_util_critical_section_enter(); + uint64_t buf[MBED_MAX_TASK_SIZE / sizeof(uint64_t)]; + + while (true) { + + // Atomically dequeue the task and copy the callback + TaskBase *task = _list.dequeue(); + if (!task) { + break; + } + MBED_ASSERT(sizeof(buf) >= task_size(task)); + TaskBase::run_callback_t callback = task_start(task, (uint8_t*)buf, sizeof(buf)); + + // Run the callback outside the critical section + core_util_critical_section_exit(); + callback((uint8_t*)buf); + core_util_critical_section_enter(); + + // Finish + task_finish(task); + task = NULL; + + } + + core_util_critical_section_exit(); +} + +void PolledQueue::attach(mbed::Callback cb) +{ + core_util_critical_section_enter(); + + _cb = cb; + + core_util_critical_section_exit(); +} + +void PolledQueue::post(TaskBase *task) +{ + core_util_critical_section_enter(); + + bool empty = _list.head() == NULL; + _list.remove(task); + _list.enqueue(task); + if (empty && _cb) { + _cb(); + } + + core_util_critical_section_exit(); +} + +void PolledQueue::cancel(TaskBase *task) +{ + core_util_critical_section_enter(); + + _list.remove(task); + + core_util_critical_section_exit(); +} diff --git a/usb/device/utilities/events/PolledQueue.h b/usb/device/utilities/events/PolledQueue.h new file mode 100644 index 0000000000..89afb111b2 --- /dev/null +++ b/usb/device/utilities/events/PolledQueue.h @@ -0,0 +1,71 @@ +/* events + * Copyright (c) 2018 ARM Limited + * + * 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 POLLED_QUEUE_H +#define POLLED_QUEUE_H + +#include "events/TaskQueue.h" +#include "platform/Callback.h" +#include "LinkedList.h" +namespace events { +/** \addtogroup events */ + + +/** PolledQueue + * + * This class is an implementation of TaskQueue which is + * processed synchronously by calls to dispatch. + * @ingroup events + */ +class PolledQueue: public TaskQueue { +public: + + /** Create a PolledQueue + * + * Create an event queue. + * + * @param cb Callback called when dispatch needs to be called + */ + PolledQueue(mbed::Callback cb=NULL); + + virtual ~PolledQueue(); + + virtual void post(TaskBase *event); + + virtual void cancel(TaskBase *event); + + /** + * Process all the events in this queue + */ + void dispatch(); + + /** + * Attach a callback indicating that this queue needs to be processed + * + * @param cb Callback called when dispatch needs to be called + */ + void attach(mbed::Callback cb); + +protected: + + mbed::Callback _cb; + LinkedList _list; + +}; + +} +#endif +