Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AsyncOp.cpp Source File

AsyncOp.cpp

00001 /*
00002  * Copyright (c) 2018-2019, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "AsyncOp.h"
00019 #include "mbed_critical.h"
00020 #include "mbed_assert.h"
00021 
00022 using namespace rtos;
00023 
00024 AsyncOp::AsyncOp():
00025     _list(NULL), _wait(NULL), _aborted(false), _timeout(false)
00026 {
00027 
00028 }
00029 
00030 AsyncOp::AsyncOp(mbed::Callback<void()> &callback):
00031     _list(NULL), _wait(NULL), _aborted(false), _timeout(false)
00032 {
00033     _callback = callback;
00034 }
00035 
00036 AsyncOp::~AsyncOp()
00037 {
00038     MBED_ASSERT(_list == NULL);
00039 }
00040 
00041 void AsyncOp::wait(rtos::Mutex *host_mutex, uint32_t milliseconds)
00042 {
00043     // Optimization so semaphore is only created if necessary
00044     core_util_critical_section_enter();
00045     bool done = _list == NULL;
00046     core_util_critical_section_exit();
00047     if (done) {
00048         return;
00049     }
00050 
00051     // Construct semaphore to wait on
00052     Semaphore sem(0);
00053 
00054     core_util_critical_section_enter();
00055     done = _list == NULL;
00056     // Wait is only allowed to be called from one thread
00057     MBED_ASSERT(_wait == NULL);
00058     _wait = &sem;
00059     core_util_critical_section_exit();
00060 
00061     if (done) {
00062         // Operation was signaled before semaphore was set
00063         return;
00064     }
00065 
00066     if (sem.try_acquire_for(milliseconds)) {
00067         // Operation completion signaled semaphore
00068         return;
00069     }
00070 
00071     _host_lock(host_mutex);
00072     _abort(true);
00073     _host_unlock(host_mutex);
00074 }
00075 
00076 void AsyncOp::abort()
00077 {
00078     // Host lock must be held
00079 
00080     _abort(false);
00081 }
00082 
00083 void AsyncOp::complete()
00084 {
00085     core_util_critical_section_enter();
00086 
00087     mbed::Callback<void()> cb = _callback;
00088     _callback = NULL;
00089     _list = NULL;
00090     if (_wait != NULL) {
00091         _wait->release();
00092     }
00093 
00094     core_util_critical_section_exit();
00095 
00096     if (cb) {
00097         cb();
00098     }
00099 }
00100 
00101 bool AsyncOp::timeout()
00102 {
00103     core_util_critical_section_enter();
00104 
00105     bool ret = _timeout;
00106 
00107     core_util_critical_section_exit();
00108     return ret;
00109 }
00110 
00111 void AsyncOp::_abort(bool timeout)
00112 {
00113     // host lock must be held
00114 
00115     core_util_critical_section_enter();
00116     OperationListBase *list = _list;
00117     if (list) {
00118         _callback = NULL;
00119         _aborted = true;
00120         _wait = NULL;
00121         _timeout = timeout;
00122         _list = NULL;
00123     }
00124     core_util_critical_section_exit();
00125     if (list) {
00126         list->remove(this);
00127     }
00128 }
00129 
00130 void AsyncOp::_host_lock(rtos::Mutex *host_mutex)
00131 {
00132     if (host_mutex) {
00133         host_mutex->lock();
00134     } else {
00135         core_util_critical_section_enter();
00136     }
00137 }
00138 
00139 void AsyncOp::_host_unlock(rtos::Mutex *host_mutex)
00140 {
00141     if (host_mutex) {
00142         host_mutex->unlock();
00143     } else {
00144         core_util_critical_section_exit();
00145     }
00146 }