External Libraries
Here are some external libraries that can be used with MWX.
EASTL - EASTL is a C++ standard library by Electronic Arts that provides a container that runs in fixed-length memory, making it easy to use in embedded microcontrollers.
EASTL
EASTL is a standard template library (containers and algorithms) maintained by Electronic Arts, and is implemented in the manner of the STL (Standard Template Library) of C++. It has been developed for the development of game consoles with many restrictions, and containers and algorithms have been prepared for environments with large memory handling restrictions.
This library makes EASTL available within TWENET.
The following is a list of EASTL's features.
Container with fixed memory allocation (fixed_
) : Containers with a fixed number of elements can be declared without dynamic allocation. If declared globally, a fixed memory area is allocated at compile time. If declared locally, the memory area is allocated in the stack area and can be used within its scope.
Intrusive containers:While ordinary containers can store arbitrary data structures, Intrusive containers inherit a dedicated base class for data structures, which holds link information and other information to maintain link structures and other structures within the container. Although each element in a container is dedicated to that container, lists and map structures are very efficient in memory usage.(Reference: Intrusive and non-intrusive containers)
The 2007 article EASTL (open-std.org) describes the motivation behind the development.
Please keep in mind the following
We do not perform comprehensive verification of the library's operation. Please verify the operation of the library by yourself. We also cannot respond to inquiries about how to use EASTL. Please refer to the information such as opening materials and library resource codes of the distribution source.
Use the EASTL3.07 (2018/1/31) version. (the last version that can be compiled in C++11)
The following libraries are not incorporated.
test/packages/EAAssert
, source/assert.cpp
test/packages/EATest
test/packages/EAThread
, source/thread_support.cpp
The test code test/source
has not been ported to work.
In sprintf related matters, EA::StdC::Vsnprintf(char8_t*, ...)
is only solved by calling vsnprintf_()
in the printf.h library.
EASTL can be used when writing an ACT Act.
Add include paths and libraries as required by the development environment for TWELITE. Please include the library headers in the code you create.
Library compilation and include path settings have already been performed in the directories under MWSDK/TWENET, but the internal settings are described below.
Compile the code in EASTL/source as a library archive (libEASTL.a
). Reference to this library is required at link time.
Add the following include paths at compile time.
If $(PATH_EASTL)
is the EASTL directory, the include path would be
std::
and eastl::
MWX Live internally also uses the standard libraries in the std::
namespace.
The standard library (std::
) and EASTL (eastl::
) have the same name and the same functionality defined. They may be mixed, but their use may result in errors. In other words, for EASTL use, the definitions in EASTL are usually used (e.g., trying to store eastl::fixed_string
in std::unique_ptr
will result in a compiler error).
Also, when using statements such as using namespace std;
, be careful of name collisions.
In the development of TWENET, the constructor of the globally declared object is not executed due to compiler constraints. The memory area of the globally declared object is simply cleared to zero. If the code is executed as is, it will hang due to null pointer access in most cases.
Use placement new to initialize this object。
*The code for placement new looks a bit messy, so we provide an auxiliary function mwx::pnew()
. The previous example can be rewritten as follows
The second and subsequent arguments are variable numbers and are passed directly to the constructor.
Another way to initialize global objects is to use unique_ptr
(description of std::unique_ptr). Although unique_ptr
is available in both std::
and eastl::
, EASTL classes use the one in eastl::
.
Call .reset()
at the time of initialization as follows.
The following is an example of an element definition for intrusive_list
. It has only int mX
members.
Elements of intrusive_list
must have intrusive_list_node
in the base class. Within the base class are link pointers to maintain the list. This section further defines the comparison operators used for sort
and so on.
EA Standard Template Library ーNote that the libraries included in TWENET are for EASTL 3.07 and contain elements that have been implemented or modified since then.)
C++ reference ーThis is a C++ reference, but the STL explanation is helpful.
The license description of EASTL is as follows
Modified BSD License (3-Clause BSD license) see the file LICENSE in the project root.
The sample code applies MWSLA-1J/E.
An array with a fixed maximum length (i.e., not expandable). (* mwx::smplbuf
is also a fixed maximum length array, but it is partially specialized for internal processing of the MWX library)
There are three template arguments for fixed_vector
, the first is the type, the second is the maximum number, and the third is false. For manipulating arrays, .puch_back()
, .pop_back()
, and [] operators
similar to the general std::vector
are available.
It is also possible to apply sorting algorithms, etc. In the above example, eastl::sort
is applied with ascending order eastl::less
.
A list structure with a fixed maximum number of elements (see also intrusive_list
).
There are three template arguments for fixed_list
: the first is the type, the second is the maximum number, and the third is false. For manipulating the list, .insert()
, .erase()
, etc. similar to the general std::list
are available.
In the above code, the list contains the elements of a pair eastl::pair
, where the first of the pair is an integer of type uint8_t
and the second is a function pointer to void (*)(uint8_t)
. In the code, the lambda expression is written directly. The x.second(x.first);
in the code implies that the value of first is given to the function obtained from second.
This list can be searched for elements using eastl::find_if
and sorted using bubble_sort
.
While a normal list can have any data structure as an element, intrusive_list
constructs a data structure by assigning specific data to an element and using that data.
In the following example, to be an element of the intruslve_list
data structure, it must be a data element type that inherits from eastl::intrusive_list_node
. The eastl::intrusive_list_node
is an extension that allows pointers to the previous and next elements to be stored。
In this example, eastl::fixed_vector<>
is used for the purpose of allocating the required number of elements of the IntNode
, not that fixed_vector
was needed. 5 elements are used to store the test values and Construct an intrusive_list. The example calls l.push_pront()
to store the elements one by one in the list. Actually, it is not storing, but rewiring the pointers of each element IntNode
.
Sorting is described by calling a member function like l.sort()
.
The ring buffer ring_buffer
is constructed in combination with another container (fixed_vector
in the example).
The definition of ring_buffer
is a combination of an element type and its container type. The element type should have one extra element.
In the above example, .push_front()
inserts the element at the top. If it overflows, the tail will disappear. The oldest element is taken out by .back()
. Remove the oldest element by .pop_back()
.
The map structure is a key-value data structure designed to efficiently extract elements by key value. The intrusive_hash_map
is implemented using the intrusive structure and hash values. It is somewhat complicated to define, but memory consumption can be reduced.
As with intrusive_list, you need to define your own element type IntNode
by inheriting from eastl::intrusive_hash_node_key<element type>
. Also, a maximum hash value (N_BUCKET_CT
) must be defined to use hashing. This value should be set to an appropriate prime number depending on the expected number of elements to be stored.
The above example assumes that the key of the map is a single character of type uint8_t
and the value part of the map is a function pointer. In loop()
, the function is executed according to the key input, and so on.
First, since the table and elements are defined as global objects, we initialize the data elements (nd_a, nd_b, nd_c, nd_d
) and initialize the hashmap (mp
) by calling mwx::pnew()
in setup()
. The return value of mwx::pnew()
is a pointer to the constructed object, so we write the values (lambda expressions) to the member variables directly after initialization.
After setting the initials and values of the elements (nd_a, nd_b, nd_c, nd_d
), insert the elements into the map as in mp.insert(nd_a)
.
In loop()
, a search of the hashmap is performed each time a character is entered from the serial. The search calls the mp.find()
method, which returns an iterator, or mp.end()
if the search fails. If the search succeeds, (*it)
can be used to refer to the element that was found.
intrusive_hash_multimap
is a multimap that allows duplicate values. Its usage is almost the same as hashmap, except that it uses .equal_range()
when searching and treats it as a pair of iterators.