[ion] Ion::Storage is not a global variable anymore

This commit is contained in:
Romain Goyet
2018-04-10 15:05:41 +02:00
parent 5b379010d8
commit 628992680b
6 changed files with 41 additions and 27 deletions

View File

@@ -4,8 +4,7 @@
#include "variable_box_controller.h"
#include <apps/code/app.h>
#include <escher/metric.h>
extern Ion::Storage storage;
#include <ion.h>
namespace Code {
@@ -28,7 +27,7 @@ void EditorController::setScript(Script script) {
m_script = script;
const char * scriptBody = m_script.readContent();
size_t scriptBodySize = strlen(scriptBody)+1;
size_t availableScriptSize = scriptBodySize + storage.availableSize();
size_t availableScriptSize = scriptBodySize + Ion::Storage::sharedStorage()->availableSize();
assert(m_areaBuffer == nullptr);
m_areaBuffer = new char[availableScriptSize];
strlcpy(m_areaBuffer, scriptBody, scriptBodySize);

View File

@@ -26,7 +26,7 @@ void ScriptStore::deleteAllScripts() {
}
bool ScriptStore::isFull() {
return (numberOfScripts() >= k_maxNumberOfScripts || storage.availableSize() < k_fullFreeSpaceSizeLimit);
return (numberOfScripts() >= k_maxNumberOfScripts || Ion::Storage::sharedStorage()->availableSize() < k_fullFreeSpaceSizeLimit);
}
void ScriptStore::scanScriptsForFunctionsAndVariables(void * context, ScanCallback storeFunction, ScanCallback storeVariable) {
@@ -124,7 +124,7 @@ Script::ErrorStatus ScriptStore::addScriptFromTemplate(const ScriptTemplate * sc
char * body = new char[scriptSize+Script::k_importationStatusSize];
body[0] = 1;
strlcpy(body+Script::k_importationStatusSize, scriptTemplate->content(), scriptSize);
Script::ErrorStatus err = storage.createRecord(scriptTemplate->name(), body, scriptSize+Script::k_importationStatusSize);
Script::ErrorStatus err = Ion::Storage::sharedStorage()->createRecord(scriptTemplate->name(), body, scriptSize+Script::k_importationStatusSize);
assert(err != Script::ErrorStatus::NonCompliantName);
delete[] body;
return err;

View File

@@ -1,6 +1,7 @@
#ifndef CODE_SCRIPT_STORE_H
#define CODE_SCRIPT_STORE_H
#include <ion.h>
#include "script.h"
#include "script_template.h"
#include <python/port/port.h>
@@ -8,8 +9,6 @@ extern "C" {
#include "py/parse.h"
}
extern Ion::Storage storage;
namespace Code {
class ScriptStore : public MicroPython::ScriptProvider {
@@ -20,13 +19,13 @@ public:
ScriptStore();
Script scriptAtIndex(int index) {
return Script(storage.recordWithExtensionAtIndex(k_scriptExtension, index));
return Script(Ion::Storage::sharedStorage()->recordWithExtensionAtIndex(k_scriptExtension, index));
}
Script scriptNamed(const char * name) {
return Script(storage.recordNamed(name));
return Script(Ion::Storage::sharedStorage()->recordNamed(name));
}
int numberOfScripts() {
return storage.numberOfRecordsWithExtension(k_scriptExtension);
return Ion::Storage::sharedStorage()->numberOfRecordsWithExtension(k_scriptExtension);
}
Ion::Storage::Record::ErrorStatus addNewScript() {
return addScriptFromTemplate(ScriptTemplate::Empty());

View File

@@ -5,19 +5,12 @@
namespace Ion {
class Storage;
}
extern Ion::Storage storage;
namespace Ion {
/* Storage : | Magic | Record1 | Record2 | ... | Magic |
* | Magic | Size1(uint16_t) | Name1 | Body1 | Size2(uint16_t) | Name2 | Body2 | ... | Magic */
class Storage {
public:
static Storage * sharedStorage();
class Record {
/* A Record is identified by the CRC32 on his name because:
* - a record is identified by its name which is unique
@@ -46,19 +39,19 @@ public:
return m_nameCRC32 == 0;
}
const char * name() const {
return storage.nameOfRecord(*this);
return Storage::sharedStorage()->nameOfRecord(*this);
}
ErrorStatus setName(const char * name) {
return storage.setNameOfRecord(*this, name);
return Storage::sharedStorage()->setNameOfRecord(*this, name);
}
Data value() const {
return storage.valueOfRecord(*this);
return Storage::sharedStorage()->valueOfRecord(*this);
}
ErrorStatus setValue(Data data) {
return storage.setValueOfRecord(*this, data);
return Storage::sharedStorage()->setValueOfRecord(*this, data);
}
void destroy() {
return storage.destroyRecord(*this);
return Storage::sharedStorage()->destroyRecord(*this);
}
private:
uint32_t m_nameCRC32;

View File

@@ -13,7 +13,10 @@
#define HEADER_SECTION
#endif
extern Ion::Storage storage;
namespace Ion {
extern char staticStorageArea[];
}
constexpr void * storageAddress = &(Ion::staticStorageArea);
class PlatformInfo {
public:
@@ -21,7 +24,7 @@ public:
m_header(Magic),
m_version{EPSILON_VERSION},
m_patchLevel{PATCH_LEVEL},
m_storageAddress(&storage),
m_storageAddress(storageAddress),
m_footer(Magic) { }
const char * version() const {
assert(m_storageAddress != nullptr);

View File

@@ -1,11 +1,31 @@
#include <ion.h>
#include <string.h>
#include <assert.h>
Ion::Storage storage;
#include <new>
namespace Ion {
/* We want to implement a simple singleton pattern, to make sure the storage is
* initialized on first use, therefore preventing the static init order fiasco.
* That being said, we rely on knowing where the storage resides in the device's
* memory at compile time. Indeed, we want to advertise the static storage's
* memory address in the PlatformInfo structure (so that we can read and write
* it in DFU).
* Using a "static Storage storage;" variable makes it a local symbol at best,
* preventing the PlatformInfo from retrieving its address. And making the
* Storage variable global yields the static init fiasco issue. We're working
* around both issues by creating a global staticStorageArea buffer, and by
* placement-newing the Storage into that area on first use. */
char staticStorageArea[sizeof(Storage)] = {0};
Storage * Storage::sharedStorage() {
static Storage * storage = nullptr;
if (storage == nullptr) {
storage = new (staticStorageArea) Storage();
}
return storage;
}
Storage::Record::Record(const char * name) {
if (name == nullptr) {
m_nameCRC32 = 0;