update
Revision 0:bfff72fb3650, committed 2021-04-08
- Comitter:
- kwengryn3
- Date:
- Thu Apr 08 16:43:07 2021 +0000
- Commit message:
- update;
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ATCmdParser.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,324 @@ +/* Copyright (c) 2017 ARM Limited + * 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. + * + * @section DESCRIPTION + * + * Parser for the AT command syntax + * + */ +#ifndef MBED_ATCMDPARSER_H +#define MBED_ATCMDPARSER_H + +#include <cstdarg> +#include "Callback.h" +#include "NonCopyable.h" +#include "FileHandle.h" + +namespace mbed { + +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_ATCmdParser ATCmdParser class + * @{ + */ + +/** + * Parser class for parsing AT commands + * + * Here are some examples: + * @code + * UARTSerial serial = UARTSerial(D1, D0); + * ATCmdParser at = ATCmdParser(&serial, "\r\n"); + * int value; + * char buffer[100]; + * + * at.send("AT") && at.recv("OK"); + * at.send("AT+CWMODE=%d", 3) && at.recv("OK"); + * at.send("AT+CWMODE?") && at.recv("+CWMODE:%d\r\nOK", &value); + * at.recv("+IPD,%d:", &value); + * at.read(buffer, value); + * at.recv("OK"); + * @endcode + */ + +class ATCmdParser : private NonCopyable<ATCmdParser> { +private: + // File handle + // Not owned by ATCmdParser + FileHandle *_fh; + + int _buffer_size; + char *_buffer; + int _timeout; + + // Parsing information + const char *_output_delimiter; + int _output_delim_size; + int _oob_cb_count; + char _in_prev; + bool _dbg_on; + bool _aborted; + + struct oob { + unsigned len; + const char *prefix; + mbed::Callback<void()> cb; + oob *next; + }; + oob *_oobs; + +public: + + /** + * Constructor + * + * @param fh A FileHandle to the digital interface, used for AT commands + * @param output_delimiter End of command-line termination + * @param buffer_size Size of internal buffer for transaction + * @param timeout Timeout of the connection + * @param debug Turns on/off debug output for AT commands + */ + ATCmdParser(FileHandle *fh, const char *output_delimiter = "\r", + int buffer_size = 256, int timeout = 8000, bool debug = false) + : _fh(fh), _buffer_size(buffer_size), _oob_cb_count(0), _in_prev(0), _oobs(NULL) + { + _buffer = new char[buffer_size]; + set_timeout(timeout); + set_delimiter(output_delimiter); + debug_on(debug); + } + + /** + * Destructor + */ + ~ATCmdParser() + { + while (_oobs) { + struct oob *oob = _oobs; + _oobs = oob->next; + delete oob; + } + delete[] _buffer; + } + + /** + * Allows timeout to be changed between commands + * + * @param timeout ATCmdParser APIs (read/write/send/recv ..etc) throw an + * error if no response is received in `timeout` duration + */ + void set_timeout(int timeout) + { + _timeout = timeout; + } + + /** + * For backward compatibility. + * @deprecated Do not use this function. This function has been replaced with set_timeout for consistency. + * + * Please use set_timeout(int) API only from now on. + * Allows timeout to be changed between commands + * + * @param timeout ATCmdParser APIs (read/write/send/recv ..etc) throw an + * error if no response is received in `timeout` duration + * + */ + MBED_DEPRECATED_SINCE("mbed-os-5.5.0", "Replaced with set_timeout for consistency") + void setTimeout(int timeout) + { + set_timeout(timeout); + } + + /** + * Sets string of characters to use as line delimiters + * + * @param output_delimiter String of characters to use as line delimiters + */ + void set_delimiter(const char *output_delimiter) + { + _output_delimiter = output_delimiter; + _output_delim_size = strlen(output_delimiter); + } + + /** + * For backwards compatibility. + * @deprecated Do not use this function. This function has been replaced with set_delimiter for consistency. + * + * Please use set_delimiter(const char *) API only from now on. + * Sets string of characters to use as line delimiters + * + * @param output_delimiter string of characters to use as line delimiters + */ + MBED_DEPRECATED_SINCE("mbed-os-5.5.0", "Replaced with set_delimiter for consistency") + void setDelimiter(const char *output_delimiter) + { + set_delimiter(output_delimiter); + } + + /** + * Allows traces from modem to be turned on or off + * + * @param on Set as 1 to turn on traces and 0 to disable traces. + */ + void debug_on(uint8_t on) + { + _dbg_on = (on) ? 1 : 0; + } + + /** + * For backward compatibility. + * @deprecated Do not use this function. This function has been replaced with debug_on for consistency. + * + * Allows traces from modem to be turned on or off + * + * @param on Set as 1 to turn on traces and 0 to disable traces. + */ + MBED_DEPRECATED_SINCE("mbed-os-5.5.0", "Replaced with debug_on for consistency") + void debugOn(uint8_t on) + { + debug_on(on); + } + + /** + * Sends an AT command + * + * Sends a formatted command using printf style formatting + * @see printf + * + * @param command printf-like format string of command to send which + * is appended with a newline + * @param ... all printf-like arguments to insert into command + * @return true only if command is successfully sent + */ + bool send(const char *command, ...) MBED_PRINTF_METHOD(1, 2); + + bool vsend(const char *command, std::va_list args); + + /** + * Receive an AT response + * + * Receives a formatted response using scanf style formatting + * @see scanf + * + * Responses are parsed line at a time. + * Any received data that does not match the response is ignored until + * a timeout occurs. + * + * @param response scanf-like format string of response to expect + * @param ... all scanf-like arguments to extract from response + * @return true only if response is successfully matched + */ + bool recv(const char *response, ...) MBED_SCANF_METHOD(1, 2); + + bool vrecv(const char *response, std::va_list args); + + /** + * Write a single byte to the underlying stream + * + * @param c The byte to write + * @return The byte that was written or -1 during a timeout + */ + int putc(char c); + + /** + * Get a single byte from the underlying stream + * + * @return The byte that was read or -1 during a timeout + */ + int getc(); + + /** + * Write an array of bytes to the underlying stream + * + * @param data The array of bytes to write + * @param size Number of bytes to write + * @return number of bytes written or -1 on failure + */ + int write(const char *data, int size); + + /** + * Read an array of bytes from the underlying stream + * + * @param data The buffer for filling the read bytes + * @param size Number of bytes to read + * @return number of bytes read or -1 on failure + */ + int read(char *data, int size); + + /** + * Direct printf to underlying stream + * @see printf + * + * @param format Format string to pass to printf + * @param ... Variable arguments to printf + * @return number of bytes written or -1 on failure + */ + int printf(const char *format, ...) MBED_PRINTF_METHOD(1, 2); + + int vprintf(const char *format, std::va_list args); + + /** + * Direct scanf on underlying stream + * @see scanf + * + * @param format Format string to pass to scanf + * @param ... Variable arguments to scanf + * @return number of bytes read or -1 on failure + */ + int scanf(const char *format, ...) MBED_SCANF_METHOD(1, 2); + + int vscanf(const char *format, std::va_list args); + + /** + * Attach a callback for out-of-band data + * + * @param prefix String on when to initiate callback + * @param func Callback to call when string is read + * @note out-of-band data is only processed during a scanf call + */ + void oob(const char *prefix, mbed::Callback<void()> func); + + /** + * Flushes the underlying stream + */ + void flush(); + + /** + * Abort current recv + * + * Can be called from out-of-band handler to interrupt the current + * recv operation. + */ + void abort(); + + /** + * Process out-of-band data + * + * Process out-of-band data in the receive buffer. This function + * returns immediately if there is no data to process. + * + * @return true if out-of-band data processed, false otherwise + */ + bool process_oob(void); +}; + +/**@}*/ + +/**@}*/ + +} //namespace mbed + +#endif //MBED_ATCMDPARSER_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CThunk.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,174 @@ + +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_CThunk CThunk class + * @{ + */ +/* General C++ Object Thunking class + * + * - allows direct callbacks to non-static C++ class functions + * - keeps track for the corresponding class instance + * - supports an optional context parameter for the called function + * - ideally suited for class object receiving interrupts (NVIC_SetVector) + * + * Copyright (c) 2014-2015 ARM Limited + * 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. + */ + +/* General C++ Object Thunking class + * + * - allows direct callbacks to non-static C++ class functions + * - keeps track for the corresponding class instance + * - supports an optional context parameter for the called function + * - ideally suited for class object receiving interrupts (NVIC_SetVector) + */ + +#ifndef __CTHUNK_H__ +#define __CTHUNK_H__ + +#include "CThunkBase.h" + +/** + * Class for created a pointer with data bound to it + * + * @note Synchronization level: Not protected + */ +template<class T> +class CThunk: public CThunkBase { +public: + typedef void (T::*CCallbackSimple)(void); + typedef void (T::*CCallback)(void *context); + + inline CThunk(T *instance) + { + init(instance, NULL, NULL); + } + + inline CThunk(T *instance, CCallback callback) + { + init(instance, callback, NULL); + } + + ~CThunk() + { + cthunk_free(_entry); + _entry = NULL; + } + + inline CThunk(T *instance, CCallbackSimple callback) + { + init(instance, (CCallback)callback, NULL); + } + + inline CThunk(T &instance, CCallback callback) + { + init(instance, callback, NULL); + } + + inline CThunk(T &instance, CCallbackSimple callback) + { + init(instance, (CCallback)callback, NULL); + } + + inline CThunk(T &instance, CCallback callback, void *context) + { + init(instance, callback, context); + } + + inline void callback(CCallback callback) + { + _callback = callback; + } + + inline void callback(CCallbackSimple callback) + { + _callback_simple = callback; + } + + inline void context(void *context) + { + _context = context; + } + + inline void context(uint32_t context) + { + _context = (void *)context; + } + + inline uint32_t entry(void) + { + if (_entry == NULL) { + _entry = cthunk_alloc(this); + } + return (uint32_t)_entry; + } + + /* get thunk entry point for connecting rhunk to an IRQ table */ + inline operator CThunkEntry(void) + { + return (CThunkEntry)entry(); + } + + /* get thunk entry point for connecting rhunk to an IRQ table */ + inline operator uint32_t(void) + { + return entry(); + } + + /* simple test function */ + inline void call(void) + { + (((CThunkEntry)(entry()))()); + } + +private: + T *_instance; + void *_context; + union { + CCallbackSimple _callback_simple; + CCallback _callback; + }; + + CThunkEntry _entry; + + static void trampoline(CThunkBase *base) + { + CThunk<T> *self = static_cast<CThunk<T>*>(base); + T *instance = self->_instance; + void *context = self->_context; + CCallback callback = self->_callback; + + if (instance && callback) { + (instance->*callback)(context); + } + } + + inline void init(T *instance, CCallback callback, void *context) + { + _instance = instance; + _context = context; + _callback = callback; + _trampoline = &trampoline; + _entry = 0; + } +}; + +/**@}*/ + +/**@}*/ + +#endif/*__CTHUNK_H__*/ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CThunkBase.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,78 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * 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 __CTHUNK_BASE_H__ +#define __CTHUNK_BASE_H__ + +/* IRQ/Exception compatible thunk entry function */ +typedef void (*CThunkEntry)(void); + +class CThunkBase { +protected: + typedef void (*Trampoline)(CThunkBase *); + + Trampoline _trampoline; + + /* + * Allocate a CThunkEntry which can be called without arguments + * + * Calling the CThunkEntry invokes the _trampoline of the + * given cthunk. This function traps if there are no more + * free thunks. + */ + static CThunkEntry cthunk_alloc(CThunkBase *cthunk); + + /* + * Free a cthunk_entry so it can be reused + */ + static void cthunk_free(CThunkEntry cthunk_entry); + +private: + typedef void (*CthunkFree)(CThunkEntry cthunk_entry); + + /* + * Table of thunk functions + */ + static const CThunkEntry _thunk_table[MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX]; + + /* + * Table of active CThunk classes + */ + static CThunkBase *_thunk_storage[MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX]; + + /* + * Lazily initialized free function pointer + */ + static CthunkFree _cthunk_free_real; + + /* + * Actual free function + */ + static void cthunk_free_real(CThunkEntry cthunk_entry); + + /* + * Template function which stored in the _thunk_table + */ + template<int N> + static void thunk_entry() + { + _thunk_storage[N]->_trampoline(_thunk_storage[N]); + } +}; + +#endif/*__CTHUNK_BASE_H__*/ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CallChain.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,265 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * 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_CALLCHAIN_H +#define MBED_CALLCHAIN_H + +#include "platform/Callback.h" +#include "platform/mbed_toolchain.h" +#include "platform/NonCopyable.h" +#include <string.h> + +namespace mbed { + + +typedef Callback<void()> *pFunctionPointer_t; +class CallChainLink; + +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_CallChain CallChain class + * @{ + */ + +/** Group one or more functions in an instance of a CallChain, then call them in + * sequence using CallChain::call(). Used mostly by the interrupt chaining code, + * but can be used for other purposes. + * + * @deprecated Do not use this class. This class is not part of the public API of mbed-os and is being removed in the future. + * @note Synchronization level: Not protected + * + * Example: + * @code + * #include "mbed.h" + * + * CallChain chain; + * + * void first(void) { + * printf("'first' function.\n"); + * } + * + * void second(void) { + * printf("'second' function.\n"); + * } + * + * class Test { + * public: + * void f(void) { + * printf("A::f (class member).\n"); + * } + * }; + * + * int main() { + * Test test; + * + * chain.add(second); + * chain.add_front(first); + * chain.add(&test, &Test::f); + * chain.call(); + * } + * @endcode + */ +class CallChain : private NonCopyable<CallChain> { +public: + /** Create an empty chain + * @deprecated + * Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future. + * + * @param size (optional) Initial size of the chain + */ + MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the " + "public API of mbed-os and is being removed in the future.") + CallChain(int size = 4); + + /** Create an empty chain + * @deprecated + * Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future. + */ + MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the " + "public API of mbed-os and is being removed in the future.") + virtual ~CallChain(); + + /** Add a function at the end of the chain + * + * @deprecated + * Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future. + * + * @param func A pointer to a void function + * + * @returns + * The function object created for 'func' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the " + "public API of mbed-os and is being removed in the future.") + pFunctionPointer_t add(Callback<void()> func); + + /** Add a function at the end of the chain + * + * @param obj pointer to the object to call the member function on + * @param method pointer to the member function to be called + * + * @returns + * The function object created for 'obj' and 'method' + * + * @deprecated + * The add function does not support cv-qualifiers. Replaced by + * add(callback(obj, method)). + */ + template<typename T, typename M> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "The add function does not support cv-qualifiers. Replaced by " + "add(callback(obj, method)).") + pFunctionPointer_t add(T *obj, M method) + { + return add(callback(obj, method)); + } + + /** Add a function at the beginning of the chain + * @deprecated + * Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future. + * + * + * @param func A pointer to a void function + * + * @returns + * The function object created for 'func' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the " + "public API of mbed-os and is being removed in the future.") + pFunctionPointer_t add_front(Callback<void()> func); + + /** Add a function at the beginning of the chain + * + * @param obj pointer to the object to call the member function on + * @param method pointer to the member function to be called + * + * @returns + * The function object created for the object and method pointers + * + * @deprecated + * The add_front function does not support cv-qualifiers. Replaced by + * add_front(callback(obj, method)). + */ + template<typename T, typename M> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "The add_front function does not support cv-qualifiers. Replaced by " + "add_front(callback(obj, method)).") + pFunctionPointer_t add_front(T *obj, M method) + { + return add_front(callback(obj, method)); + } + + /** Get the number of functions in the chain + * @deprecated + * Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future. + * + */ + MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the " + "public API of mbed-os and is being removed in the future.") + int size() const; + + /** Get a function object from the chain + * @deprecated + * Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future. + * + * @param i function object index + * + * @returns + * The function object at position 'i' in the chain + */ + MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the " + "public API of mbed-os and is being removed in the future.") + pFunctionPointer_t get(int i) const; + + /** Look for a function object in the call chain + * @deprecated + * Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future. + * + * @param f the function object to search + * + * @returns + * The index of the function object if found, -1 otherwise. + */ + MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the " + "public API of mbed-os and is being removed in the future.") + int find(pFunctionPointer_t f) const; + + /** Clear the call chain (remove all functions in the chain). + * @deprecated Do not use this function. This class is not part of the public API of mbed-os and is being removed in the future. + */ + MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the " + "public API of mbed-os and is being removed in the future.") + void clear(); + + /** Remove a function object from the chain + * @deprecated + * Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future. + * + * @arg f the function object to remove + * + * @returns + * true if the function object was found and removed, false otherwise. + */ + MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the " + "public API of mbed-os and is being removed in the future.") + bool remove(pFunctionPointer_t f); + + /** Call all the functions in the chain in sequence + * @deprecated + * Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future. + * + */ + MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the " + "public API of mbed-os and is being removed in the future.") + void call(); + + /** + * @deprecated + * Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future. + * + */ + MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the " + "public API of mbed-os and is being removed in the future.") + void operator()(void) + { + call(); + } + + /** + * @deprecated + * Do not use this function, this class is not part of the public API of mbed-os and is being removed in the future. + * + */ + MBED_DEPRECATED_SINCE("mbed-os-5.6", "This class is not part of the " + "public API of mbed-os and is being removed in the future.") + pFunctionPointer_t operator [](int i) const + { + return get(i); + } + +private: + CallChainLink *_chain; +}; + +/**@}*/ + +/**@}*/ + +} // namespace mbed + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Callback.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,4939 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2015 ARM Limited + * 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_CALLBACK_H +#define MBED_CALLBACK_H + +#include <string.h> +#include <stdint.h> +#include <new> +#include "platform/mbed_assert.h" +#include "platform/mbed_toolchain.h" + +namespace mbed { +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_Callback Callback class + * @{ + */ + +/** Callback class based on template specialization + * + * @note Synchronization level: Not protected + */ +template <typename F> +class Callback; + +// Internal sfinae declarations +// +// These are used to eliminate overloads based on type attributes +// 1. Does a function object have a call operator +// 2. Does a function object fit in the available storage +// +// These eliminations are handled cleanly by the compiler and avoid +// massive and misleading error messages when confronted with an +// invalid type (or worse, runtime failures) +namespace detail { +struct nil {}; + +template <bool B, typename R = nil> +struct enable_if { + typedef R type; +}; + +template <typename R> +struct enable_if<false, R> {}; + +template <typename M, M> +struct is_type { + static const bool value = true; +}; +} + +#define MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M) \ + typename detail::enable_if< \ + detail::is_type<M, &F::operator()>::value && \ + sizeof(F) <= sizeof(uintptr_t) \ + >::type = detail::nil() + +/** Callback class based on template specialization + * + * @note Synchronization level: Not protected + */ +template <typename R> +class Callback<R()> { +public: + /** Create a Callback with a static function + * @param func Static function to attach + */ + Callback(R(*func)() = 0) + { + if (!func) { + memset(this, 0, sizeof(Callback)); + } else { + generate(func); + } + } + + /** Attach a Callback + * @param func The Callback to attach + */ + Callback(const Callback<R()> &func) + { + if (func._ops) { + func._ops->move(this, &func); + } + _ops = func._ops; + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(U *obj, R(T::*method)()) + { + generate(method_context<T, R(T::*)()>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const U *obj, R(T::*method)() const) + { + generate(method_context<const T, R(T::*)() const>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(volatile U *obj, R(T::*method)() volatile) + { + generate(method_context<volatile T, R(T::*)() volatile>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const volatile U *obj, R(T::*method)() const volatile) + { + generate(method_context<const volatile T, R(T::*)() const volatile>(obj, method)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(T *), U *arg) + { + generate(function_context<R(*)(T *), T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(const T *), const U *arg) + { + generate(function_context<R(*)(const T *), const T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(volatile T *), volatile U *arg) + { + generate(function_context<R(*)(volatile T *), volatile T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(const volatile T *), const volatile U *arg) + { + generate(function_context<R(*)(const volatile T *), const volatile T>(func, arg)); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)())) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)() const)) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)() volatile)) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)() const volatile)) + { + generate(f); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(U *obj, R(*func)(T *)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(const U *obj, R(*func)(const T *)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(volatile U *obj, R(*func)(volatile T *)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(const volatile U *obj, R(*func)(const volatile T *)) + { + new (this) Callback(func, obj); + } + + /** Destroy a callback + */ + ~Callback() + { + if (_ops) { + _ops->dtor(this); + } + } + + /** Attach a static function + * @param func Static function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)()) + { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a Callback + * @param func The Callback to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const Callback<R()> &func) + { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(U *obj, R(T::*method)()) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const U *obj, R(T::*method)() const) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(volatile U *obj, R(T::*method)() volatile) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const volatile U *obj, R(T::*method)() const volatile) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(T *), U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(const T *), const U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(volatile T *), volatile U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(const volatile T *), const volatile U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)())) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)() const)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)() volatile)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)() const volatile)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(U *obj, R(*func)(T *)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(const U *obj, R(*func)(const T *)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(volatile U *obj, R(*func)(volatile T *)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(const volatile U *obj, R(*func)(const volatile T *)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Assign a callback + */ + Callback &operator=(const Callback &that) + { + if (this != &that) { + this->~Callback(); + new (this) Callback(that); + } + + return *this; + } + + /** Call the attached function + */ + R call() const + { + MBED_ASSERT(_ops); + return _ops->call(this); + } + + /** Call the attached function + */ + R operator()() const + { + return call(); + } + + /** Test if function has been attached + */ + operator bool() const + { + return _ops; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) + { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) + { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + * @return the value as determined by func which is of + * type and determined by the signature of func + */ + static R thunk(void *func) + { + return static_cast<Callback *>(func)->call(); + } + +private: + // Stored as pointer to function and pointer to optional object + // Function pointer is stored as union of possible function types + // to guarantee proper size and alignment + struct _class; + union { + void (*_staticfunc)(); + void (*_boundfunc)(_class *); + void (_class::*_methodfunc)(); + } _func; + void *_obj; + + // Dynamically dispatched operations + const struct ops { + R(*call)(const void *); + void (*move)(void *, const void *); + void (*dtor)(void *); + } *_ops; + + // Generate operations for function object + template <typename F> + void generate(const F &f) + { + static const ops ops = { + &Callback::function_call<F>, + &Callback::function_move<F>, + &Callback::function_dtor<F>, + }; + + MBED_STATIC_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F), + "Type F must not exceed the size of the Callback class"); + memset(this, 0, sizeof(Callback)); + new (this) F(f); + _ops = &ops; + } + + // Function attributes + template <typename F> + static R function_call(const void *p) + { + return (*(F *)p)(); + } + + template <typename F> + static void function_move(void *d, const void *p) + { + new (d) F(*(F *)p); + } + + template <typename F> + static void function_dtor(void *p) + { + ((F *)p)->~F(); + } + + // Wrappers for functions with context + template <typename O, typename M> + struct method_context { + M method; + O *obj; + + method_context(O *obj, M method) + : method(method), obj(obj) {} + + R operator()() const + { + return (obj->*method)(); + } + }; + + template <typename F, typename A> + struct function_context { + F func; + A *arg; + + function_context(F func, A *arg) + : func(func), arg(arg) {} + + R operator()() const + { + return func(arg); + } + }; +}; + +/** Callback class based on template specialization + * + * @note Synchronization level: Not protected + */ +template <typename R, typename A0> +class Callback<R(A0)> { +public: + /** Create a Callback with a static function + * @param func Static function to attach + */ + Callback(R(*func)(A0) = 0) + { + if (!func) { + memset(this, 0, sizeof(Callback)); + } else { + generate(func); + } + } + + /** Attach a Callback + * @param func The Callback to attach + */ + Callback(const Callback<R(A0)> &func) + { + if (func._ops) { + func._ops->move(this, &func); + } + _ops = func._ops; + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(U *obj, R(T::*method)(A0)) + { + generate(method_context<T, R(T::*)(A0)>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const U *obj, R(T::*method)(A0) const) + { + generate(method_context<const T, R(T::*)(A0) const>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(volatile U *obj, R(T::*method)(A0) volatile) + { + generate(method_context<volatile T, R(T::*)(A0) volatile>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const volatile U *obj, R(T::*method)(A0) const volatile) + { + generate(method_context<const volatile T, R(T::*)(A0) const volatile>(obj, method)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(T *, A0), U *arg) + { + generate(function_context<R(*)(T *, A0), T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(const T *, A0), const U *arg) + { + generate(function_context<R(*)(const T *, A0), const T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(volatile T *, A0), volatile U *arg) + { + generate(function_context<R(*)(volatile T *, A0), volatile T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(const volatile T *, A0), const volatile U *arg) + { + generate(function_context<R(*)(const volatile T *, A0), const volatile T>(func, arg)); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0))) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0) const)) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0) volatile)) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0) const volatile)) + { + generate(f); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(U *obj, R(*func)(T *, A0)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(const U *obj, R(*func)(const T *, A0)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(volatile U *obj, R(*func)(volatile T *, A0)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(const volatile U *obj, R(*func)(const volatile T *, A0)) + { + new (this) Callback(func, obj); + } + + /** Destroy a callback + */ + ~Callback() + { + if (_ops) { + _ops->dtor(this); + } + } + + /** Attach a static function + * @param func Static function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(A0)) + { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a Callback + * @param func The Callback to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const Callback<R(A0)> &func) + { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(U *obj, R(T::*method)(A0)) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const U *obj, R(T::*method)(A0) const) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(volatile U *obj, R(T::*method)(A0) volatile) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const volatile U *obj, R(T::*method)(A0) const volatile) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(T *, A0), U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(const T *, A0), const U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(volatile T *, A0), volatile U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(const volatile T *, A0), const volatile U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0))) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0) const)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0) volatile)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0) const volatile)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(U *obj, R(*func)(T *, A0)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(const U *obj, R(*func)(const T *, A0)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(volatile U *obj, R(*func)(volatile T *, A0)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(const volatile U *obj, R(*func)(const volatile T *, A0)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Assign a callback + */ + Callback &operator=(const Callback &that) + { + if (this != &that) { + this->~Callback(); + new (this) Callback(that); + } + + return *this; + } + + /** Call the attached function + */ + R call(A0 a0) const + { + MBED_ASSERT(_ops); + return _ops->call(this, a0); + } + + /** Call the attached function + */ + R operator()(A0 a0) const + { + return call(a0); + } + + /** Test if function has been attached + */ + operator bool() const + { + return _ops; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) + { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) + { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + * @param a0 An argument to be called with function func + * @return the value as determined by func which is of + * type and determined by the signature of func + */ + static R thunk(void *func, A0 a0) + { + return static_cast<Callback *>(func)->call(a0); + } + +private: + // Stored as pointer to function and pointer to optional object + // Function pointer is stored as union of possible function types + // to guarantee proper size and alignment + struct _class; + union { + void (*_staticfunc)(A0); + void (*_boundfunc)(_class *, A0); + void (_class::*_methodfunc)(A0); + } _func; + void *_obj; + + // Dynamically dispatched operations + const struct ops { + R(*call)(const void *, A0); + void (*move)(void *, const void *); + void (*dtor)(void *); + } *_ops; + + // Generate operations for function object + template <typename F> + void generate(const F &f) + { + static const ops ops = { + &Callback::function_call<F>, + &Callback::function_move<F>, + &Callback::function_dtor<F>, + }; + + MBED_STATIC_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F), + "Type F must not exceed the size of the Callback class"); + memset(this, 0, sizeof(Callback)); + new (this) F(f); + _ops = &ops; + } + + // Function attributes + template <typename F> + static R function_call(const void *p, A0 a0) + { + return (*(F *)p)(a0); + } + + template <typename F> + static void function_move(void *d, const void *p) + { + new (d) F(*(F *)p); + } + + template <typename F> + static void function_dtor(void *p) + { + ((F *)p)->~F(); + } + + // Wrappers for functions with context + template <typename O, typename M> + struct method_context { + M method; + O *obj; + + method_context(O *obj, M method) + : method(method), obj(obj) {} + + R operator()(A0 a0) const + { + return (obj->*method)(a0); + } + }; + + template <typename F, typename A> + struct function_context { + F func; + A *arg; + + function_context(F func, A *arg) + : func(func), arg(arg) {} + + R operator()(A0 a0) const + { + return func(arg, a0); + } + }; +}; + +/** Callback class based on template specialization + * + * @note Synchronization level: Not protected + */ +template <typename R, typename A0, typename A1> +class Callback<R(A0, A1)> { +public: + /** Create a Callback with a static function + * @param func Static function to attach + */ + Callback(R(*func)(A0, A1) = 0) + { + if (!func) { + memset(this, 0, sizeof(Callback)); + } else { + generate(func); + } + } + + /** Attach a Callback + * @param func The Callback to attach + */ + Callback(const Callback<R(A0, A1)> &func) + { + if (func._ops) { + func._ops->move(this, &func); + } + _ops = func._ops; + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(U *obj, R(T::*method)(A0, A1)) + { + generate(method_context<T, R(T::*)(A0, A1)>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const U *obj, R(T::*method)(A0, A1) const) + { + generate(method_context<const T, R(T::*)(A0, A1) const>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(volatile U *obj, R(T::*method)(A0, A1) volatile) + { + generate(method_context<volatile T, R(T::*)(A0, A1) volatile>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const volatile U *obj, R(T::*method)(A0, A1) const volatile) + { + generate(method_context<const volatile T, R(T::*)(A0, A1) const volatile>(obj, method)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(T *, A0, A1), U *arg) + { + generate(function_context<R(*)(T *, A0, A1), T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(const T *, A0, A1), const U *arg) + { + generate(function_context<R(*)(const T *, A0, A1), const T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(volatile T *, A0, A1), volatile U *arg) + { + generate(function_context<R(*)(volatile T *, A0, A1), volatile T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(const volatile T *, A0, A1), const volatile U *arg) + { + generate(function_context<R(*)(const volatile T *, A0, A1), const volatile T>(func, arg)); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1))) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1) const)) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1) volatile)) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1) const volatile)) + { + generate(f); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(U *obj, R(*func)(T *, A0, A1)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(const U *obj, R(*func)(const T *, A0, A1)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(volatile U *obj, R(*func)(volatile T *, A0, A1)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(const volatile U *obj, R(*func)(const volatile T *, A0, A1)) + { + new (this) Callback(func, obj); + } + + /** Destroy a callback + */ + ~Callback() + { + if (_ops) { + _ops->dtor(this); + } + } + + /** Attach a static function + * @param func Static function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(A0, A1)) + { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a Callback + * @param func The Callback to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const Callback<R(A0, A1)> &func) + { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(U *obj, R(T::*method)(A0, A1)) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const U *obj, R(T::*method)(A0, A1) const) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(volatile U *obj, R(T::*method)(A0, A1) volatile) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const volatile U *obj, R(T::*method)(A0, A1) const volatile) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(T *, A0, A1), U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(const T *, A0, A1), const U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(volatile T *, A0, A1), volatile U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(const volatile T *, A0, A1), const volatile U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1))) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1) const)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1) volatile)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1) const volatile)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(U *obj, R(*func)(T *, A0, A1)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(const U *obj, R(*func)(const T *, A0, A1)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(volatile U *obj, R(*func)(volatile T *, A0, A1)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(const volatile U *obj, R(*func)(const volatile T *, A0, A1)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Assign a callback + */ + Callback &operator=(const Callback &that) + { + if (this != &that) { + this->~Callback(); + new (this) Callback(that); + } + + return *this; + } + + /** Call the attached function + */ + R call(A0 a0, A1 a1) const + { + MBED_ASSERT(_ops); + return _ops->call(this, a0, a1); + } + + /** Call the attached function + */ + R operator()(A0 a0, A1 a1) const + { + return call(a0, a1); + } + + /** Test if function has been attached + */ + operator bool() const + { + return _ops; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) + { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) + { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + * @param a0 An argument to be called with function func + * @param a1 An argument to be called with function func + * @return the value as determined by func which is of + * type and determined by the signature of func + */ + static R thunk(void *func, A0 a0, A1 a1) + { + return static_cast<Callback *>(func)->call(a0, a1); + } + +private: + // Stored as pointer to function and pointer to optional object + // Function pointer is stored as union of possible function types + // to guarantee proper size and alignment + struct _class; + union { + void (*_staticfunc)(A0, A1); + void (*_boundfunc)(_class *, A0, A1); + void (_class::*_methodfunc)(A0, A1); + } _func; + void *_obj; + + // Dynamically dispatched operations + const struct ops { + R(*call)(const void *, A0, A1); + void (*move)(void *, const void *); + void (*dtor)(void *); + } *_ops; + + // Generate operations for function object + template <typename F> + void generate(const F &f) + { + static const ops ops = { + &Callback::function_call<F>, + &Callback::function_move<F>, + &Callback::function_dtor<F>, + }; + + MBED_STATIC_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F), + "Type F must not exceed the size of the Callback class"); + memset(this, 0, sizeof(Callback)); + new (this) F(f); + _ops = &ops; + } + + // Function attributes + template <typename F> + static R function_call(const void *p, A0 a0, A1 a1) + { + return (*(F *)p)(a0, a1); + } + + template <typename F> + static void function_move(void *d, const void *p) + { + new (d) F(*(F *)p); + } + + template <typename F> + static void function_dtor(void *p) + { + ((F *)p)->~F(); + } + + // Wrappers for functions with context + template <typename O, typename M> + struct method_context { + M method; + O *obj; + + method_context(O *obj, M method) + : method(method), obj(obj) {} + + R operator()(A0 a0, A1 a1) const + { + return (obj->*method)(a0, a1); + } + }; + + template <typename F, typename A> + struct function_context { + F func; + A *arg; + + function_context(F func, A *arg) + : func(func), arg(arg) {} + + R operator()(A0 a0, A1 a1) const + { + return func(arg, a0, a1); + } + }; +}; + +/** Callback class based on template specialization + * + * @note Synchronization level: Not protected + */ +template <typename R, typename A0, typename A1, typename A2> +class Callback<R(A0, A1, A2)> { +public: + /** Create a Callback with a static function + * @param func Static function to attach + */ + Callback(R(*func)(A0, A1, A2) = 0) + { + if (!func) { + memset(this, 0, sizeof(Callback)); + } else { + generate(func); + } + } + + /** Attach a Callback + * @param func The Callback to attach + */ + Callback(const Callback<R(A0, A1, A2)> &func) + { + if (func._ops) { + func._ops->move(this, &func); + } + _ops = func._ops; + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(U *obj, R(T::*method)(A0, A1, A2)) + { + generate(method_context<T, R(T::*)(A0, A1, A2)>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const U *obj, R(T::*method)(A0, A1, A2) const) + { + generate(method_context<const T, R(T::*)(A0, A1, A2) const>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(volatile U *obj, R(T::*method)(A0, A1, A2) volatile) + { + generate(method_context<volatile T, R(T::*)(A0, A1, A2) volatile>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const volatile U *obj, R(T::*method)(A0, A1, A2) const volatile) + { + generate(method_context<const volatile T, R(T::*)(A0, A1, A2) const volatile>(obj, method)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(T *, A0, A1, A2), U *arg) + { + generate(function_context<R(*)(T *, A0, A1, A2), T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(const T *, A0, A1, A2), const U *arg) + { + generate(function_context<R(*)(const T *, A0, A1, A2), const T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(volatile T *, A0, A1, A2), volatile U *arg) + { + generate(function_context<R(*)(volatile T *, A0, A1, A2), volatile T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(const volatile T *, A0, A1, A2), const volatile U *arg) + { + generate(function_context<R(*)(const volatile T *, A0, A1, A2), const volatile T>(func, arg)); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2))) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2) const)) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2) volatile)) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2) const volatile)) + { + generate(f); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(U *obj, R(*func)(T *, A0, A1, A2)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(const U *obj, R(*func)(const T *, A0, A1, A2)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(volatile U *obj, R(*func)(volatile T *, A0, A1, A2)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2)) + { + new (this) Callback(func, obj); + } + + /** Destroy a callback + */ + ~Callback() + { + if (_ops) { + _ops->dtor(this); + } + } + + /** Attach a static function + * @param func Static function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(A0, A1, A2)) + { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a Callback + * @param func The Callback to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const Callback<R(A0, A1, A2)> &func) + { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(U *obj, R(T::*method)(A0, A1, A2)) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const U *obj, R(T::*method)(A0, A1, A2) const) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(volatile U *obj, R(T::*method)(A0, A1, A2) volatile) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const volatile U *obj, R(T::*method)(A0, A1, A2) const volatile) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(T *, A0, A1, A2), U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(const T *, A0, A1, A2), const U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(volatile T *, A0, A1, A2), volatile U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(const volatile T *, A0, A1, A2), const volatile U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2))) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2) const)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2) volatile)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2) const volatile)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(U *obj, R(*func)(T *, A0, A1, A2)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(const U *obj, R(*func)(const T *, A0, A1, A2)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(volatile U *obj, R(*func)(volatile T *, A0, A1, A2)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Assign a callback + */ + Callback &operator=(const Callback &that) + { + if (this != &that) { + this->~Callback(); + new (this) Callback(that); + } + + return *this; + } + + /** Call the attached function + */ + R call(A0 a0, A1 a1, A2 a2) const + { + MBED_ASSERT(_ops); + return _ops->call(this, a0, a1, a2); + } + + /** Call the attached function + */ + R operator()(A0 a0, A1 a1, A2 a2) const + { + return call(a0, a1, a2); + } + + /** Test if function has been attached + */ + operator bool() const + { + return _ops; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) + { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) + { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + * @param a0 An argument to be called with function func + * @param a1 An argument to be called with function func + * @param a2 An argument to be called with function func + * @return the value as determined by func which is of + * type and determined by the signature of func + */ + static R thunk(void *func, A0 a0, A1 a1, A2 a2) + { + return static_cast<Callback *>(func)->call(a0, a1, a2); + } + +private: + // Stored as pointer to function and pointer to optional object + // Function pointer is stored as union of possible function types + // to guarantee proper size and alignment + struct _class; + union { + void (*_staticfunc)(A0, A1, A2); + void (*_boundfunc)(_class *, A0, A1, A2); + void (_class::*_methodfunc)(A0, A1, A2); + } _func; + void *_obj; + + // Dynamically dispatched operations + const struct ops { + R(*call)(const void *, A0, A1, A2); + void (*move)(void *, const void *); + void (*dtor)(void *); + } *_ops; + + // Generate operations for function object + template <typename F> + void generate(const F &f) + { + static const ops ops = { + &Callback::function_call<F>, + &Callback::function_move<F>, + &Callback::function_dtor<F>, + }; + + MBED_STATIC_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F), + "Type F must not exceed the size of the Callback class"); + memset(this, 0, sizeof(Callback)); + new (this) F(f); + _ops = &ops; + } + + // Function attributes + template <typename F> + static R function_call(const void *p, A0 a0, A1 a1, A2 a2) + { + return (*(F *)p)(a0, a1, a2); + } + + template <typename F> + static void function_move(void *d, const void *p) + { + new (d) F(*(F *)p); + } + + template <typename F> + static void function_dtor(void *p) + { + ((F *)p)->~F(); + } + + // Wrappers for functions with context + template <typename O, typename M> + struct method_context { + M method; + O *obj; + + method_context(O *obj, M method) + : method(method), obj(obj) {} + + R operator()(A0 a0, A1 a1, A2 a2) const + { + return (obj->*method)(a0, a1, a2); + } + }; + + template <typename F, typename A> + struct function_context { + F func; + A *arg; + + function_context(F func, A *arg) + : func(func), arg(arg) {} + + R operator()(A0 a0, A1 a1, A2 a2) const + { + return func(arg, a0, a1, a2); + } + }; +}; + +/** Callback class based on template specialization + * + * @note Synchronization level: Not protected + */ +template <typename R, typename A0, typename A1, typename A2, typename A3> +class Callback<R(A0, A1, A2, A3)> { +public: + /** Create a Callback with a static function + * @param func Static function to attach + */ + Callback(R(*func)(A0, A1, A2, A3) = 0) + { + if (!func) { + memset(this, 0, sizeof(Callback)); + } else { + generate(func); + } + } + + /** Attach a Callback + * @param func The Callback to attach + */ + Callback(const Callback<R(A0, A1, A2, A3)> &func) + { + if (func._ops) { + func._ops->move(this, &func); + } + _ops = func._ops; + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(U *obj, R(T::*method)(A0, A1, A2, A3)) + { + generate(method_context<T, R(T::*)(A0, A1, A2, A3)>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const U *obj, R(T::*method)(A0, A1, A2, A3) const) + { + generate(method_context<const T, R(T::*)(A0, A1, A2, A3) const>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(volatile U *obj, R(T::*method)(A0, A1, A2, A3) volatile) + { + generate(method_context<volatile T, R(T::*)(A0, A1, A2, A3) volatile>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const volatile U *obj, R(T::*method)(A0, A1, A2, A3) const volatile) + { + generate(method_context<const volatile T, R(T::*)(A0, A1, A2, A3) const volatile>(obj, method)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(T *, A0, A1, A2, A3), U *arg) + { + generate(function_context<R(*)(T *, A0, A1, A2, A3), T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(const T *, A0, A1, A2, A3), const U *arg) + { + generate(function_context<R(*)(const T *, A0, A1, A2, A3), const T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(volatile T *, A0, A1, A2, A3), volatile U *arg) + { + generate(function_context<R(*)(volatile T *, A0, A1, A2, A3), volatile T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(const volatile T *, A0, A1, A2, A3), const volatile U *arg) + { + generate(function_context<R(*)(const volatile T *, A0, A1, A2, A3), const volatile T>(func, arg)); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3))) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3) const)) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3) volatile)) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3) const volatile)) + { + generate(f); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(U *obj, R(*func)(T *, A0, A1, A2, A3)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(const U *obj, R(*func)(const T *, A0, A1, A2, A3)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(volatile U *obj, R(*func)(volatile T *, A0, A1, A2, A3)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2, A3)) + { + new (this) Callback(func, obj); + } + + /** Destroy a callback + */ + ~Callback() + { + if (_ops) { + _ops->dtor(this); + } + } + + /** Attach a static function + * @param func Static function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(A0, A1, A2, A3)) + { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a Callback + * @param func The Callback to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const Callback<R(A0, A1, A2, A3)> &func) + { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(U *obj, R(T::*method)(A0, A1, A2, A3)) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const U *obj, R(T::*method)(A0, A1, A2, A3) const) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(volatile U *obj, R(T::*method)(A0, A1, A2, A3) volatile) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const volatile U *obj, R(T::*method)(A0, A1, A2, A3) const volatile) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(T *, A0, A1, A2, A3), U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(const T *, A0, A1, A2, A3), const U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(volatile T *, A0, A1, A2, A3), volatile U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(const volatile T *, A0, A1, A2, A3), const volatile U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3))) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3) const)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3) volatile)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3) const volatile)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(U *obj, R(*func)(T *, A0, A1, A2, A3)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(const U *obj, R(*func)(const T *, A0, A1, A2, A3)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(volatile U *obj, R(*func)(volatile T *, A0, A1, A2, A3)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2, A3)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Assign a callback + */ + Callback &operator=(const Callback &that) + { + if (this != &that) { + this->~Callback(); + new (this) Callback(that); + } + + return *this; + } + + /** Call the attached function + */ + R call(A0 a0, A1 a1, A2 a2, A3 a3) const + { + MBED_ASSERT(_ops); + return _ops->call(this, a0, a1, a2, a3); + } + + /** Call the attached function + */ + R operator()(A0 a0, A1 a1, A2 a2, A3 a3) const + { + return call(a0, a1, a2, a3); + } + + /** Test if function has been attached + */ + operator bool() const + { + return _ops; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) + { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) + { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + * @param a0 An argument to be called with function func + * @param a1 An argument to be called with function func + * @param a2 An argument to be called with function func + * @param a3 An argument to be called with function func + * @return the value as determined by func which is of + * type and determined by the signature of func + */ + static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3) + { + return static_cast<Callback *>(func)->call(a0, a1, a2, a3); + } + +private: + // Stored as pointer to function and pointer to optional object + // Function pointer is stored as union of possible function types + // to guarantee proper size and alignment + struct _class; + union { + void (*_staticfunc)(A0, A1, A2, A3); + void (*_boundfunc)(_class *, A0, A1, A2, A3); + void (_class::*_methodfunc)(A0, A1, A2, A3); + } _func; + void *_obj; + + // Dynamically dispatched operations + const struct ops { + R(*call)(const void *, A0, A1, A2, A3); + void (*move)(void *, const void *); + void (*dtor)(void *); + } *_ops; + + // Generate operations for function object + template <typename F> + void generate(const F &f) + { + static const ops ops = { + &Callback::function_call<F>, + &Callback::function_move<F>, + &Callback::function_dtor<F>, + }; + + MBED_STATIC_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F), + "Type F must not exceed the size of the Callback class"); + memset(this, 0, sizeof(Callback)); + new (this) F(f); + _ops = &ops; + } + + // Function attributes + template <typename F> + static R function_call(const void *p, A0 a0, A1 a1, A2 a2, A3 a3) + { + return (*(F *)p)(a0, a1, a2, a3); + } + + template <typename F> + static void function_move(void *d, const void *p) + { + new (d) F(*(F *)p); + } + + template <typename F> + static void function_dtor(void *p) + { + ((F *)p)->~F(); + } + + // Wrappers for functions with context + template <typename O, typename M> + struct method_context { + M method; + O *obj; + + method_context(O *obj, M method) + : method(method), obj(obj) {} + + R operator()(A0 a0, A1 a1, A2 a2, A3 a3) const + { + return (obj->*method)(a0, a1, a2, a3); + } + }; + + template <typename F, typename A> + struct function_context { + F func; + A *arg; + + function_context(F func, A *arg) + : func(func), arg(arg) {} + + R operator()(A0 a0, A1 a1, A2 a2, A3 a3) const + { + return func(arg, a0, a1, a2, a3); + } + }; +}; + +/** Callback class based on template specialization + * + * @note Synchronization level: Not protected + */ +template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +class Callback<R(A0, A1, A2, A3, A4)> { +public: + /** Create a Callback with a static function + * @param func Static function to attach + */ + Callback(R(*func)(A0, A1, A2, A3, A4) = 0) + { + if (!func) { + memset(this, 0, sizeof(Callback)); + } else { + generate(func); + } + } + + /** Attach a Callback + * @param func The Callback to attach + */ + Callback(const Callback<R(A0, A1, A2, A3, A4)> &func) + { + if (func._ops) { + func._ops->move(this, &func); + } + _ops = func._ops; + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(U *obj, R(T::*method)(A0, A1, A2, A3, A4)) + { + generate(method_context<T, R(T::*)(A0, A1, A2, A3, A4)>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const U *obj, R(T::*method)(A0, A1, A2, A3, A4) const) + { + generate(method_context<const T, R(T::*)(A0, A1, A2, A3, A4) const>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) volatile) + { + generate(method_context<volatile T, R(T::*)(A0, A1, A2, A3, A4) volatile>(obj, method)); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + */ + template<typename T, typename U> + Callback(const volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) const volatile) + { + generate(method_context<const volatile T, R(T::*)(A0, A1, A2, A3, A4) const volatile>(obj, method)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(T *, A0, A1, A2, A3, A4), U *arg) + { + generate(function_context<R(*)(T *, A0, A1, A2, A3, A4), T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(const T *, A0, A1, A2, A3, A4), const U *arg) + { + generate(function_context<R(*)(const T *, A0, A1, A2, A3, A4), const T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(volatile T *, A0, A1, A2, A3, A4), volatile U *arg) + { + generate(function_context<R(*)(volatile T *, A0, A1, A2, A3, A4), volatile T>(func, arg)); + } + + /** Create a Callback with a static function and bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + */ + template<typename T, typename U> + Callback(R(*func)(const volatile T *, A0, A1, A2, A3, A4), const volatile U *arg) + { + generate(function_context<R(*)(const volatile T *, A0, A1, A2, A3, A4), const volatile T>(func, arg)); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3, A4))) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3, A4) const)) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3, A4) volatile)) + { + generate(f); + } + + /** Create a Callback with a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + */ + template <typename F> + Callback(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3, A4) const volatile)) + { + generate(f); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(U *obj, R(*func)(T *, A0, A1, A2, A3, A4)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(const U *obj, R(*func)(const T *, A0, A1, A2, A3, A4)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(volatile U *obj, R(*func)(volatile T *, A0, A1, A2, A3, A4)) + { + new (this) Callback(func, obj); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to Callback(func, arg) + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to Callback(func, arg)") + Callback(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2, A3, A4)) + { + new (this) Callback(func, obj); + } + + /** Destroy a callback + */ + ~Callback() + { + if (_ops) { + _ops->dtor(this); + } + } + + /** Attach a static function + * @param func Static function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(A0, A1, A2, A3, A4)) + { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a Callback + * @param func The Callback to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const Callback<R(A0, A1, A2, A3, A4)> &func) + { + this->~Callback(); + new (this) Callback(func); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(U *obj, R(T::*method)(A0, A1, A2, A3, A4)) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const U *obj, R(T::*method)(A0, A1, A2, A3, A4) const) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) volatile) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param method Member function to attach + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template<typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) const volatile) + { + this->~Callback(); + new (this) Callback(obj, method); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(T *, A0, A1, A2, A3, A4), U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(const T *, A0, A1, A2, A3, A4), const U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(volatile T *, A0, A1, A2, A3, A4), volatile U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a static function with a bound pointer + * @param func Static function to attach + * @param arg Pointer argument to function + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(R(*func)(const volatile T *, A0, A1, A2, A3, A4), const volatile U *arg) + { + this->~Callback(); + new (this) Callback(func, arg); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3, A4))) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3, A4) const)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3, A4) volatile)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param f Function object to attach + * @note The function object is limited to a single word of storage + * @deprecated + * Replaced by simple assignment 'Callback cb = func' + */ + template <typename F> + MBED_DEPRECATED_SINCE("mbed-os-5.4", + "Replaced by simple assignment 'Callback cb = func") + void attach(const volatile F f, MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, R(F::*)(A0, A1, A2, A3, A4) const volatile)) + { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(U *obj, R(*func)(T *, A0, A1, A2, A3, A4)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(const U *obj, R(*func)(const T *, A0, A1, A2, A3, A4)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(volatile U *obj, R(*func)(volatile T *, A0, A1, A2, A3, A4)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + * @deprecated + * Arguments to callback have been reordered to attach(func, arg) + */ + template <typename T, typename U> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to attach(func, arg)") + void attach(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2, A3, A4)) + { + this->~Callback(); + new (this) Callback(func, obj); + } + + /** Assign a callback + */ + Callback &operator=(const Callback &that) + { + if (this != &that) { + this->~Callback(); + new (this) Callback(that); + } + + return *this; + } + + /** Call the attached function + */ + R call(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const + { + MBED_ASSERT(_ops); + return _ops->call(this, a0, a1, a2, a3, a4); + } + + /** Call the attached function + */ + R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const + { + return call(a0, a1, a2, a3, a4); + } + + /** Test if function has been attached + */ + operator bool() const + { + return _ops; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) + { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) + { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + * @param a0 An argument to be called with function func + * @param a1 An argument to be called with function func + * @param a2 An argument to be called with function func + * @param a3 An argument to be called with function func + * @param a4 An argument to be called with function func + * @return the value as determined by func which is of + * type and determined by the signature of func + */ + static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) + { + return static_cast<Callback *>(func)->call(a0, a1, a2, a3, a4); + } + +private: + // Stored as pointer to function and pointer to optional object + // Function pointer is stored as union of possible function types + // to guarantee proper size and alignment + struct _class; + union { + void (*_staticfunc)(A0, A1, A2, A3, A4); + void (*_boundfunc)(_class *, A0, A1, A2, A3, A4); + void (_class::*_methodfunc)(A0, A1, A2, A3, A4); + } _func; + void *_obj; + + // Dynamically dispatched operations + const struct ops { + R(*call)(const void *, A0, A1, A2, A3, A4); + void (*move)(void *, const void *); + void (*dtor)(void *); + } *_ops; + + // Generate operations for function object + template <typename F> + void generate(const F &f) + { + static const ops ops = { + &Callback::function_call<F>, + &Callback::function_move<F>, + &Callback::function_dtor<F>, + }; + + MBED_STATIC_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F), + "Type F must not exceed the size of the Callback class"); + memset(this, 0, sizeof(Callback)); + new (this) F(f); + _ops = &ops; + } + + // Function attributes + template <typename F> + static R function_call(const void *p, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) + { + return (*(F *)p)(a0, a1, a2, a3, a4); + } + + template <typename F> + static void function_move(void *d, const void *p) + { + new (d) F(*(F *)p); + } + + template <typename F> + static void function_dtor(void *p) + { + ((F *)p)->~F(); + } + + // Wrappers for functions with context + template <typename O, typename M> + struct method_context { + M method; + O *obj; + + method_context(O *obj, M method) + : method(method), obj(obj) {} + + R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const + { + return (obj->*method)(a0, a1, a2, a3, a4); + } + }; + + template <typename F, typename A> + struct function_context { + F func; + A *arg; + + function_context(F func, A *arg) + : func(func), arg(arg) {} + + R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const + { + return func(arg, a0, a1, a2, a3, a4); + } + }; +}; + +// Internally used event type +typedef Callback<void(int)> event_callback_t; + + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @return Callback with inferred type + */ +template <typename R> +Callback<R()> callback(R(*func)() = 0) +{ + return Callback<R()>(func); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @return Callback with inferred type + */ +template <typename R> +Callback<R()> callback(const Callback<R()> &func) +{ + return Callback<R()>(func); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R> +Callback<R()> callback(U *obj, R(T::*method)()) +{ + return Callback<R()>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R> +Callback<R()> callback(const U *obj, R(T::*method)() const) +{ + return Callback<R()>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R> +Callback<R()> callback(volatile U *obj, R(T::*method)() volatile) +{ + return Callback<R()>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R> +Callback<R()> callback(const volatile U *obj, R(T::*method)() const volatile) +{ + return Callback<R()>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R> +Callback<R()> callback(R(*func)(T *), U *arg) +{ + return Callback<R()>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R> +Callback<R()> callback(R(*func)(const T *), const U *arg) +{ + return Callback<R()>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R> +Callback<R()> callback(R(*func)(volatile T *), volatile U *arg) +{ + return Callback<R()>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R> +Callback<R()> callback(R(*func)(const volatile T *), const volatile U *arg) +{ + return Callback<R()>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R()> callback(U *obj, R(*func)(T *)) +{ + return Callback<R()>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R()> callback(const U *obj, R(*func)(const T *)) +{ + return Callback<R()>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R()> callback(volatile U *obj, R(*func)(volatile T *)) +{ + return Callback<R()>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R()> callback(const volatile U *obj, R(*func)(const volatile T *)) +{ + return Callback<R()>(func, obj); +} + + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @return Callback with inferred type + */ +template <typename R, typename A0> +Callback<R(A0)> callback(R(*func)(A0) = 0) +{ + return Callback<R(A0)>(func); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @return Callback with inferred type + */ +template <typename R, typename A0> +Callback<R(A0)> callback(const Callback<R(A0)> &func) +{ + return Callback<R(A0)>(func); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(U *obj, R(T::*method)(A0)) +{ + return Callback<R(A0)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(const U *obj, R(T::*method)(A0) const) +{ + return Callback<R(A0)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(volatile U *obj, R(T::*method)(A0) volatile) +{ + return Callback<R(A0)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(const volatile U *obj, R(T::*method)(A0) const volatile) +{ + return Callback<R(A0)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(R(*func)(T *, A0), U *arg) +{ + return Callback<R(A0)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(R(*func)(const T *, A0), const U *arg) +{ + return Callback<R(A0)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(R(*func)(volatile T *, A0), volatile U *arg) +{ + return Callback<R(A0)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0> +Callback<R(A0)> callback(R(*func)(const volatile T *, A0), const volatile U *arg) +{ + return Callback<R(A0)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0)> callback(U *obj, R(*func)(T *, A0)) +{ + return Callback<R(A0)>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0)> callback(const U *obj, R(*func)(const T *, A0)) +{ + return Callback<R(A0)>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0)> callback(volatile U *obj, R(*func)(volatile T *, A0)) +{ + return Callback<R(A0)>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0)> callback(const volatile U *obj, R(*func)(const volatile T *, A0)) +{ + return Callback<R(A0)>(func, obj); +} + + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @return Callback with inferred type + */ +template <typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(R(*func)(A0, A1) = 0) +{ + return Callback<R(A0, A1)>(func); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @return Callback with inferred type + */ +template <typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(const Callback<R(A0, A1)> &func) +{ + return Callback<R(A0, A1)>(func); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(U *obj, R(T::*method)(A0, A1)) +{ + return Callback<R(A0, A1)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(const U *obj, R(T::*method)(A0, A1) const) +{ + return Callback<R(A0, A1)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(volatile U *obj, R(T::*method)(A0, A1) volatile) +{ + return Callback<R(A0, A1)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(const volatile U *obj, R(T::*method)(A0, A1) const volatile) +{ + return Callback<R(A0, A1)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(R(*func)(T *, A0, A1), U *arg) +{ + return Callback<R(A0, A1)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(R(*func)(const T *, A0, A1), const U *arg) +{ + return Callback<R(A0, A1)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(R(*func)(volatile T *, A0, A1), volatile U *arg) +{ + return Callback<R(A0, A1)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(R(*func)(const volatile T *, A0, A1), const volatile U *arg) +{ + return Callback<R(A0, A1)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0, A1)> callback(U *obj, R(*func)(T *, A0, A1)) +{ + return Callback<R(A0, A1)>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0, A1)> callback(const U *obj, R(*func)(const T *, A0, A1)) +{ + return Callback<R(A0, A1)>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0, A1)> callback(volatile U *obj, R(*func)(volatile T *, A0, A1)) +{ + return Callback<R(A0, A1)>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0, A1)> callback(const volatile U *obj, R(*func)(const volatile T *, A0, A1)) +{ + return Callback<R(A0, A1)>(func, obj); +} + + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @return Callback with inferred type + */ +template <typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(R(*func)(A0, A1, A2) = 0) +{ + return Callback<R(A0, A1, A2)>(func); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @return Callback with inferred type + */ +template <typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(const Callback<R(A0, A1, A2)> &func) +{ + return Callback<R(A0, A1, A2)>(func); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(U *obj, R(T::*method)(A0, A1, A2)) +{ + return Callback<R(A0, A1, A2)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(const U *obj, R(T::*method)(A0, A1, A2) const) +{ + return Callback<R(A0, A1, A2)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(volatile U *obj, R(T::*method)(A0, A1, A2) volatile) +{ + return Callback<R(A0, A1, A2)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(const volatile U *obj, R(T::*method)(A0, A1, A2) const volatile) +{ + return Callback<R(A0, A1, A2)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(R(*func)(T *, A0, A1, A2), U *arg) +{ + return Callback<R(A0, A1, A2)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(R(*func)(const T *, A0, A1, A2), const U *arg) +{ + return Callback<R(A0, A1, A2)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(R(*func)(volatile T *, A0, A1, A2), volatile U *arg) +{ + return Callback<R(A0, A1, A2)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(R(*func)(const volatile T *, A0, A1, A2), const volatile U *arg) +{ + return Callback<R(A0, A1, A2)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0, A1, A2)> callback(U *obj, R(*func)(T *, A0, A1, A2)) +{ + return Callback<R(A0, A1, A2)>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0, A1, A2)> callback(const U *obj, R(*func)(const T *, A0, A1, A2)) +{ + return Callback<R(A0, A1, A2)>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0, A1, A2)> callback(volatile U *obj, R(*func)(volatile T *, A0, A1, A2)) +{ + return Callback<R(A0, A1, A2)>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0, A1, A2)> callback(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2)) +{ + return Callback<R(A0, A1, A2)>(func, obj); +} + + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @return Callback with inferred type + */ +template <typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(R(*func)(A0, A1, A2, A3) = 0) +{ + return Callback<R(A0, A1, A2, A3)>(func); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @return Callback with inferred type + */ +template <typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(const Callback<R(A0, A1, A2, A3)> &func) +{ + return Callback<R(A0, A1, A2, A3)>(func); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(U *obj, R(T::*method)(A0, A1, A2, A3)) +{ + return Callback<R(A0, A1, A2, A3)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(const U *obj, R(T::*method)(A0, A1, A2, A3) const) +{ + return Callback<R(A0, A1, A2, A3)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(volatile U *obj, R(T::*method)(A0, A1, A2, A3) volatile) +{ + return Callback<R(A0, A1, A2, A3)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(const volatile U *obj, R(T::*method)(A0, A1, A2, A3) const volatile) +{ + return Callback<R(A0, A1, A2, A3)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(R(*func)(T *, A0, A1, A2, A3), U *arg) +{ + return Callback<R(A0, A1, A2, A3)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(R(*func)(const T *, A0, A1, A2, A3), const U *arg) +{ + return Callback<R(A0, A1, A2, A3)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(R(*func)(volatile T *, A0, A1, A2, A3), volatile U *arg) +{ + return Callback<R(A0, A1, A2, A3)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(R(*func)(const volatile T *, A0, A1, A2, A3), const volatile U *arg) +{ + return Callback<R(A0, A1, A2, A3)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0, A1, A2, A3)> callback(U *obj, R(*func)(T *, A0, A1, A2, A3)) +{ + return Callback<R(A0, A1, A2, A3)>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0, A1, A2, A3)> callback(const U *obj, R(*func)(const T *, A0, A1, A2, A3)) +{ + return Callback<R(A0, A1, A2, A3)>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0, A1, A2, A3)> callback(volatile U *obj, R(*func)(volatile T *, A0, A1, A2, A3)) +{ + return Callback<R(A0, A1, A2, A3)>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0, A1, A2, A3)> callback(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2, A3)) +{ + return Callback<R(A0, A1, A2, A3)>(func, obj); +} + + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @return Callback with inferred type + */ +template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(R(*func)(A0, A1, A2, A3, A4) = 0) +{ + return Callback<R(A0, A1, A2, A3, A4)>(func); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @return Callback with inferred type + */ +template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(const Callback<R(A0, A1, A2, A3, A4)> &func) +{ + return Callback<R(A0, A1, A2, A3, A4)>(func); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(U *obj, R(T::*method)(A0, A1, A2, A3, A4)) +{ + return Callback<R(A0, A1, A2, A3, A4)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(const U *obj, R(T::*method)(A0, A1, A2, A3, A4) const) +{ + return Callback<R(A0, A1, A2, A3, A4)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) volatile) +{ + return Callback<R(A0, A1, A2, A3, A4)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param method Member function to attach + * @return Callback with inferred type + */ +template<typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(const volatile U *obj, R(T::*method)(A0, A1, A2, A3, A4) const volatile) +{ + return Callback<R(A0, A1, A2, A3, A4)>(obj, method); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(R(*func)(T *, A0, A1, A2, A3, A4), U *arg) +{ + return Callback<R(A0, A1, A2, A3, A4)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(R(*func)(const T *, A0, A1, A2, A3, A4), const U *arg) +{ + return Callback<R(A0, A1, A2, A3, A4)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(R(*func)(volatile T *, A0, A1, A2, A3, A4), volatile U *arg) +{ + return Callback<R(A0, A1, A2, A3, A4)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param func Static function to attach + * @param arg Pointer argument to function + * @return Callback with inferred type + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(R(*func)(const volatile T *, A0, A1, A2, A3, A4), const volatile U *arg) +{ + return Callback<R(A0, A1, A2, A3, A4)>(func, arg); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0, A1, A2, A3, A4)> callback(U *obj, R(*func)(T *, A0, A1, A2, A3, A4)) +{ + return Callback<R(A0, A1, A2, A3, A4)>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0, A1, A2, A3, A4)> callback(const U *obj, R(*func)(const T *, A0, A1, A2, A3, A4)) +{ + return Callback<R(A0, A1, A2, A3, A4)>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0, A1, A2, A3, A4)> callback(volatile U *obj, R(*func)(volatile T *, A0, A1, A2, A3, A4)) +{ + return Callback<R(A0, A1, A2, A3, A4)>(func, obj); +} + +/** Create a callback class with type inferred from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with inferred type + * @deprecated + * Arguments to callback have been reordered to callback(func, arg) + */ +template <typename T, typename U, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +MBED_DEPRECATED_SINCE("mbed-os-5.1", + "Arguments to callback have been reordered to callback(func, arg)") +Callback<R(A0, A1, A2, A3, A4)> callback(const volatile U *obj, R(*func)(const volatile T *, A0, A1, A2, A3, A4)) +{ + return Callback<R(A0, A1, A2, A3, A4)>(func, obj); +} + +/**@}*/ + +/**@}*/ + +} // namespace mbed + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CircularBuffer.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,215 @@ +/* mbed Microcontroller Library + * Copyright (c) 2015 ARM Limited + * 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_CIRCULARBUFFER_H +#define MBED_CIRCULARBUFFER_H + +#include "platform/mbed_critical.h" +#include "platform/mbed_assert.h" + +namespace mbed { + +namespace internal { +/* Detect if CounterType of the Circular buffer is of unsigned type. */ +template<typename T> +struct is_unsigned { + static const bool value = false; +}; +template<> +struct is_unsigned<unsigned char> { + static const bool value = true; +}; +template<> +struct is_unsigned<unsigned short> { + static const bool value = true; +}; +template<> +struct is_unsigned<unsigned int> { + static const bool value = true; +}; +template<> +struct is_unsigned<unsigned long> { + static const bool value = true; +}; +template<> +struct is_unsigned<unsigned long long> { + static const bool value = true; +}; +}; + +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_CircularBuffer CircularBuffer functions + * @{ + */ + +/** Templated Circular buffer class + * + * @note Synchronization level: Interrupt safe + * @note CounterType must be unsigned and consistent with BufferSize + */ +template<typename T, uint32_t BufferSize, typename CounterType = uint32_t> +class CircularBuffer { +public: + CircularBuffer() : _head(0), _tail(0), _full(false) + { + MBED_STATIC_ASSERT( + internal::is_unsigned<CounterType>::value, + "CounterType must be unsigned" + ); + + MBED_STATIC_ASSERT( + (sizeof(CounterType) >= sizeof(uint32_t)) || + (BufferSize < (((uint64_t) 1) << (sizeof(CounterType) * 8))), + "Invalid BufferSize for the CounterType" + ); + } + + ~CircularBuffer() + { + } + + /** Push the transaction to the buffer. This overwrites the buffer if it's + * full + * + * @param data Data to be pushed to the buffer + */ + void push(const T &data) + { + core_util_critical_section_enter(); + if (full()) { + _tail++; + if (_tail == BufferSize) { + _tail = 0; + } + } + _pool[_head++] = data; + if (_head == BufferSize) { + _head = 0; + } + if (_head == _tail) { + _full = true; + } + core_util_critical_section_exit(); + } + + /** Pop the transaction from the buffer + * + * @param data Data to be popped from the buffer + * @return True if the buffer is not empty and data contains a transaction, false otherwise + */ + bool pop(T &data) + { + bool data_popped = false; + core_util_critical_section_enter(); + if (!empty()) { + data = _pool[_tail++]; + if (_tail == BufferSize) { + _tail = 0; + } + _full = false; + data_popped = true; + } + core_util_critical_section_exit(); + return data_popped; + } + + /** Check if the buffer is empty + * + * @return True if the buffer is empty, false if not + */ + bool empty() const + { + core_util_critical_section_enter(); + bool is_empty = (_head == _tail) && !_full; + core_util_critical_section_exit(); + return is_empty; + } + + /** Check if the buffer is full + * + * @return True if the buffer is full, false if not + */ + bool full() const + { + core_util_critical_section_enter(); + bool full = _full; + core_util_critical_section_exit(); + return full; + } + + /** Reset the buffer + * + */ + void reset() + { + core_util_critical_section_enter(); + _head = 0; + _tail = 0; + _full = false; + core_util_critical_section_exit(); + } + + /** Get the number of elements currently stored in the circular_buffer */ + CounterType size() const + { + core_util_critical_section_enter(); + CounterType elements; + if (!_full) { + if (_head < _tail) { + elements = BufferSize + _head - _tail; + } else { + elements = _head - _tail; + } + } else { + elements = BufferSize; + } + core_util_critical_section_exit(); + return elements; + } + + /** Peek into circular buffer without popping + * + * @param data Data to be peeked from the buffer + * @return True if the buffer is not empty and data contains a transaction, false otherwise + */ + bool peek(T &data) const + { + bool data_updated = false; + core_util_critical_section_enter(); + if (!empty()) { + data = _pool[_tail]; + data_updated = true; + } + core_util_critical_section_exit(); + return data_updated; + } + +private: + T _pool[BufferSize]; + CounterType _head; + CounterType _tail; + bool _full; +}; + +/**@}*/ + +/**@}*/ + +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CriticalSectionLock.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2017 ARM Limited + * 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_CRITICALSECTIONLOCK_H +#define MBED_CRITICALSECTIONLOCK_H + +#include "platform/mbed_critical.h" +#include "platform/mbed_toolchain.h" + +namespace mbed { + +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_CriticalSectionLock CriticalSectionLock functions + * @{ + */ + +/** RAII object for disabling, then restoring, interrupt state + * Usage: + * @code + * + * // RAII style usage + * unsigned int atomic_counter_increment(unsigned int &counter) { + * CriticalSectionLock lock; + * // Code in this block will run with interrupts disabled + * // Interrupts will be restored to their previous state automatically + * // at the end of function scope + * return ++counter; + * } + * + * // free locking usage + * unsigned int atomic_counter_decrement(unsigned int &counter) { + * CriticalSectionLock::enable(); + * // Code in this block will run with interrupts disabled + * counter--; + * CriticalSectionLock::disable(); // need explicitly to disable critical section lock + * // interrupts will be restored to their previous state here + * return counter; + * } + * + * @endcode + */ +class CriticalSectionLock { +public: + CriticalSectionLock() + { + core_util_critical_section_enter(); + } + + ~CriticalSectionLock() + { + core_util_critical_section_exit(); + } + + /** Mark the start of a critical section + * @deprecated This function is inconsistent with RAII and is being removed in the future. Replaced by static function CriticalSectionLock::enable. + * + */ + MBED_DEPRECATED_SINCE("mbed-os-5.8", + "This function is inconsistent with RAII and is being removed in the future." + "Replaced by static function CriticalSectionLock::enable.") + void lock() + { + core_util_critical_section_enter(); + } + + /** Mark the end of a critical section + * @deprecated This function is inconsistent with RAII and is being removed in the future. Replaced by static function CriticalSectionLock::enable. + * + */ + MBED_DEPRECATED_SINCE("mbed-os-5.8", + "This function is inconsistent with RAII and is being removed in the future." + "Replaced by static function CriticalSectionLock::disable.") + void unlock() + { + core_util_critical_section_exit(); + } + + /** Mark the start of a critical section + */ + static void enable() + { + core_util_critical_section_enter(); + } + + /** Mark the end of a critical section + */ + static void disable() + { + core_util_critical_section_exit(); + } +}; + +/**@}*/ + +/**@}*/ + +} // namespace mbed + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DeepSleepLock.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,99 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * 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_DEEPSLEEPLOCK_H +#define MBED_DEEPSLEEPLOCK_H + +#include <limits.h> +#include "platform/mbed_power_mgmt.h" +#include "platform/mbed_critical.h" + +namespace mbed { + +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_DeepSleepLock DeepSleepLock functions + * @{ + */ + +/** RAII object for disabling, then restoring the deep sleep mode + * Usage: + * @code + * + * void f() { + * // some code here + * { + * DeepSleepLock lock; + * // Code in this block will run with the deep sleep mode locked + * } + * // deep sleep mode will be restored to their previous state + * } + * @endcode + */ +class DeepSleepLock { +private: + uint16_t _lock_count; + +public: + DeepSleepLock(): _lock_count(1) + { + sleep_manager_lock_deep_sleep(); + } + + ~DeepSleepLock() + { + if (_lock_count) { + sleep_manager_unlock_deep_sleep(); + } + } + + /** Mark the start of a locked deep sleep section + */ + void lock() + { + uint16_t count = core_util_atomic_incr_u16(&_lock_count, 1); + if (1 == count) { + sleep_manager_lock_deep_sleep(); + } + if (0 == count) { + MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OVERFLOW), "DeepSleepLock overflow (> USHRT_MAX)", count); + } + } + + /** Mark the end of a locked deep sleep section + */ + void unlock() + { + uint16_t count = core_util_atomic_decr_u16(&_lock_count, 1); + if (count == 0) { + sleep_manager_unlock_deep_sleep(); + } + if (count == USHRT_MAX) { + core_util_critical_section_exit(); + MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNDERFLOW), "DeepSleepLock underflow (< 0)", count); + } + } +}; + +/**@}*/ + +/**@}*/ + + +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DirHandle.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,178 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * 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_DIRHANDLE_H +#define MBED_DIRHANDLE_H + +#include <stdint.h> +#include "platform/platform.h" +#include "platform/FileHandle.h" +#include "platform/NonCopyable.h" + +namespace mbed { +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_DirHandle DirHandle functions + * @{ + */ + + +/** Represents a directory stream. An opendir function returns + * objects of this type. The core functions are read and seek, + * but only a subset needs to be provided. + * + * If a FileSystemLike class defines the opendir method, then you + * can access the directories of an object of that type by either: + * @code + * DIR *d = opendir("/example/directory"); + * @endcode + * or + * @code + * DIR *d = opendir("/example"); + * @endcode + * to open the root of the file system. + * + * The root directory is considered to contain all FileHandle and + * FileSystem objects, so the DIR pointer returned by opendir("/") + * reflects this. + * + * @note to create a directory, @see Dir + * @note Synchronization level: Set by subclass + */ +class DirHandle : private NonCopyable<DirHandle> { +public: + virtual ~DirHandle() {} + + /** Read the next directory entry + * + * @param ent The directory entry to fill out + * @return 1 on reading a filename, 0 at end of directory, negative error on failure + */ + virtual ssize_t read(struct dirent *ent) = 0; + + /** Close a directory + * + * @return 0 on success, negative error code on failure + */ + virtual int close() = 0; + + /** Set the current position of the directory + * + * @param offset Offset of the location to seek to, + * must be a value returned from tell + */ + virtual void seek(off_t offset) = 0; + + /** Get the current position of the directory + * + * @return Position of the directory that can be passed to rewind + */ + virtual off_t tell() = 0; + + /** Rewind the current position to the beginning of the directory + */ + virtual void rewind() = 0; + + /** Get the sizeof the directory + * + * @return Number of files in the directory + */ + virtual size_t size() + { + off_t off = tell(); + size_t size = 0; + struct dirent *ent = new struct dirent; + + rewind(); + while (read(ent) > 0) { + size += 1; + } + seek(off); + + delete ent; + return size; + } + + /** Closes the directory. + * + * @returns + * 0 on success, + * -1 on error. + * @deprecated Replaced by `int DirHandle::close()' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", "Replaced by DirHandle::close") + virtual int closedir() + { + return close(); + }; + + /** Returns the directory entry at the current position, and + * advances the position to the next entry. + * + * @returns + * A pointer to a dirent structure representing the + * directory entry at the current position, or NULL on reaching + * end of directory or error. + * @deprecated Replaced by `ssize_t DirHandle::read(struct dirent *ent) + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", "Replaced by DirHandle::read") + virtual struct dirent *readdir() + { + static struct dirent ent; + return (read(&ent) > 0) ? &ent : NULL; + } + + /** Resets the position to the beginning of the directory. + * @deprecated Replaced by `void DirHandle::rewind()' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", "Replaced by DirHandle::rewind") + virtual void rewinddir() + { + rewind(); + } + + /** Returns the current position of the DirHandle. + * + * @returns + * the current position, + * -1 on error. + * @deprecated Replaced by `off_t DirHandle::tell()' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", "Replaced by DirHandle::tell") + virtual off_t telldir() + { + return tell(); + } + + /** Sets the position of the DirHandle. + * + * @param location The location to seek to. Must be a value returned by telldir. + * @deprecated Replaced by `void DirHandle::seek(off_t offset)' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", "Replaced by DirHandle::seek") + virtual void seekdir(off_t location) + { + seek(location); + } +}; + +/**@}*/ + +/**@}*/ +} // namespace mbed + +#endif /* MBED_DIRHANDLE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FileBase.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,75 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * 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_FILEBASE_H +#define MBED_FILEBASE_H + +typedef int FILEHANDLE; + +#include "platform/platform.h" +#include "platform/SingletonPtr.h" +#include "platform/PlatformMutex.h" +#include "platform/NonCopyable.h" + +namespace mbed { + +typedef enum { + FilePathType, + FileSystemPathType +} PathType; + +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_FileBase FileBase class + * @{ + */ +/** Class FileBase + * + */ + +class FileBase : private NonCopyable<FileBase> { +public: + FileBase(const char *name, PathType t); + virtual ~FileBase(); + + const char *getName(void); + PathType getPathType(void); + + static FileBase *lookup(const char *name, unsigned int len); + + static FileBase *get(int n); + + void set_as_default(); + +private: + static FileBase *_head; + static FileBase *_default; + static SingletonPtr<PlatformMutex> _mutex; + + FileBase *_next; + const char *const _name; + const PathType _path_type; +}; + +/**@}*/ + +/**@}*/ + +} // namespace mbed + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FileHandle.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,276 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * 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_FILEHANDLE_H +#define MBED_FILEHANDLE_H + +typedef int FILEHANDLE; + +#include <cstdio> +#include "Callback.h" +#include "platform/mbed_poll.h" +#include "platform/platform.h" +#include "platform/NonCopyable.h" + +namespace mbed { +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_FileHandle FileHandle functions + * @{ + */ + + +/** Class FileHandle + * + * An abstract interface that represents operations on a file-like + * object. The core functions are read, write and seek, but only + * a subset of these operations can be provided. + * + * @note to create a file, @see File + * @note Synchronization level: Set by subclass + */ +class FileHandle : private NonCopyable<FileHandle> { +public: + virtual ~FileHandle() {} + + /** Read the contents of a file into a buffer + * + * Devices acting as FileHandles should follow POSIX semantics: + * + * * if no data is available, and nonblocking set, return -EAGAIN + * * if no data is available, and blocking set, wait until some data is available + * * If any data is available, call returns immediately + * + * @param buffer The buffer to read in to + * @param size The number of bytes to read + * @return The number of bytes read, 0 at end of file, negative error on failure + */ + virtual ssize_t read(void *buffer, size_t size) = 0; + + /** Write the contents of a buffer to a file + * + * Devices acting as FileHandles should follow POSIX semantics: + * + * * if blocking, block until all data is written + * * if no data can be written, and nonblocking set, return -EAGAIN + * * if some data can be written, and nonblocking set, write partial + * + * @param buffer The buffer to write from + * @param size The number of bytes to write + * @return The number of bytes written, negative error on failure + */ + virtual ssize_t write(const void *buffer, size_t size) = 0; + + /** Move the file position to a given offset from from a given location + * + * @param offset The offset from whence to move to + * @param whence The start of where to seek + * SEEK_SET to start from beginning of file, + * SEEK_CUR to start from current position in file, + * SEEK_END to start from end of file + * @return The new offset of the file, negative error code on failure + */ + virtual off_t seek(off_t offset, int whence = SEEK_SET) = 0; + + /** Close a file + * + * @return 0 on success, negative error code on failure + */ + virtual int close() = 0; + + /** Flush any buffers associated with the file + * + * @return 0 on success, negative error code on failure + */ + virtual int sync() + { + return 0; + } + + /** Check if the file in an interactive terminal device + * + * @return True if the file is a terminal + * @return False if the file is not a terminal + * @return Negative error code on failure + */ + virtual int isatty() + { + return false; + } + + /** Get the file position of the file + * + * @note This is equivalent to seek(0, SEEK_CUR) + * + * @return The current offset in the file, negative error code on failure + */ + virtual off_t tell() + { + return seek(0, SEEK_CUR); + } + + /** Rewind the file position to the beginning of the file + * + * @note This is equivalent to seek(0, SEEK_SET) + */ + virtual void rewind() + { + seek(0, SEEK_SET); + } + + /** Get the size of the file + * + * @return Size of the file in bytes + */ + virtual off_t size(); + + /** Move the file position to a given offset from a given location. + * + * @param offset The offset from whence to move to + * @param whence SEEK_SET for the start of the file, SEEK_CUR for the + * current file position, or SEEK_END for the end of the file. + * + * @returns + * new file position on success, + * -1 on failure or unsupported + * @deprecated Replaced by `off_t FileHandle::seek(off_t offset, int whence = SEEK_SET)' + * + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", "Replaced by FileHandle::seek") + virtual off_t lseek(off_t offset, int whence) + { + return seek(offset, whence); + } + + /** Flush any buffers associated with the FileHandle, ensuring it + * is up to date on disk + * + * @returns + * 0 on success or un-needed, + * -1 on error + * @deprecated Replaced by `int FileHandle::sync()' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", "Replaced by FileHandle::sync") + virtual int fsync() + { + return sync(); + } + + /** Find the length of the file + * + * @returns + * Length of the file + * @deprecated Replaced by `off_t FileHandle::size()' + */ + MBED_DEPRECATED_SINCE("mbed-os-5.4", "Replaced by FileHandle::size") + virtual off_t flen() + { + return size(); + } + + /** Set blocking or nonblocking mode of the file operation like read/write. + * Definition depends on the subclass implementing FileHandle. + * The default is blocking. + * + * @param blocking true for blocking mode, false for nonblocking mode. + * + * @return 0 on success + * @return Negative error code on failure + */ + virtual int set_blocking(bool blocking) + { + return blocking ? 0 : -ENOTTY; + } + + /** Check current blocking or nonblocking mode for file operations. + * + * @return true for blocking mode, false for nonblocking mode. + */ + virtual bool is_blocking() const + { + return true; + } + + /** Check for poll event flags + * You can use or ignore the input parameter. You can return all events + * or check just the events listed in events. + * Call is nonblocking - returns instantaneous state of events. + * Whenever an event occurs, the derived class should call the sigio() callback). + * + * @param events bitmask of poll events we're interested in - POLLIN/POLLOUT etc. + * + * @returns bitmask of poll events that have occurred. + */ + virtual short poll(short events) const + { + // Possible default for real files + return POLLIN | POLLOUT; + } + + /** Definition depends on the subclass implementing FileHandle. + * For example, if the FileHandle is of type Stream, writable() could return + * true when there is ample buffer space available for write() calls. + * + * @returns true if the FileHandle is writable. + */ + bool writable() const + { + return poll(POLLOUT) & POLLOUT; + } + + /** Definition depends on the subclass implementing FileHandle. + * For example, if the FileHandle is of type Stream, readable() could return + * true when there is something available to read. + * + * @returns true when there is something available to read. + */ + bool readable() const + { + return poll(POLLIN) & POLLIN; + } + + /** Register a callback on state change of the file. + * + * The specified callback will be called on state changes such as when + * the file can be written to or read from. + * + * The callback may be called in an interrupt context and should not + * perform expensive operations. + * + * Note! This is not intended as an attach-like asynchronous API, but rather + * as a building block for constructing such functionality. + * + * The exact timing of when the registered function + * is called is not guaranteed and is susceptible to change. It should be used + * as a cue to make read/write/poll calls to find the current state. + * + * @param func Function to call on state change + */ + virtual void sigio(Callback<void()> func) + { + //Default for real files. Do nothing for real files. + } +}; + +/**@}*/ + +/**@}*/ + + +} // namespace mbed + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FileLike.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,55 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * 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_FILELIKE_H +#define MBED_FILELIKE_H + +#include "platform/mbed_toolchain.h" +#include "platform/FileBase.h" +#include "platform/FileHandle.h" +#include "platform/NonCopyable.h" + +namespace mbed { +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_FileLike FileLike class + * @{ + */ +/** Class FileLike + * + * A file-like object is one that can be opened with fopen by + * fopen("/name", mode). + * + * @note Synchronization level: Set by subclass + */ +class FileLike : public FileHandle, public FileBase, private NonCopyable<FileLike> { +public: + /** Constructor FileLike + * + * @param name The name to use to open the file. + */ + FileLike(const char *name = NULL) : FileBase(name, FilePathType) {} + virtual ~FileLike() {} +}; + +/**@}*/ + +/**@}*/ + +} // namespace mbed + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FilePath.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,66 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * 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_FILEPATH_H +#define MBED_FILEPATH_H + +#include "platform/platform.h" + +#include "platform/FileSystemLike.h" +#include "platform/FileLike.h" + +namespace mbed { +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_FilePath FilePath class + * @{ + */ + +class FileSystem; +/** Class FilePath + * + */ + +class FilePath { +public: + /** Constructor FilePath + * + * @param file_path The path of file. + */ + FilePath(const char *file_path); + + const char *fileName(void); + + bool isFileSystem(void); + FileSystemLike *fileSystem(void); + + bool isFile(void); + FileLike *file(void); + bool exists(void); + +private: + const char *file_name; + FileBase *fb; +}; + +/**@}*/ + +/**@}*/ + +} // namespace mbed + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FileSystemHandle.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,113 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * 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_FILESYSTEMHANDLE_H +#define MBED_FILESYSTEMHANDLE_H + +#include "platform/platform.h" + +#include "platform/FileBase.h" +#include "platform/FileHandle.h" +#include "platform/DirHandle.h" +#include "platform/NonCopyable.h" + +namespace mbed { +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_FileSystemHandle FileSystemHandle functions + * @{ + */ + + +/** A filesystem-like object is one that can be used to open file-like + * objects though it by fopen("/name/filename", mode) + * + * Implementations must define at least open (the default definitions + * of the rest of the functions just return error values). + * + * @note Synchronization level: Set by subclass + */ +class FileSystemHandle : private NonCopyable<FileSystemHandle> { +public: + /** FileSystemHandle lifetime + */ + virtual ~FileSystemHandle() {} + + /** Open a file on the filesystem + * + * @param file Destination for the handle to a newly created file + * @param filename The name of the file to open + * @param flags The flags to open the file in, one of O_RDONLY, O_WRONLY, O_RDWR, + * bitwise or'd with one of O_CREAT, O_TRUNC, O_APPEND + * @return 0 on success, negative error code on failure + */ + virtual int open(FileHandle **file, const char *filename, int flags) = 0; + + /** Open a directory on the filesystem + * + * @param dir Destination for the handle to the directory + * @param path Name of the directory to open + * @return 0 on success, negative error code on failure + */ + virtual int open(DirHandle **dir, const char *path); + + /** Remove a file from the filesystem. + * + * @param path The name of the file to remove. + * @return 0 on success, negative error code on failure + */ + virtual int remove(const char *path); + + /** Rename a file in the filesystem. + * + * @param path The name of the file to rename. + * @param newpath The name to rename it to + * @return 0 on success, negative error code on failure + */ + virtual int rename(const char *path, const char *newpath); + + /** Store information about the file in a stat structure + * + * @param path The name of the file to find information about + * @param st The stat buffer to write to + * @return 0 on success, negative error code on failure + */ + virtual int stat(const char *path, struct stat *st); + + /** Create a directory in the filesystem. + * + * @param path The name of the directory to create. + * @param mode The permissions with which to create the directory + * @return 0 on success, negative error code on failure + */ + virtual int mkdir(const char *path, mode_t mode); + + /** Store information about the mounted filesystem in a statvfs structure + * + * @param path The name of the file to find information about + * @param buf The stat buffer to write to + * @return 0 on success, negative error code on failure + */ + virtual int statvfs(const char *path, struct statvfs *buf); +}; +/**@}*/ + +/**@}*/ + +} // namespace mbed + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FileSystemLike.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,93 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * 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_FILESYSTEMLIKE_H +#define MBED_FILESYSTEMLIKE_H + +#include "platform/platform.h" + +#include "platform/FileSystemHandle.h" +#include "platform/FileHandle.h" +#include "platform/DirHandle.h" +#include "platform/NonCopyable.h" + +namespace mbed { +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_FileSystemLike FileSystemLike functions + * @{ + */ + + +/** A filesystem-like object is one that can be used to open file-like + * objects though it by fopen("/name/filename", mode) + * + * Implementations must define at least open (the default definitions + * of the rest of the functions just return error values). + * + * @note Synchronization level: Set by subclass + */ +class FileSystemLike : public FileSystemHandle, public FileBase, private NonCopyable<FileSystemLike> { +public: + /** FileSystemLike lifetime + */ + FileSystemLike(const char *name = NULL) : FileBase(name, FileSystemPathType) {} + virtual ~FileSystemLike() {} + + // Inherited functions with name conflicts + using FileSystemHandle::open; + + /** Open a file on the filesystem + * + * @param path The name of the file to open + * @param flags The flags to open the file in, one of O_RDONLY, O_WRONLY, O_RDWR, + * bitwise or'd with one of O_CREAT, O_TRUNC, O_APPEND + * @return A file handle on success, NULL on failure + * @deprecated Replaced by `int open(FileHandle **, ...)` for propagating error codes + */ + MBED_DEPRECATED_SINCE("mbed-os-5.5", + "Replaced by `int open(FileHandle **, ...)` for propagating error codes") + FileHandle *open(const char *path, int flags) + { + FileHandle *file; + int err = open(&file, path, flags); + return err ? NULL : file; + } + + /** Open a directory on the filesystem + * + * @param path Name of the directory to open + * @return A directory handle on success, NULL on failure + * @deprecated Replaced by `int open(DirHandle **, ...)` for propagating error codes + */ + MBED_DEPRECATED_SINCE("mbed-os-5.5", + "Replaced by `int open(DirHandle **, ...)` for propagating error codes") + DirHandle *opendir(const char *path) + { + DirHandle *dir; + int err = open(&dir, path); + return err ? NULL : dir; + } +}; + +/**@}*/ + +/**@}*/ + +} // namespace mbed + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FunctionPointer.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,112 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2015 ARM Limited + * 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_FUNCTIONPOINTER_H +#define MBED_FUNCTIONPOINTER_H + +#include "platform/Callback.h" +#include "platform/mbed_toolchain.h" +#include <string.h> +#include <stdint.h> + +namespace mbed { +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_FunctionPointer FunctionPointer class + * @{ + */ + +// Declarations for backwards compatibility +// To be foward compatible, code should adopt the Callback class +template <typename R, typename A1> +class FunctionPointerArg1 : public Callback<R(A1)> { +public: + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "FunctionPointerArg1<R, A> has been replaced by Callback<R(A)>") + FunctionPointerArg1(R(*function)(A1) = 0) + : Callback<R(A1)>(function) {} + + template<typename T> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "FunctionPointerArg1<R, A> has been replaced by Callback<R(A)>") + FunctionPointerArg1(T *object, R(T::*member)(A1)) + : Callback<R(A1)>(object, member) {} + + R(*get_function())(A1) + { + return *reinterpret_cast<R(* *)(A1)>(this); + } + + R call(A1 a1) const + { + if (!Callback<R(A1)>::operator bool()) { + return (R)0; + } + + return Callback<R(A1)>::call(a1); + } + + R operator()(A1 a1) const + { + return Callback<R(A1)>::call(a1); + } +}; + +template <typename R> +class FunctionPointerArg1<R, void> : public Callback<R()> { +public: + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "FunctionPointer has been replaced by Callback<void()>") + FunctionPointerArg1(R(*function)() = 0) + : Callback<R()>(function) {} + + template<typename T> + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "FunctionPointer has been replaced by Callback<void()>") + FunctionPointerArg1(T *object, R(T::*member)()) + : Callback<R()>(object, member) {} + + R(*get_function())() + { + return *reinterpret_cast<R(* *)()>(this); + } + + R call() const + { + if (!Callback<R()>::operator bool()) { + return (R)0; + } + + return Callback<R()>::call(); + } + + R operator()() const + { + return Callback<R()>::call(); + } +}; + +typedef FunctionPointerArg1<void, void> FunctionPointer; + +/**@}*/ + +/**@}*/ + + +} // namespace mbed + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LocalFileSystem.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,129 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * 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_LOCALFILESYSTEM_H +#define MBED_LOCALFILESYSTEM_H + +#include "platform/platform.h" + +#if DEVICE_LOCALFILESYSTEM + +#include "platform/FileSystemLike.h" +#include "platform/PlatformMutex.h" +#include "platform/NonCopyable.h" + +namespace mbed { +/** \addtogroup platform */ +/** @{*/ +/** + * \defgroup platform_LocalFileSystem LocalFileSystem functions + * @{ + */ + +FILEHANDLE local_file_open(const char *name, int flags); + +/** + * @class LocalFileHandle + * @ingroup platform + */ +class LocalFileHandle : public FileHandle, private NonCopyable<LocalFileHandle> { + +public: + LocalFileHandle(FILEHANDLE fh); + + virtual int close(); + + virtual ssize_t write(const void *buffer, size_t length); + + virtual ssize_t read(void *buffer, size_t length); + + virtual int isatty(); + + virtual off_t seek(off_t position, int whence); + + virtual int sync(); + + virtual off_t size(); + +protected: + virtual void lock(); + virtual void unlock(); + FILEHANDLE _fh; + int pos; + PlatformMutex _mutex; +}; + +/** A filesystem for accessing the local mbed Microcontroller USB disk drive + * + * This allows programs to read and write files on the same disk drive that is used to program the + * mbed Microcontroller. Once created, the standard C file access functions are used to open, + * read and write files. + * + * @note Synchronization level: Thread safe + * + * Example: + * @code + * #include "mbed.h" + * + * LocalFileSystem local("local"); // Create the local filesystem under the name "local" + * + * int main() { + * FILE *fp = fopen("/local/out.txt", "w"); // Open "out.txt" on the local file system for writing + * fprintf(fp, "Hello World!"); + * fclose(fp); + * remove("/local/out.txt"); // Removes the file "out.txt" from the local file system + * + * DIR *d = opendir("/local"); // Opens the root directory of the local file system + * struct dirent *p; + * while((p = readdir(d)) != NULL) { // Print the names of the files in the local file system + * printf("%s\n", p->d_name); // to stdout. + * } + * closedir(d); + * } + * @endcode + * + * @note + * If the microcontroller program makes an access to the local drive, it will be marked as "removed" + * on the Host computer. This means it is no longer accessible from the Host Computer. + * + * The drive will only re-appear when the microcontroller program exists. Note that if the program does + * not exit, you will need to hold down reset on the mbed Microcontroller to be able to see the drive again! + * @ingroup platform + */ +class LocalFileSystem : public FileSystemLike, private NonCopyable<LocalFileSystem> { + // No modifiable state + +public: + LocalFileSystem(const char *n) : FileSystemLike(n) + { + + } + + virtual int open(FileHandle **file, const char *path, int flags); + virtual int open(DirHandle **dir, const char *name); + virtual int remove(const char *filename); +}; + +/**@}*/ + +/**@}*/ + +} // namespace mbed + +#endif + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/critical.h Thu Apr 08 16:43:07 2021 +0000 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2015-2016, ARM Limited, All Rights Reserved + * 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_OLD_CRITICAL_H +#define MBED_OLD_CRITICAL_H + +#warning critical.h has been replaced by mbed_critical.h, please update to mbed_critical.h [since mbed-os-5.3] +#include "platform/mbed_critical.h" + +#endif