1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-04 18:03:20 +03:00

Use placement new for ETSTimer - no heap fragmentation (#6164)

* Use placement new for ETSTimer - no heap fragmentation, new/delete semantics unchanged.

* Make change completely invisible to derived classes at compile-time.

* Fix "sizeof() incomplete type ETSTimer" error.

* C++ reinterpret_cast<> instead of C-style cast.

void* instead of uint32_t - fixes x86_64 server compiles.

* Simplify casts.

* Revert to complete placement new treatment of ETSTimer member.

* Cleanup includes

* Fix omitted casts

* Change per review https://github.com/esp8266/Arduino/pull/6164#pullrequestreview-243583458

* wtf - local compile didn't catch this sloppy mistake

* Resolves review https://github.com/esp8266/Arduino/pull/6164#discussion_r290388119

* Reviewer stated that floating point operations are inlined, software operations -

reduce number of code spots to one.
This commit is contained in:
Dirk O. Kaar 2019-06-05 06:14:14 +02:00 committed by Develo
parent 8859b818d8
commit 79101213a5
2 changed files with 49 additions and 58 deletions

View File

@ -1,9 +1,9 @@
/* /*
Ticker.cpp - esp8266 library that calls functions periodically Ticker.cpp - esp8266 library that calls functions periodically
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment. This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
@ -19,21 +19,20 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include <stddef.h>
#include <stdint.h>
#include "c_types.h" #include "c_types.h"
#include "eagle_soc.h" #include "eagle_soc.h"
#include "ets_sys.h"
#include "osapi.h" #include "osapi.h"
static const int ONCE = 0;
static const int REPEAT = 1;
#include "Ticker.h" #include "Ticker.h"
namespace
{
constexpr int ONCE = 0;
constexpr int REPEAT = 1;
}
Ticker::Ticker() Ticker::Ticker()
: _timer(nullptr) : _timer(nullptr)
{ {
} }
@ -42,7 +41,12 @@ Ticker::~Ticker()
detach(); detach();
} }
void Ticker::_attach_ms(uint32_t milliseconds, bool repeat, callback_with_arg_t callback, uint32_t arg) void Ticker::_attach_s(float seconds, bool repeat, callback_with_arg_t callback, void* arg)
{
_attach_ms(1000 * seconds, repeat, callback, arg);
}
void Ticker::_attach_ms(uint32_t milliseconds, bool repeat, callback_with_arg_t callback, void* arg)
{ {
if (_timer) if (_timer)
{ {
@ -50,11 +54,11 @@ void Ticker::_attach_ms(uint32_t milliseconds, bool repeat, callback_with_arg_t
} }
else else
{ {
_timer = new ETSTimer; _timer = &_etsTimer;
} }
os_timer_setfn(_timer, reinterpret_cast<ETSTimerFunc*>(callback), reinterpret_cast<void*>(arg)); os_timer_setfn(_timer, callback, arg);
os_timer_arm(_timer, milliseconds, (repeat)?REPEAT:ONCE); os_timer_arm(_timer, milliseconds, (repeat) ? REPEAT : ONCE);
} }
void Ticker::detach() void Ticker::detach()
@ -63,25 +67,18 @@ void Ticker::detach()
return; return;
os_timer_disarm(_timer); os_timer_disarm(_timer);
delete _timer;
_timer = nullptr; _timer = nullptr;
_callback_function = nullptr; _callback_function = nullptr;
} }
bool Ticker::active() const bool Ticker::active() const
{ {
return (bool)_timer; return _timer;
} }
void Ticker::_static_callback(void* arg) void Ticker::_static_callback(void* arg)
{ {
Ticker* _this = (Ticker*)arg; Ticker* _this = reinterpret_cast<Ticker*>(arg);
if (_this == nullptr) if (_this && _this->_callback_function)
{
return;
}
if (_this->_callback_function)
{
_this->_callback_function(); _this->_callback_function();
}
} }

View File

@ -1,9 +1,9 @@
/* /*
Ticker.h - esp8266 library that calls functions periodically Ticker.h - esp8266 library that calls functions periodically
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment. This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
@ -22,22 +22,16 @@
#ifndef TICKER_H #ifndef TICKER_H
#define TICKER_H #define TICKER_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <functional> #include <functional>
#include <Schedule.h> #include <Schedule.h>
#include <ets_sys.h>
extern "C" {
typedef struct _ETSTIMER_ ETSTimer;
}
class Ticker class Ticker
{ {
public: public:
Ticker(); Ticker();
~Ticker(); ~Ticker();
typedef void (*callback_t)(void);
typedef void (*callback_with_arg_t)(void*); typedef void (*callback_with_arg_t)(void*);
typedef std::function<void(void)> callback_function_t; typedef std::function<void(void)> callback_function_t;
@ -48,8 +42,8 @@ public:
void attach(float seconds, callback_function_t callback) void attach(float seconds, callback_function_t callback)
{ {
_callback_function = callback; _callback_function = std::move(callback);
attach(seconds, _static_callback, (void*)this); _attach_s(seconds, true, _static_callback, this);
} }
void attach_ms_scheduled(uint32_t milliseconds, callback_function_t callback) void attach_ms_scheduled(uint32_t milliseconds, callback_function_t callback)
@ -59,27 +53,25 @@ public:
void attach_ms(uint32_t milliseconds, callback_function_t callback) void attach_ms(uint32_t milliseconds, callback_function_t callback)
{ {
_callback_function = callback; _callback_function = std::move(callback);
attach_ms(milliseconds, _static_callback, (void*)this); _attach_ms(milliseconds, true, _static_callback, this);
} }
template<typename TArg> template<typename TArg>
void attach(float seconds, void (*callback)(TArg), TArg arg) void attach(float seconds, void (*callback)(TArg), TArg arg)
{ {
static_assert(sizeof(TArg) <= sizeof(uint32_t), "attach() callback argument size must be <= 4 bytes"); static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
// C-cast serves two purposes: // C-cast serves two purposes:
// static_cast for smaller integer types, // static_cast for smaller integer types,
// reinterpret_cast + const_cast for pointer types // reinterpret_cast + const_cast for pointer types
uint32_t arg32 = (uint32_t)arg; _attach_s(seconds, true, reinterpret_cast<callback_with_arg_t>(callback), (void*)arg);
_attach_ms(seconds * 1000, true, reinterpret_cast<callback_with_arg_t>(callback), arg32);
} }
template<typename TArg> template<typename TArg>
void attach_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg) void attach_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg)
{ {
static_assert(sizeof(TArg) <= sizeof(uint32_t), "attach_ms() callback argument size must be <= 4 bytes"); static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
uint32_t arg32 = (uint32_t)arg; _attach_ms(milliseconds, true, reinterpret_cast<callback_with_arg_t>(callback), (void*)arg);
_attach_ms(milliseconds, true, reinterpret_cast<callback_with_arg_t>(callback), arg32);
} }
void once_scheduled(float seconds, callback_function_t callback) void once_scheduled(float seconds, callback_function_t callback)
@ -89,8 +81,8 @@ public:
void once(float seconds, callback_function_t callback) void once(float seconds, callback_function_t callback)
{ {
_callback_function = callback; _callback_function = std::move(callback);
once(seconds, _static_callback, (void*)this); _attach_s(seconds, false, _static_callback, this);
} }
void once_ms_scheduled(uint32_t milliseconds, callback_function_t callback) void once_ms_scheduled(uint32_t milliseconds, callback_function_t callback)
@ -100,36 +92,38 @@ public:
void once_ms(uint32_t milliseconds, callback_function_t callback) void once_ms(uint32_t milliseconds, callback_function_t callback)
{ {
_callback_function = callback; _callback_function = std::move(callback);
once_ms(milliseconds, _static_callback, (void*)this); _attach_ms(milliseconds, false, _static_callback, this);
} }
template<typename TArg> template<typename TArg>
void once(float seconds, void (*callback)(TArg), TArg arg) void once(float seconds, void (*callback)(TArg), TArg arg)
{ {
static_assert(sizeof(TArg) <= sizeof(uint32_t), "attach() callback argument size must be <= 4 bytes"); static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
uint32_t arg32 = (uint32_t)(arg); _attach_s(seconds, false, reinterpret_cast<callback_with_arg_t>(callback), (void*)arg);
_attach_ms(seconds * 1000, false, reinterpret_cast<callback_with_arg_t>(callback), arg32);
} }
template<typename TArg> template<typename TArg>
void once_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg) void once_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg)
{ {
static_assert(sizeof(TArg) <= sizeof(uint32_t), "attach_ms() callback argument size must be <= 4 bytes"); static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
uint32_t arg32 = (uint32_t)(arg); _attach_ms(milliseconds, false, reinterpret_cast<callback_with_arg_t>(callback), (void*)arg);
_attach_ms(milliseconds, false, reinterpret_cast<callback_with_arg_t>(callback), arg32);
} }
void detach(); void detach();
bool active() const; bool active() const;
protected:
void _attach_ms(uint32_t milliseconds, bool repeat, callback_with_arg_t callback, uint32_t arg);
static void _static_callback (void* arg);
protected: protected:
void _attach_ms(uint32_t milliseconds, bool repeat, callback_with_arg_t callback, void* arg);
static void _static_callback(void* arg);
ETSTimer* _timer; ETSTimer* _timer;
callback_function_t _callback_function = nullptr; callback_function_t _callback_function = nullptr;
private:
void _attach_s(float seconds, bool repeat, callback_with_arg_t callback, void* arg);
//char _etsTimerMem[sizeof(ETSTimer)];
ETSTimer _etsTimer;
}; };