diff options
Diffstat (limited to 'doc/html/EASTL Maintenance.html')
-rw-r--r-- | doc/html/EASTL Maintenance.html | 292 |
1 files changed, 0 insertions, 292 deletions
diff --git a/doc/html/EASTL Maintenance.html b/doc/html/EASTL Maintenance.html deleted file mode 100644 index aaca955..0000000 --- a/doc/html/EASTL Maintenance.html +++ /dev/null @@ -1,292 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html> -<head> - <title>EASTL Maintenance</title> - <meta content="text/html; charset=us-ascii" http-equiv="content-type"> - <meta name="author" content="Paul Pedriana"> - <meta name="description" content="Information for the EASTL maintainer."> - <link type="text/css" rel="stylesheet" href="EASTLDoc.css"> -</head> -<body> - -<h1>EASTL Maintenance</h1> -<h2><span style="font-style: italic;"><a name="Introduction" id="Introduction"></a></span>Introduction</h2> -<p>The purpose of this document is to provide some necessary background for anybody who might do work on EASTL. Writing - generic templated systems like EASTL can be surprisingly tricky. There are numerous details of the C++ language that - you need to understand which don't usually come into play during the day-to-day C++ coding that many people do. It is - easy to make a change to some function that seems proper and works for your test case but either violates the design - expectations or simply breaks under other circumstances.<br> - <br> - It may be useful to start with an example. Here we provide an implementation of the count algorithm which is seems -simple enough. Except it is wrong and while it will compile in some cases it won't compile in others:</p> -<pre class="code-example">template <class InputIterator, class T> -int count(InputIterator first, InputIterator last, const T& value) -{ - int result = 0; - - for(; first < last; ++first){ - if(*first == value) - ++result; - } - - return result; - } </pre> -<p>The problem is with the comparison 'first < last'. The count algorithm takes an InputIterator and operator< is -not guaranteed to exist for any given InputIterator (and indeed while operator< exists for vector::iterator, it -doesn't exist for list::iterator). The comparison in the above algorithm must instead be implemented as 'first != -last'. If we were working with a RandomAccessIterator then 'first < last' would be valid.</p> -<p>In the following sections we cover various topics of interest regarding the development and maintentance of EASTL. - Unfortunately, this document can't cover every aspect of EASTL maintenance issues, but at least it should give you a -sense of the kinds of issues.</p> - -<h2> <a name="Language_Standard" id="Language_Standard"></a>C++ Language Standard</h2> -<p>First and foremost, you need to be familiar with the C++ standard. In particular, the sections of the standard related - to containers, algorithms, and iterators are of prime significance. We'll talk about some of this in more detail below. - Similarly, a strong understanding of the basic data types is required. What is the difference between ptrdiff_t and -intptr_t; unsigned int and size_t; char and signed char?</p> -<p>In addition to the C++ language standard, you'll want to be familiar with the C++ Defect Report. This is a continuously - updated document which lists flaws in the original C++ language specification and the current thinking as the -resolutions of those flaws. You will notice various references to the Defect Report in EASTL source code.</p> -<p>Additionally, you will want to be familiar with the C++ Technical Report 1 (as of this writing there is only one). This - document is the evolving addendum to the C++ standard based on both the Defect Report and based on desired additions to -the C++ language and standard library.</p> -<p>Additionally, you will probably want to have some familiarity with Boost. It also helps to keep an eye on - comp.std.c++ Usenet discussions. However, watch out for what people say on Usenet. They tend to defend GCC, Unix, std - STL, and C++ to a sometimes unreasonable degree. Many discussions ignore performance implications and -concentrate only on correctness and sometimes academic correctness above usability.</p> -<h2> <a name="Langauge_Use" id="Langauge_Use"></a>Language Use</h2> -<p>Macros are (almost) not allowed in EASTL. A prime directive of EASTL is to be easier to read by users and most of - the time macros are an impedence to this. So we avoid macros at all costs, even if it ends up making our development - and maintenance more difficult. That being said, you will notice that the EASTL config.h file uses macros to control - various options. This is an exception to the rule; when we talk about not using macros, we mean with the EASTL -implementation itself.</p> -<p>EASTL assumes a compliant and intelligent C++ compiler, and thus all language facilities are usable. However, we -nevertheless choose to stay away from some language functionality. The primary language features we avoid are:</p> -<ul> - <li>RTTI (run-time-type-identification) (this is deemed too costly)</li> -<li>Template export (few compilers support this)</li> -<li>Exception specifications (most compilers ignore them)</li> -</ul> -<p>Use of per-platform or per-compiler code should be avoided when possible but where there is a significant advantage to - be gained it can and indeed should be used. An example of this is the GCC __builtin_expect feature, which allows the - user to give the compiler a hint about whether an expression is true or false. This allows for the generation of code -that executes faster due to more intelligent branch prediction.</p> -<h2> <a name="Prime_Directives" id="Prime_Directives"></a>Prime Directives</h2> -<p>The -implementation of EASTL is guided foremost by the following directives which are listed in order of importance.</p> -<ol> -<li>Efficiency (speed and memory usage)</li> -<li>Correctness (doesn't have bugs)</li> -<li>Portability (works on all required platforms with minimal specialized code)</li> -<li>Readability (code is legible and comments are present and useful)</li> -</ol> -<p>Note that unlike commercial STL implementations which must put correctness above all, we put a higher value on - efficiency. As a result, some functionality may have some usage limitation that is not present in other similar systems -but which allows for more efficient operation, especially on the platforms of significance to us.</p> -<p>Portability is significant, but not critical. Yes, EASTL must compile and run on all platforms that we will ship games - for. But we don't take that to mean under all compilers that could be conceivably used for such platforms. For example, - Microsoft VC6 can be used to compile Windows programs, but VC6's C++ support is too weak for EASTL and so you simply -cannot use EASTL under VC6.</p> -<p>Readability is something that EASTL achieves better than many other templated libraries, particularly Microsoft STL and - STLPort. We make every attempt to make EASTL code clean and sensible. Sometimes our need to provide optimizations - (particularly related to type_traits and iterator types) results in less simple code, but efficiency happens to be our -prime directive and so it overrides all other considerations.</p> - -<h2> <a name="Coding_Conventions" id="Coding_Conventions"></a>Coding Conventions</h2> -<p>Here we provide a list of coding conventions to follow when maintaining or adding to EASTL, starting with the three -language use items from above:</p> -<ul> -<li>No RTTI use.</li> -<li>No use of exception specifications (e.g. appending the 'throw' declarator to a function).</li> -<li>No use of exception handling itself except where explicitly required by the implementation (e.g. vector::at).</li> -<li>Exception use needs to savvy to EASTL_EXCEPTIONS_ENABLED.</li> -<li>No use of macros (outside of config.h). Macros make things more difficult for the user.</li> -<li>No use of static or global variables.</li> -<li>No use of global new, delete, malloc, or free. All memory must be user-specifyable via an Allocator parameter -(default-specified or explicitly specified).</li> -<li>Containers use protected member data and functions as opposed to private. This is because doing so allows -subclasses to extend the container without the creation of intermediary functions. Recall from our <a href="#Prime_Directives">prime directives</a> above that performance and simplicity overrule all.</li> -<li>No use of multithreading primitives. </li> -<li>No use of the export keyword.</li> -<li>We don't have a rule about C-style casts vs. C++ static_cast<>, etc. We would always use static_cast except -that debuggers can't evaluate them and so in practice they can get in the way of debugging and tracing. However, if the -cast is one that users don't tend to need to view in a debugger, C++ casts are preferred.</li> -<li>No external library dependencies whatsoever, including standard STL. EASTL is dependent on only EABase and the -C++ compiler. </li> -<li>All code must be const-correct. This isn't just for readability -- compilation can fail unless const-ness is used -correctly everywhere. </li> -<li>Algorithms do not refer to containers; they refer only to iterators.</li> -<li>Algorithms in general do not allocate memory. If such a situation arises, there should be a version of the -algorithm which allows the user to provide the allocator.</li> -<li>No inferior implementations. No facility should be added to EASTL unless it is of professional -quality.</li> -<li>The maintainer should emulate the EASTL style of code layout, regardless of the maintainer's personal preferences. -When in Rome, do as the Romans do. EASTL uses 4 spaces for indents, which is how the large majority of code within EA -is written.</li> -<li>No major changes should be done without consulting a peer group.</li> -</ul> - -<h2><a name="Compiler_Issues" id="Compiler_Issues"></a>Compiler Issues</h2> -<p>Historically, templates are the feature of C++ that has given C++ compilers the most fits. We are still working with - compilers that don't completely and properly support templates. Luckily, most compilers are now good enough to handle -what EASTL requires. Nevertheless, there are precautions we must take.</p> -<p>It turns out that the biggest problem in writing portable EASTL code is that VC++ allows you to make illegal statements - which are not allowed by other compilers. For example, VC++ will allow you to neglect using the typename keyword in -template references, whereas GCC (especially 3.4+) requires it.</p> -<p>In order to feel comfortable that your EASTL code is C++ correct and is portable, you must do at least these two -things:</p> -<ul> -<li>Test under at least VS2005, GCC 3.4+, GCC 4.4+, EDG, and clang. </li> -<li>Test all functions that you write, as compilers will often skip the compilation of a template function if it isn't -used.</li> -</ul> -<p>The two biggest issues to watch out for are 'typename' and a concept called "dependent names". In both cases VC++ will - accept non-conforming syntax whereas most other compilers will not. Whenever you reference a templated type (and not a templated - value) in a template, you need to prefix it by 'typename'. Whenever your class function refers to a base class member (data or - function), you need to refer to it by "this->", "base_type::", or by placing a "using" statement in your class to -declare that you will be referencing the given base class member.</p> - -<h2> <a name="Iterator_Issues" id="Iterator_Issues"></a>Iterator Issues</h2> -<p>The most important thing to understand about iterators is the concept of iterator types and their designated - properties. In particular, we need to understand the difference between InputIterator, ForwardIterator, - BidirectionalIterator, RandomAccessIterator, and OutputIterator. These differences dictate both how we implement our - algorithms and how we implement our optimizations. Please read the C++ standard for a reasonably well-implemented - description of these iterator types.</p> -<p>Here's an example from EASTL/algorithm.h which demonstrates how we use iterator types to optimize the reverse algorithm -based on the kind of iterator passed to it:</p> -<pre class="code-example">template <class BidirectionalIterator> -inline void reverse_impl(BidirectionalIterator first, BidirectionalIterator last, bidirectional_iterator_tag)<br>{ - for(; (first != last) && (first != --last); ++first) <span class="code-example-comment">// We are not allowed to use operator <, <=, >, >= with</span> - iter_swap(first, last); <span class="code-example-comment">// a generic (bidirectional or otherwise) iterator.</span> -}<br> - -template <typename RandomAccessIterator> -inline void reverse_impl(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag) -{ - for(; first < --last; ++first) <span class="code-example-comment">// With a random access iterator, we can use operator < to more efficiently implement</span> - iter_swap(first, last); <span class="code-example-comment">// this algorithm. A generic iterator doesn't necessarily have an operator < defined.</span> -}<br><br> -template <class BidirectionalIterator> -inline void reverse(BidirectionalIterator first, BidirectionalIterator last) -{ - typedef typename iterator_traits<BidirectionalIterator>::iterator_category IC; - reverse_impl(first, last, IC()); -}</pre> - -<h2> <a name="Exception_Handling" id="Exception_Handling"></a>Exception Handling</h2> -<p>You will notice that EASTL uses try/catch in some places (particularly in containers) and uses - the EASTL_EXCEPTIONS_ENABLED define. For starters, any EASTL code that uses try/catch should always be wrapped - within #if EASTL_EXCEPTIONS_ENABLED (note: #if, not #ifdef).</p> -<p>This is simple enough, but what you may be wondering is how it is that EASTL decides to use try/catch for some sections - of code and not for others. EASTL follows the C++ standard library conventions with respect to exception handling, and - you will see similar exception handling in standard STL. The code that you need to wrap in try/catch is code that can - throw a C++ exception (not to be confused with CPU exception) and needs to have something unwound (or fixed) as a - result. The important thing is that the container be in a valid state after encountering such exceptions. In general -the kinds of things that require such try/catch are:</p> -<ul> -<li>Memory allocation failures (which throw exceptions)</li> -<li>Constructor exceptions</li> -</ul> -<p>Take a look at the cases in EASTL where try/catch is used and see what it is doing.</p> -<h2> <a name="Type_Traits" id="Type_Traits"></a>Type Traits </h2> -<p>EASTL provides a facility called type_traits which is very similar to the type_traits being proposed by the C++ TR1 - (see above). type_traits are useful because they tell you about properties of types at compile time. This allows you to - do things such as assert that a data type is scalar or that a data type is const. The way we put them to use in EASTL - is to take advantage of them to implement different pathways for functions based on types. For example, we can copy a - contiguous array of scalars much faster via memcpy than we can via a for loop, though we could not safely employ the - for loop for a non-trivial C++ class.</p> -<p>As mentioned in the GeneralOptimizations section below, EASTL should take advantage of type_traits information to the -extent possible to achive maximum effiiciency.</p> -<h2> <a name="General_Optimizations" id="General_Optimizations"></a>General -Optimizations</h2> -<p>One of the primary goals of EASTL is to achieve the highest possible efficiency. In cases where EASTL functionality - overlaps standard C++ STL functionality, standard STL implementations provided by compiler vendors are a benchmark upon - which EASTL strives to beat. Indeed EASTL is more efficient than all other current STL implementations (with some - exception in the case of some Metrowerks STL facilities). Here we list some of the things to look for when considering - optimization of EASTL code These items can be considered general optimization suggestions for any code, but this -particular list applies to EASTL:</p> -<ul> -<li>Take advantage of type_traits to the extent possible (e.g. to use memcpy to move data instead of a for loop when -possible).</li> -<li>Take advantage of iterator types to the extent possible.</li> -<li>Take advantage of the compiler's expectation that if statements are expected to evaluate as true and for loop -conditions are expected to evaluate as false.</li> -<li>Make inline-friendly code. This often means avoiding temporaries to the extent possible.</li> -<li>Minimize branching (i.e. minimize 'if' statements). Where branching is used, make it so that 'if' statements -execute as true.</li> -<li>Use EASTL_LIKELY/EASTL_UNLIKELY to give branch hints to the compiler when you are confident it will be -beneficial.</li> -<li>Use restricted pointers (EABase's EA_RESTRICT or various compiler-specific versions of __restrict).</li> -<li>Compare unsigned values to < max instead of comparing signed values to >= 0 && < max.</li> -<li>Employ power of 2 integer math instead of math with any kind of integer.</li> -<li>Use template specialization where possible to implement improved functionality.</li> -<li>Avoid function calls when the call does something trivial. This improves debug build speed (which matters) and -sometimes release build speed as well, though sometimes makes the code intent less clear. A comment next to the code -saying what call it is replacing makes the intent clear without sacrificing performance.</li> -</ul> -<h2><a name="Unit_Tests" id="Unit_Tests"></a>Unit Tests</h2> -<p>Writing robust templated containers and algorithms is difficult or impossible without a heavy unit test suite in place. - EASTL has a pretty extensive set of unit tests for all containers and algorithms. While the successful automated unit - testing of shipping application programs may be a difficult thing to pull off, unit testing of libraries such as this - is of huge importance and cannot be understated. </p> -<ul> -<li>When making a new unit test, start by copying one of the existing unit tests and follow its conventions.</li> -<li>Test containers of both scalars and classes.</li> -<li>Test algorithms on both container iterators (e.g. vector.begin()) and pointer iterators (e.g. int*).</li> -<li>Make sure that algorithm or container member functions which take iterators work with the type of iterator they -claim to (InputIterator, ForwardIterator, BidirectionalIterator, RandomAccessIterator). </li> -<li>Test for const-correctness. If a user is allowed to modify something that is supposed to be const, silent errors -can go undetected.</li> -<li>Make sure that unit tests cover all functions and all pathways of the tested code. This means that in writing the -unit test you need to look at the source code to understand all the pathways.</li> -<li>Consider using a random number generator (one is provided in the test library) to do 'monkey' testing whereby -unexpected input is given to a module being tested. When doing so, make sure you seed the generator in a way that -problems can be reproduced.</li> -<li>While we avoid macros in EASTL user code, macros to assist in unit tests aren't considered a problem. However, -consider that a number of macros could be replaced by templated functions and thus be easier to work with.</li> -<li>Unit tests don't need to be efficient; feel free to take up all the CPU power and time you need to test a module -sufficiently.</li> -<li>EASTL containers are not thread-safe, by design. Thus there is no need to do multithreading tests as long as you -stay away from the usage of static and global variables.</li> -<li>Unit tests must succeed with no memory leaks and of course no memory corruption. The heap system should be -configured to test for this, and heap validation functions are available to the unit tests while in the middle of -runs.</li> -</ul> - -<h2><a name="Things_to_Keep_in_Mind" id="Things_to_Keep_in_Mind"></a>Things to Keep in Mind</h2> -<ul> -<li>When referring to EASTL functions and types from EASTL code, make sure to preface the type with the EASTL -namespace. If you don't do this you can get collisions due to the compiler not knowing if it should use the EASTL -namespace or the namespace of the templated type for the function or type.</li> -<li>Newly constructed empty containers do no memory allocation. Some STL and other container libraries allocate an -initial node from the class memory allocator. EASTL containers by design never do this. If a container needs an -initial node, that node should be made part of the container itself or be a static empty node object.</li> -<li>Empty containers (new or otherwise) contain no constructed objects, including those that might be in an 'end' node. -Similarly, no user object (e.g. of type T) should be constructed unless required by the design and unless documented in -the cotainer/algorithm contract. </li> -<li>When creating a new container class, it's best to copy from an existing similar class to the extent possible. This -helps keep the library consistent and resolves subtle problems that can happen in the construction of containers.</li> -<li>Be very careful about tweaking the code. It's easy to think (for example) that a > could be switch to a >= -where instead it is a big deal. Just about every line of code in EASTL has been thought through and has a purpose. Unit -tests may or may not currently test every bit of EASTL, so you can't necessarily rely on them to give you 100% -confidence in changes. If you are not sure about something, contact the original author and he will tell you for -sure.</li> -<li>Algorithm templates always work with iterators and not containers. A given container may of course implement an -optimized form or an algorithm itself.</li> -<li>Make sure everything is heavily unit tested. If somebody finds a bug, fix the bug and make a unit test to make sure -the bug doesn't happen again.</li> -<li>It's easy to get iterator categories confused or forgotten while implementing algorithms and containers.</li> -<li>Watch out for the strictness of GCC 3.4+. There is a bit of syntax — especially related to templates — that other -compilers accept but GCC 3.4+ will not.</li> -<li>Don't forget to update the config.h EASTL_VERSION define before publishing.</li> -<li>The vector and string classes define iterator to be T*. We want to always leave this so — at least in release -builds — as this gives some algorithms an advantage that optimizers cannot get around.</li> -</ul> -<hr style="width: 100%; height: 2px;"> -<br> -<br> -<br> -<br> -<br> -</body> -</html> |