/      日本語

TWENETeastl - EASTL Library

Implementation of C++ STL with static memory allocation
Additional explanation about the EASTL library.

TWENETeastl - EASTL Library

EASTL is a standard template library (containers and algorithms) maintained by Electronic Arts. It is implemented following C++ STL (Standard Template Library) but was developed with the constraints of game console environments in mind, providing containers and algorithms designed for systems with strict memory usage limitations.

This library enables the use of EASTL within TWENET.

Key features include:

  • Fixed-memory containers (fixed_):
    Containers with a fixed number of elements that do not perform dynamic allocation. If declared globally, memory is allocated at compile time; if declared locally, memory is allocated on the stack and available within that scope.

  • Intrusive containers:
    Unlike normal containers that can store arbitrary data structures, intrusive containers require inheriting a base class to maintain link information within the data structure itself.
    While this restricts container usage to specific data structures, it greatly improves memory efficiency for lists or maps.
    (Reference: Intrusive and non-intrusive containers)

The 2007 article EASTL (open-std.org) describes the motivation behind its development.
(Additional articles: EASTL and Game Development, Part 1, Part 2)

EASTL Library Documentation

Please refer to the HTML files under the doc directory.

The README.md and CONTRIBUTING.md files, originally located in the root directory of the distribution,
have been moved to the doc/ directory.

Usage in TWENET

Please note the following:

We have not conducted comprehensive testing of the library’s operation.
Customers are responsible for verifying its functionality.
We also cannot provide support for questions regarding the usage of EASTL.
Please refer to the official documentation, source code, and related materials provided by the original authors.

  • The version used is EASTL 3.07 (2018/1/31),
    which is the last version compatible with C++11.
  • The following libraries are not included:
    • test/packages/EAAssert, source/assert.cpp
    • test/packages/EATest
    • test/packages/EAThread, source/thread_support.cpp
  • Test code under test/source has not been ported.
  • For sprintf related functionality, only EA::StdC::Vsnprintf(char8_t*, ...)
    is supported by calling vsnprintf_() in the printf.h library.

Integration and Compilation

EASTL can be used when writing Acts.

The necessary include paths and library additions for the TWELITE development environment are already provided.
Simply include the required library headers in the code you create.

#include <TWELITE>
#include <EASTL/fixed_string.h>

using namespace eastl;
using tstr128 = fixed_string<char, 127 + 1, false>;

void setup() {
    tstr128 s1;
    s1 = "Hello World";
    Serial << s1.c_str();
}
void loop() {
    ;
}

Detailed Integration Steps

  • Compile the code under EASTL/source into a library archive (libEASTL.a).
    Linking against this library is required during the build process.
  • Add the following include paths during compilation.

If $(PATH_EASTL) points to the EASTL directory, the include paths are as follows:

-I$(PATH_EASTL)/include
-I$(PATH_EASTL)/test/packages/EAAssert/include
-I$(PATH_EASTL)/test/packages/EABase/include/Common
-I$(PATH_EASTL)/test/packages/EAMain/include
-I$(PATH_EASTL)/test/packages/EAStdC/include
-I$(PATH_EASTL)/test/packages/EATest/include
-I$(PATH_EASTL)/test/packages/EAThread/include

Coding Guidelines

std:: vs eastl::

Both the standard library (std::) and EASTL (eastl::) define components with the same names and functionalities.
While they may sometimes be interoperable, using them together can lead to compilation errors.

As a general rule, when working with EASTL, use definitions provided by EASTL itself.
For example, attempting to store an eastl::fixed_string in a std::unique_ptr will result in a compiler error.

Global Object Initialization 1 (Placement New)

In TWENET development, due to compiler constraints, constructors for globally declared objects are not executed.
Memory for such globally declared objects is only zero-initialized.
If the code is executed as-is, it will typically hang due to null pointer access.

To properly initialize these objects, use placement new.

#include <TWELITE>
#include <EASTL/fixed_string.h>

using namespace eastl;
using tstr128 = fixed_string<char, 127 + 1, false>;

tstr128 g_str1; // constructor is NOT called! needs to be initialized before use.

void setup() {
    (void) new ((void*)&g_str1) tstr128("Hello World");
    Serial << g_str1.c_str();
}

Since the placement new code can look a bit messy, a helper function mwx::pnew() is provided. The previous example can be rewritten as follows.

(void) new ((void*)&g_str1) tstr128("Hello World");
// ↓
mwx::pnew(g_str1, "Hello World");

Note: Arguments from the second one onward are variadic and passed directly to the constructor.

Global Object Initialization 2 (unique_ptr)

As another way to initialize global objects, you can use unique_ptr (std::unique_ptr reference). Both std:: and eastl:: provide unique_ptr, but for EASTL classes, you should use the one from eastl::.

Call .reset() at the timing of initialization as shown below.

#include <TWELITE>
#include <EASTL/unique_ptr.h>
#include <EASTL/fixed_string.h>

using namespace eastl;
using tstr128 = fixed_string<char, 127 + 1, false>;

eastl::unique_ptr<tstr128> uq_str1;

void setup() {
	uq_str1.reset(new tstr128("Hello World"));
    if (uq_str1) { // true: object is stored.
        Serial << uq_str1->c_str();
    }
}

About intrusive containers

The following example shows an element definition for intrusive_list. The only member is int mX.

struct IntNode : public eastl::intrusive_list_node {
    int mX;
    IntNode(int x = 0) : mX(x) { }
        // no need to call super class's constructor eastl::intrusive_list_node()
};

inline bool operator<(const IntNode& a, const IntNode& b) { return a.mX < b.mX; }
inline bool operator>(const IntNode& a, const IntNode& b) { return a.mX > b.mX; }

Elements of intrusive_list must inherit from the intrusive_list_node base class. The base class contains link pointers used to maintain the list. Here we also define comparison operators used by functions such as sort.

using tiList = intrusive_list<IntNode>;

void setup() {
    IntNode nodeA(5);
    IntNode nodeB(1);
    IntNode nodeC(9);
    IntNode nodeD(2);
    IntNode nodeE(4);

    tiList l; // intrusive_list body

    l.push_front(nodeA); // forming list strucure
                         //   by updating link info in intrusive_list_node.
    l.push_front(nodeB);
    l.push_front(nodeC);
    l.push_front(nodeD);
    l.push_front(nodeE);

    l.sort(); // sort, using < operator
    l.sort(eastl::greater<tilist::value_type>()); // sort, using > operator
}

References

About this sample

The EASTL license description is as follows.

Modified BSD License (3-Clause BSD license) see the file LICENSE in the project root.

/*
Copyright (C) 2015 Electronic Arts Inc.  All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1.  Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
2.  Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
3.  Neither the name of Electronic Arts, Inc. ("EA") nor the names of
    its contributors may be used to endorse or promote products derived
    from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

The sample code applies MWSLA-1J/E.