First commit
authorBenjamin Segovia <segovia.benjamin@gmail.com>
Thu, 9 Aug 2012 23:23:09 +0000 (16:23 -0700)
committerKeith Packard <keithp@keithp.com>
Fri, 10 Aug 2012 23:14:13 +0000 (16:14 -0700)
 - Added commom system files
 - Added empty files for the IR we are going to use for GEN

54 files changed:
COPYING [new file with mode: 0644]
backend/CMakeLists.txt [new file with mode: 0644]
backend/src/CMakeLists.txt [new file with mode: 0644]
backend/src/ir/function.cpp [new file with mode: 0644]
backend/src/ir/function.hpp [new file with mode: 0644]
backend/src/ir/instruction.cpp [new file with mode: 0644]
backend/src/ir/instruction.hpp [new file with mode: 0644]
backend/src/ir/register.cpp [new file with mode: 0644]
backend/src/ir/register.hpp [new file with mode: 0644]
backend/src/ir/scope.cpp [new file with mode: 0644]
backend/src/ir/scope.hpp [new file with mode: 0644]
backend/src/ir/unit.cpp [new file with mode: 0644]
backend/src/ir/unit.hpp [new file with mode: 0644]
backend/src/sys/alloc.cpp [new file with mode: 0644]
backend/src/sys/alloc.hpp [new file with mode: 0644]
backend/src/sys/array.hpp [new file with mode: 0644]
backend/src/sys/atomic.hpp [new file with mode: 0644]
backend/src/sys/barrier.hpp [new file with mode: 0644]
backend/src/sys/condition.cpp [new file with mode: 0644]
backend/src/sys/condition.hpp [new file with mode: 0644]
backend/src/sys/constants.hpp [new file with mode: 0644]
backend/src/sys/default_path.cpp [new file with mode: 0644]
backend/src/sys/default_path.hpp [new file with mode: 0644]
backend/src/sys/filename.cpp [new file with mode: 0644]
backend/src/sys/filename.hpp [new file with mode: 0644]
backend/src/sys/fixed_array.hpp [new file with mode: 0644]
backend/src/sys/hash_map.hpp [new file with mode: 0644]
backend/src/sys/intrinsics.hpp [new file with mode: 0644]
backend/src/sys/library.cpp [new file with mode: 0644]
backend/src/sys/library.hpp [new file with mode: 0644]
backend/src/sys/list.hpp [new file with mode: 0644]
backend/src/sys/logging.cpp [new file with mode: 0644]
backend/src/sys/logging.hpp [new file with mode: 0644]
backend/src/sys/map.hpp [new file with mode: 0644]
backend/src/sys/mutex.cpp [new file with mode: 0644]
backend/src/sys/mutex.hpp [new file with mode: 0644]
backend/src/sys/platform.cpp [new file with mode: 0644]
backend/src/sys/platform.hpp [new file with mode: 0644]
backend/src/sys/ref.hpp [new file with mode: 0644]
backend/src/sys/set.hpp [new file with mode: 0644]
backend/src/sys/string.cpp [new file with mode: 0644]
backend/src/sys/string.hpp [new file with mode: 0644]
backend/src/sys/sysinfo.cpp [new file with mode: 0644]
backend/src/sys/sysinfo.hpp [new file with mode: 0644]
backend/src/sys/thread.cpp [new file with mode: 0644]
backend/src/sys/thread.hpp [new file with mode: 0644]
backend/src/sys/vector.hpp [new file with mode: 0644]
backend/src/utest/utest.cpp [new file with mode: 0644]
backend/src/utest/utest.hpp [new file with mode: 0644]
backend/src/utest/utest_console.cpp [new file with mode: 0644]
backend/src/utest/utest_font.cpp [new file with mode: 0644]
backend/src/utest/utest_lua.cpp [new file with mode: 0644]
backend/src/utest/utest_rt.cpp [new file with mode: 0644]
backend/src/utest/utest_tasking.cpp [new file with mode: 0644]

diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..4362b49
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,502 @@
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt
new file mode 100644 (file)
index 0000000..73a79ed
--- /dev/null
@@ -0,0 +1,104 @@
+project (PF)
+
+cmake_minimum_required (VERSION 2.6.0)
+
+set (PF_CMAKE_DIR "${PF_SOURCE_DIR}/cmake")
+set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PF_CMAKE_DIR}")
+
+##############################################################
+# Compilation directives
+##############################################################
+
+set (PF_DEBUG_MEMORY false CACHE bool "Activate the memory debugger")
+set (PF_USE_BLOB false CACHE bool "Compile everything from one big file")
+set (PF_VERBOSE_VECTORIZER false CACHE bool "Output vectorizer diagnostic (GCC only)")
+
+##############################################################
+# Compiler
+##############################################################
+if (UNIX)
+  set (COMPILER "GCC" CACHE INT "Compiler to choose on Linux (GCC,ICC,CLANG)")
+endif (UNIX)
+
+if (WIN32)
+  if (MINGW)
+    set (DEF "-D")
+  else (MINGW)
+    set (DEF "/D")
+  endif (MINGW)
+else (WIN32)
+  set (DEF "-D")
+endif (WIN32)
+
+if (PF_DEBUG_MEMORY)
+  set (PF_DEBUG_MEMORY_FLAG "${DEF}PF_DEBUG_MEMORY=1")
+else (PF_DEBUG_MEMORY)
+  set (PF_DEBUG_MEMORY_FLAG "${DEF}PF_DEBUG_MEMORY=0")
+endif (PF_DEBUG_MEMORY)
+
+## Linux compilation
+if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+  # Hide all symbols and allows the symbols declared as visible to be exported
+  set (VISIBILITY_FLAG "-fvisibility=hidden")
+
+  if (COMPILER STREQUAL "GCC")
+    set (CMAKE_CXX_FLAGS "-Wstrict-aliasing=2 -Wno-invalid-offsetof -fstrict-aliasing -msse2 -ffast-math -fPIC -Wall -fno-rtti -std=c++0x")
+    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PF_DEBUG_MEMORY_FLAG}")
+    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${VISIBILITY_FLAG} -Wl,-E")
+    set (CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG -ftree-vectorize")
+    if (PF_VERBOSE_VECTORIZER)
+      set (CMAKE_CXX_FLAGS "-ftree-vectorizer-verbose=2")
+    endif (PF_VERBOSE_VECTORIZER)
+  elseif (COMPILER STREQUAL "CLANG")
+    set (CMAKE_C_COMPILER             "clang")
+    set (CMAKE_C_FLAGS                "-Wall -std=c99")
+    set (CMAKE_C_FLAGS_DEBUG          "-g")
+    set (CMAKE_C_FLAGS_MINSIZEREL     "-Os -DNDEBUG")
+    set (CMAKE_C_FLAGS_RELEASE        "-O3 -DNDEBUG")
+    set (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g")
+    set (CMAKE_CXX_COMPILER             "clang++")
+    set (CMAKE_CXX_FLAGS "-fstrict-aliasing -msse2 -ffast-math -fPIC -Wall -Wno-format-security -Wno-invalid-offsetof -std=c++0x")
+    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PF_DEBUG_MEMORY_FLAG}")
+    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${VISIBILITY_FLAG}")
+    set (CMAKE_CXX_FLAGS_DEBUG          "-g")
+    set (CMAKE_CXX_FLAGS_MINSIZEREL     "-Os -DNDEBUG")
+    set (CMAKE_CXX_FLAGS_RELEASE        "-O3 -DNDEBUG")
+    set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
+    set (CMAKE_AR      "/usr/bin/llvm-ar")
+    set (CMAKE_LINKER  "/usr/bin/llvm-ld")
+    set (CMAKE_NM      "/usr/bin/llvm-nm")
+    set (CMAKE_OBJDUMP "/usr/bin/llvm-objdump")
+    set (CMAKE_RANLIB  "ranlib")
+  elseif (COMPILER STREQUAL "ICC")
+    set (CMAKE_CXX_COMPILER "icpc")
+    set (CMAKE_C_COMPILER "icc")
+    set (CMAKE_CXX_FLAGS "-std=c++0x -wd2928 -Wall -fPIC -fstrict-aliasing -fp-model fast -xSSE2")
+    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PF_DEBUG_MEMORY_FLAG}")
+    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${VISIBILITY_FLAG} -Wl,-E")
+    set (CMAKE_CXX_FLAGS_DEBUG "-g -O0")
+    set (CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O2")
+    set (CCMAKE_CXX_FLAGS_RELWITHDEBINFO "-g -O2")
+    set (CCMAKE_CXX_FLAGS_MINSIZEREL "-Os")
+    set (CMAKE_EXE_LINKER_FLAGS "")
+  endif ()
+
+## Windows compilation
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows")
+  if (MINGW)
+     if (PF_VERBOSE_VECTORIZER)
+      set (CMAKE_CXX_FLAGS "-ftree-vectorizer-verbose=2")
+    endif (PF_VERBOSE_VECTORIZER)
+    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PF_DEBUG_MEMORY_FLAG} -Wno-invalid-offsetof -fstrict-aliasing -msse2 -ffast-math -Wall -fno-rtti -std=c++0x")
+    set (CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
+  else (MINGW)
+    set (COMMON_FLAGS "${PF_DEBUG_MEMORY_FLAG} /arch:SSE2 /D_CRT_SECURE_NO_WARNINGS /DNOMINMAX /GR- /GS- /W3 /wd4275")
+    set (CMAKE_CXX_FLAGS ${COMMON_FLAGS})
+    set (CMAKE_C_FLAGS ${COMMON_FLAGS})
+  endif (MINGW)
+endif ()
+
+##############################################################
+# Project source code
+##############################################################
+add_subdirectory (src)
+
diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5a3b20b
--- /dev/null
@@ -0,0 +1,42 @@
+set (GBE_SRC
+  sys/vector.hpp
+  sys/hash_map.hpp
+  sys/map.hpp
+  sys/string.cpp
+  sys/string.hpp
+  sys/filename.cpp
+  sys/filename.hpp
+  sys/library.cpp
+  sys/library.hpp
+  sys/thread.cpp
+  sys/thread.hpp
+  sys/alloc.cpp
+  sys/alloc.hpp
+  sys/sysinfo.cpp
+  sys/sysinfo.hpp
+  sys/ref.hpp
+  sys/mutex.cpp
+  sys/mutex.hpp
+  sys/condition.cpp
+  sys/condition.hpp
+  sys/platform.cpp
+  sys/platform.hpp
+  sys/logging.cpp
+  sys/logging.hpp
+  sys/default_path.cpp
+  sys/default_path.hpp)
+
+set (COMPILE_UTEST false CACHE bool "Compile or not the unit tests")
+if (COMPILE_UTEST)
+  set (GBE_SRC ${GBE_SRC})
+endif (COMPILE_UTEST)
+
+if (UNIX)
+  set (EXEC_DEPENDENCIES pthread dl)
+else (UNIX)
+  set (EXEC_DEPENDENCIES)
+endif (UNIX)
+
+include_directories (.)
+add_library (gbe SHARED ${GBE_SRC})
+
diff --git a/backend/src/ir/function.cpp b/backend/src/ir/function.cpp
new file mode 100644 (file)
index 0000000..12001d6
--- /dev/null
@@ -0,0 +1,19 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/function.hpp b/backend/src/ir/function.hpp
new file mode 100644 (file)
index 0000000..12001d6
--- /dev/null
@@ -0,0 +1,19 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/instruction.cpp b/backend/src/ir/instruction.cpp
new file mode 100644 (file)
index 0000000..12001d6
--- /dev/null
@@ -0,0 +1,19 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/instruction.hpp b/backend/src/ir/instruction.hpp
new file mode 100644 (file)
index 0000000..12001d6
--- /dev/null
@@ -0,0 +1,19 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/register.cpp b/backend/src/ir/register.cpp
new file mode 100644 (file)
index 0000000..12001d6
--- /dev/null
@@ -0,0 +1,19 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/register.hpp b/backend/src/ir/register.hpp
new file mode 100644 (file)
index 0000000..12001d6
--- /dev/null
@@ -0,0 +1,19 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/scope.cpp b/backend/src/ir/scope.cpp
new file mode 100644 (file)
index 0000000..12001d6
--- /dev/null
@@ -0,0 +1,19 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/scope.hpp b/backend/src/ir/scope.hpp
new file mode 100644 (file)
index 0000000..12001d6
--- /dev/null
@@ -0,0 +1,19 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/unit.cpp b/backend/src/ir/unit.cpp
new file mode 100644 (file)
index 0000000..12001d6
--- /dev/null
@@ -0,0 +1,19 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/ir/unit.hpp b/backend/src/ir/unit.hpp
new file mode 100644 (file)
index 0000000..12001d6
--- /dev/null
@@ -0,0 +1,19 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
diff --git a/backend/src/sys/alloc.cpp b/backend/src/sys/alloc.cpp
new file mode 100644 (file)
index 0000000..e23ae8e
--- /dev/null
@@ -0,0 +1,261 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/alloc.hpp"
+#include "sys/atomic.hpp"
+#include "sys/mutex.hpp"
+
+#if PF_DEBUG_MEMORY
+#ifdef __MSVC__
+#include <unordered_map>
+#else
+#include <tr1/unordered_map>
+#endif /* __MSVC__ */
+#include <cstring>
+#endif /* PF_DEBUG_MEMORY */
+
+#if defined(__ICC__)
+#include <stdint.h>
+#endif /* __ICC__ */
+#include <map>
+#include <vector>
+
+////////////////////////////////////////////////////////////////////////////////
+/// Memory debugger
+////////////////////////////////////////////////////////////////////////////////
+namespace pf
+{
+
+#if PF_DEBUG_MEMORY
+  /*! Store each allocation data */
+  struct AllocData {
+    INLINE AllocData(void) {}
+    INLINE AllocData(int fileName_, int functionName_, int line_, intptr_t alloc_) :
+      fileName(fileName_), functionName(functionName_), line(line_), alloc(alloc_) {}
+    int fileName, functionName, line;
+    intptr_t alloc;
+  };
+
+  /*! Store allocation information */
+  struct MemDebugger {
+    MemDebugger(void) : unfreedNum(0), allocNum(0) {}
+    void* insertAlloc(void *ptr, const char *file, const char *function, int line);
+    void removeAlloc(void *ptr);
+    void dumpAlloc(void);
+    void dumpData(const AllocData &data);
+    /*! Count the still unfreed allocations */
+    volatile intptr_t unfreedNum;
+    /*! Total number of allocations done */
+    volatile intptr_t allocNum;
+    /*! Sorts the file name and function name strings */
+    std::tr1::unordered_map<const char*, int> staticStringMap;
+    /*! Each element contains the actual string */
+    std::vector<const char*> staticStringVector;
+    std::map<uintptr_t, AllocData> allocMap;
+    /*! Protect the memory debugger accesses */
+    MutexSys mutex;
+  };
+
+  void* MemDebugger::insertAlloc(void *ptr, const char *file, const char *function, int line)
+  {
+    if (ptr == NULL) return ptr;
+    Lock<MutexSys> lock(mutex);
+    const uintptr_t iptr = (uintptr_t) ptr;
+    if (UNLIKELY(allocMap.find(iptr) != allocMap.end())) {
+      this->dumpData(allocMap.find(iptr)->second);
+      FATAL("Pointer already in map");
+    }
+    const auto fileIt = staticStringMap.find(file);
+    const auto functionIt = staticStringMap.find(function);
+    int fileName, functionName;
+    if (fileIt == staticStringMap.end()) {
+      staticStringVector.push_back(file);
+      staticStringMap[file] = fileName = int(staticStringVector.size()) - 1;
+    } else
+      fileName = staticStringMap[file];
+    if (functionIt == staticStringMap.end()) {
+      staticStringVector.push_back(function);
+      staticStringMap[function] = functionName = int(staticStringVector.size()) - 1;
+    } else
+      functionName = staticStringMap[function];
+    allocMap[iptr] = AllocData(fileName, functionName, line, allocNum);
+    unfreedNum++;
+    allocNum++;
+    return ptr;
+  }
+
+  void MemDebugger::removeAlloc(void *ptr)
+  {
+    if (ptr == NULL) return;
+    Lock<MutexSys> lock(mutex);
+    const uintptr_t iptr = (uintptr_t) ptr;
+    FATAL_IF(allocMap.find(iptr) == allocMap.end(), "Pointer not referenced");
+    //if(allocMap.find(iptr) == allocMap.end()) debugbreak();
+    allocMap.erase(iptr);
+    unfreedNum--;
+  }
+
+  void MemDebugger::dumpData(const AllocData &data) {
+    std::cerr << "ALLOC " << data.alloc << ": " <<
+                 "file " << staticStringVector[data.fileName] << ", " <<
+                 "function " << staticStringVector[data.functionName] << ", " <<
+                 "line " << data.line << std::endl;
+  }
+
+  void MemDebugger::dumpAlloc(void) {
+    std::cerr << "MemDebugger: Unfreed number: " << unfreedNum << std::endl;
+    for (auto it = allocMap.begin(); it != allocMap.end(); ++it)
+      this->dumpData(it->second);
+    std::cerr << "MemDebugger: " << staticStringVector.size()
+              << " allocated static strings" << std::endl;
+  }
+
+  /*! The user can deactivate the memory initialization */
+  static bool memoryInitializationEnabled = true;
+
+  /*! Declare C like interface functions here */
+  static MemDebugger *memDebugger = NULL;
+  void* MemDebuggerInsertAlloc(void *ptr, const char *file, const char *function, int line) {
+    if (memDebugger) return memDebugger->insertAlloc(ptr, file, function, line);
+    return ptr;
+  }
+  void MemDebuggerRemoveAlloc(void *ptr) {
+    if (memDebugger) memDebugger->removeAlloc(ptr);
+  }
+  void MemDebuggerDumpAlloc(void) {
+    if (memDebugger) memDebugger->dumpAlloc();
+  }
+  void MemDebuggerEnableMemoryInitialization(bool enabled) {
+    memoryInitializationEnabled = enabled;
+  }
+  void MemDebuggerInitializeMem(void *mem, size_t sz) {
+    if (memoryInitializationEnabled) std::memset(mem, 0xcd, sz);
+  }
+  void MemDebuggerStart(void) {
+    if (memDebugger) MemDebuggerEnd();
+    memDebugger = new MemDebugger;
+  }
+  void MemDebuggerEnd(void) {
+    MemDebugger *_debug = memDebugger;
+    memDebugger = NULL;
+    delete _debug;
+  }
+#endif /* PF_DEBUG_MEMORY */
+}
+
+namespace pf
+{
+  void* malloc(size_t size) {
+    void *ptr = std::malloc(size);
+    MemDebuggerInitializeMem(ptr, size);
+    return ptr;
+  }
+
+  void* realloc(void *ptr, size_t size) {
+#if PF_DEBUG_MEMORY
+    if (ptr) MemDebuggerRemoveAlloc(ptr);
+#endif /* PF_DEBUG_MEMORY */
+    PF_ASSERT(size);
+    if (ptr == NULL) {
+      ptr = std::realloc(ptr, size);
+      MemDebuggerInitializeMem(ptr, size);
+      return ptr;
+    } else
+      return std::realloc(ptr, size);
+  }
+
+  void free(void *ptr) { if (ptr != NULL) std::free(ptr); }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Windows Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __WIN32__
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace pf
+{
+  void* alignedMalloc(size_t size, size_t align) {
+    void* ptr = _mm_malloc(size,align);
+    FATAL_IF (!ptr && size, "memory allocation failed");
+    MemDebuggerInitializeMem(ptr, size);
+    return ptr;
+  }
+
+  void alignedFree(void *ptr) { _mm_free(ptr); }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Linux Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __LINUX__
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <iostream>
+
+namespace pf
+{
+  void* alignedMalloc(size_t size, size_t align) {
+    void* ptr = memalign(align,size);
+    FATAL_IF (!ptr && size, "memory allocation failed");
+    MemDebuggerInitializeMem(ptr, size);
+    return ptr;
+  }
+
+  void alignedFree(void *ptr) { free(ptr); }
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// MacOS Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __MACOSX__
+
+#include <cstdlib>
+
+namespace pf
+{
+  void* alignedMalloc(size_t size, size_t align) {
+    void* mem = malloc(size+(align-1)+sizeof(void*));
+    FATAL_IF (!mem && size, "memory allocation failed");
+    char* aligned = ((char*)mem) + sizeof(void*);
+    aligned += align - ((uintptr_t)aligned & (align - 1));
+    ((void**)aligned)[-1] = mem;
+    MemDebuggerInitializeMem(aligned, size);
+    return aligned;
+  }
+
+  void alignedFree(void* ptr) {
+    PF_ASSERT(ptr);
+    free(((void**)ptr)[-1]);
+  }
+}
+
+#endif
+
diff --git a/backend/src/sys/alloc.hpp b/backend/src/sys/alloc.hpp
new file mode 100644 (file)
index 0000000..5b68634
--- /dev/null
@@ -0,0 +1,229 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_ALLOC_HPP__
+#define __PF_ALLOC_HPP__
+
+#include "sys/platform.hpp"
+#include <cstdlib>
+#include <new>
+
+namespace pf
+{
+  /*! regular allocation */
+  void* malloc(size_t size);
+  void* realloc(void *ptr, size_t size);
+  void  free(void *ptr);
+
+  /*! Aligned allocation */
+  void* alignedMalloc(size_t size, size_t align = 64);
+  void  alignedFree(void* ptr);
+
+  /*! Monitor memory allocations */
+#if PF_DEBUG_MEMORY
+  void* MemDebuggerInsertAlloc(void*, const char*, const char*, int);
+  void  MemDebuggerRemoveAlloc(void *ptr);
+  void  MemDebuggerDumpAlloc(void);
+  void  MemDebuggerInitializeMem(void *mem, size_t sz);
+  void  MemDebuggerEnableMemoryInitialization(bool enabled);
+  void  MemDebuggerStart(void);
+  void  MemDebuggerEnd(void);
+#else
+  INLINE void* MemDebuggerInsertAlloc(void *ptr, const char*, const char*, int) {return ptr;}
+  INLINE void  MemDebuggerRemoveAlloc(void *ptr) {}
+  INLINE void  MemDebuggerDumpAlloc(void) {}
+  INLINE void  MemDebuggerInitializeMem(void *mem, size_t sz) {}
+  INLINE void  MemDebuggerEnableMemoryInitialization(bool enabled) {}
+  INLINE void  MemDebuggerStart(void) {}
+  INLINE void  MemDebuggerEnd(void) {}
+#endif /* PF_DEBUG_MEMORY */
+
+  /*! Properly handle the allocated type */
+  template <typename T>
+  T* _MemDebuggerInsertAlloc(T *ptr, const char *file, const char *function, int line) {
+    MemDebuggerInsertAlloc(ptr, file, function, line);
+    return ptr;
+  }
+} /* namespace pf */
+
+/*! Declare a structure with custom allocators */
+#define PF_STRUCT(TYPE)                                      \
+  void* operator new(size_t size)   {                        \
+    if (AlignOf<TYPE>::value > sizeof(uintptr_t))            \
+      return pf::alignedMalloc(size, AlignOf<TYPE>::value);  \
+    else                                                     \
+      return pf::malloc(size);                               \
+  }                                                          \
+  void* operator new[](size_t size)   {                      \
+    if (AlignOf<TYPE>::value > sizeof(uintptr_t))            \
+      return pf::alignedMalloc(size, AlignOf<TYPE>::value);  \
+    else                                                     \
+      return pf::malloc(size);                               \
+  }                                                          \
+  void  operator delete(void* ptr) {                         \
+    if (AlignOf<TYPE>::value > sizeof(uintptr_t))            \
+      return pf::alignedFree(ptr);                           \
+    else                                                     \
+      return pf::free(ptr);                                  \
+  }                                                          \
+  void  operator delete[](void* ptr) {                       \
+    if (AlignOf<TYPE>::value > sizeof(uintptr_t))            \
+      return pf::alignedFree(ptr);                           \
+    else                                                     \
+      return pf::free(ptr);                                  \
+  }                                                          \
+
+/*! Declare a class with custom allocators */
+#define PF_CLASS(TYPE) \
+public:                \
+  PF_STRUCT(TYPE)      \
+private:
+
+/*! Declare an aligned structure */
+#define PF_ALIGNED_STRUCT(ALIGN)                                              \
+  void* operator new(size_t size)   { return pf::alignedMalloc(size, ALIGN); }\
+  void* operator new[](size_t size) { return pf::alignedMalloc(size, ALIGN); }\
+  void  operator delete(void* ptr)   { pf::alignedFree(ptr); }                \
+  void  operator delete[](void* ptr) { pf::alignedFree(ptr); }
+
+/*! Declare an aligned class */
+#define PF_ALIGNED_CLASS(ALIGN)    \
+public:                            \
+  PF_ALIGNED_STRUCT(ALIGN)         \
+private:
+
+/*! Macros to handle allocation position */
+#define PF_NEW(T,...)               \
+  pf::_MemDebuggerInsertAlloc(new T(__VA_ARGS__), __FILE__, __FUNCTION__, __LINE__)
+
+#define PF_NEW_ARRAY(T,N,...)       \
+  pf::_MemDebuggerInsertAlloc(new T[N](__VA_ARGS__), __FILE__, __FUNCTION__, __LINE__)
+
+#define PF_NEW_P(T,X,...)           \
+  pf::_MemDebuggerInsertAlloc(new (X) T(__VA_ARGS__), __FILE__, __FUNCTION__, __LINE__)
+
+#define PF_DELETE(X)                \
+  do { pf::MemDebuggerRemoveAlloc(X); delete X; } while (0)
+
+#define PF_DELETE_ARRAY(X)          \
+  do { pf::MemDebuggerRemoveAlloc(X); delete[] X; } while (0)
+
+#define PF_MALLOC(SZ)               \
+  pf::MemDebuggerInsertAlloc(pf::malloc(SZ),__FILE__, __FUNCTION__, __LINE__)
+
+#define PF_REALLOC(PTR, SZ)         \
+  pf::MemDebuggerInsertAlloc(pf::realloc(PTR, SZ),__FILE__, __FUNCTION__, __LINE__)
+
+#define PF_FREE(X)                  \
+  do { pf::MemDebuggerRemoveAlloc(X); pf::free(X); } while (0)
+
+#define PF_ALIGNED_FREE(X)          \
+  do { pf::MemDebuggerRemoveAlloc(X); pf::alignedFree(X); } while (0)
+
+#define PF_ALIGNED_MALLOC(SZ,ALIGN) \
+  pf::MemDebuggerInsertAlloc(pf::alignedMalloc(SZ,ALIGN),__FILE__, __FUNCTION__, __LINE__)
+
+namespace pf
+{
+  /*! STL compliant allocator to intercept all memory allocations */
+  template<typename T>
+  class Allocator {
+  public:
+    typedef T value_type;
+    typedef value_type* pointer;
+    typedef const value_type* const_pointer;
+    typedef value_type& reference;
+    typedef const value_type& const_reference;
+    typedef std::size_t size_type;
+    typedef std::ptrdiff_t difference_type;
+    typedef typename std::allocator<void>::const_pointer void_allocator_ptr;
+    template<typename U>
+    struct rebind { typedef Allocator<U> other; };
+
+    INLINE Allocator(void) {}
+    INLINE ~Allocator(void) {}
+    INLINE Allocator(Allocator const&) {}
+    template<typename U>
+    INLINE Allocator(Allocator<U> const&) {}
+    INLINE pointer address(reference r) { return &r; }
+    INLINE const_pointer address(const_reference r) { return &r; }
+    INLINE pointer allocate(size_type n, void_allocator_ptr = 0) {
+      if (AlignOf<T>::value > sizeof(uintptr_t))
+        return (pointer) PF_ALIGNED_MALLOC(n*sizeof(T), AlignOf<T>::value);
+      else
+        return (pointer) PF_MALLOC(n * sizeof(T));
+    }
+    INLINE void deallocate(pointer p, size_type) {
+      if (AlignOf<T>::value > sizeof(uintptr_t))
+        PF_ALIGNED_FREE(p);
+      else
+        PF_FREE(p);
+    }
+    INLINE size_type max_size(void) const {
+      return std::numeric_limits<size_type>::max() / sizeof(T);
+    }
+    INLINE void construct(pointer p, const T& t = T()) { ::new(p) T(t); }
+    INLINE void destroy(pointer p) { p->~T(); }
+    INLINE bool operator==(Allocator const&) { return true; }
+    INLINE bool operator!=(Allocator const& a) { return !operator==(a); }
+  };
+
+  /*! A growing pool never deallocates */
+  template <typename T>
+  class GrowingPool
+  {
+  public:
+    GrowingPool(void) : current(PF_NEW(GrowingPoolElem, 1)) {}
+    ~GrowingPool(void) { PF_ASSERT(current); PF_DELETE(current); }
+    T *allocate(void) {
+      if (UNLIKELY(current->allocated == current->maxElemNum)) {
+        GrowingPoolElem *elem = PF_NEW(GrowingPoolElem, 2 * current->maxElemNum);
+        elem->next = current;
+        current = elem;
+      }
+      T *data = current->data + current->allocated++;
+      return data;
+    }
+  private:
+    /*! Chunk of elements to allocate */
+    class GrowingPoolElem
+    {
+      friend class GrowingPool;
+      GrowingPoolElem(size_t elemNum) {
+        this->data = PF_NEW_ARRAY(T, elemNum);
+        this->next = NULL;
+        this->maxElemNum = elemNum;
+        this->allocated = 0;
+      }
+      ~GrowingPoolElem(void) {
+        PF_ASSERT(this->data);
+        PF_DELETE_ARRAY(this->data);
+        if (this->next) PF_DELETE(this->next);
+      }
+      T *data;
+      GrowingPoolElem *next;
+      size_t allocated, maxElemNum;
+    };
+    GrowingPoolElem *current;
+    PF_CLASS(GrowingPool);
+  };
+} /* namespace pf */
+
+#endif /* __PF_ALLOC_HPP__ */
+
diff --git a/backend/src/sys/array.hpp b/backend/src/sys/array.hpp
new file mode 100644 (file)
index 0000000..04cc3c6
--- /dev/null
@@ -0,0 +1,108 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_ARRAY_HPP__
+#define __PF_ARRAY_HPP__
+
+#include "sys/platform.hpp"
+#include <vector>
+
+namespace pf
+{
+  /*! Non resizable array with no checking. We make it non-copiable right now
+   *  since we do not want to implement an expensive deep copy
+   */
+  template<class T>
+  class array
+  {
+  public:
+    /*! Create an empty array */
+    INLINE array(void) : elem(NULL), elemNum(0) {}
+    /*! Allocate an array with elemNum allocated elements */
+    INLINE array(size_t elemNum) : elem(NULL), elemNum(0) { this->resize(elemNum); }
+    /*! Copy constructor */
+    INLINE array(const array &other) {
+      this->elemNum = other.elemNum;
+      if (this->elemNum) {
+        this->elem = PF_NEW_ARRAY(T, this->elemNum);
+        for (size_t i = 0; i < this->elemNum; ++i) this->elem[i] = other.elem[i];
+      } else
+        this->elem = NULL;
+    }
+    /*! Assignment operator */
+    INLINE array& operator= (const array &other) {
+      if (this->elem != NULL && this->elemNum != other->elemNum) {
+        PF_DELETE_ARRAY(this->elem);
+        this->elem = NULL;
+        this->elemNum = 0;
+      }
+      this->elemNum = other.elemNum;
+      if (this->elemNum) {
+        if (this->elem == NULL)
+          this->elem = PF_NEW_ARRAY(T, this->elemNum);
+        for (size_t i = 0; i < this->elemNum; ++i) this->elem[i] = other.elem[i];
+      } else
+        this->elem = NULL;
+      return *this;
+    }
+    /*! Delete the allocated elements */
+    INLINE ~array(void) { PF_SAFE_DELETE_ARRAY(elem); }
+    /*! Free the already allocated elements and allocate a new array */
+    INLINE void resize(size_t elemNum_) {
+      if (elemNum_ != this->elemNum) {
+        PF_SAFE_DELETE_ARRAY(elem);
+        if (elemNum_)
+          this->elem = PF_NEW_ARRAY(T, elemNum_);
+        else
+          this->elem = NULL;
+        this->elemNum = elemNum_;
+      }
+    }
+    /*! Steal the pointer. The array becomes emtpy */
+    INLINE T *steal(void) {
+      T *stolen = this->elem;
+      this->elem = NULL;
+      this->elemNum = 0;
+      return stolen;
+    }
+    /*! First element */
+    INLINE T *begin(void) { return this->elem; }
+    /*! First non-valid element */
+    INLINE T *end(void) { return this->elem + elemNum; }
+    /*! Get element at position index (with a bound check) */
+    INLINE T &operator[] (size_t index) {
+      PF_ASSERT(elem && index < elemNum);
+      return elem[index];
+    }
+    /*! Get element at position index (with bound check) */
+    INLINE const T &operator[] (size_t index) const {
+      PF_ASSERT(elem && index < elemNum);
+      return elem[index];
+    }
+    /*! Return the number of elements */
+    INLINE size_t size(void) const { return this->elemNum; }
+  private:
+    T *elem;        //!< Points to the elements
+    size_t elemNum; //!< Number of elements in the array
+    PF_CLASS(array);
+  };
+} /* namespace pf */
+
+#endif /* __PF_ARRAY_HPP__ */
+
diff --git a/backend/src/sys/atomic.hpp b/backend/src/sys/atomic.hpp
new file mode 100644 (file)
index 0000000..07b2fda
--- /dev/null
@@ -0,0 +1,57 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_ATOMIC_HPP__
+#define __PF_ATOMIC_HPP__
+
+#include "sys/intrinsics.hpp"
+
+namespace pf
+{
+  template <typename T>
+  struct AtomicInternal {
+  protected:
+    AtomicInternal(const AtomicInternal&); // don't implement
+    AtomicInternal& operator= (const AtomicInternal&); // don't implement
+
+  public:
+    INLINE AtomicInternal(void) {}
+    INLINE AtomicInternal(T data) : data(data) {}
+    INLINE AtomicInternal& operator =(const T input) { data = input; return *this; }
+    INLINE operator T() const { return data; }
+    INLINE void storeRelease(T x) { __store_release(&data, x); }
+  public:
+    INLINE friend T operator+= (AtomicInternal& value, T input) { return atomic_add(&value.data, input) + input; }
+    INLINE friend T operator++ (AtomicInternal& value) { return atomic_add(&value.data,  1) + 1; }
+    INLINE friend T operator-- (AtomicInternal& value) { return atomic_add(&value.data, -1) - 1; }
+    INLINE friend T operator++ (AtomicInternal& value, int) { return atomic_add(&value.data,  1); }
+    INLINE friend T operator-- (AtomicInternal& value, int) { return atomic_add(&value.data, -1); }
+    INLINE friend T cmpxchg    (AtomicInternal& value, const T v, const T c) { return atomic_cmpxchg(&value.data,v,c); }
+
+  private:
+    volatile T data;
+    PF_STRUCT(AtomicInternal);
+  };
+
+  typedef AtomicInternal<atomic32_t> Atomic32;
+  typedef AtomicInternal<atomic_t> Atomic;
+}
+
+#endif /* __PF_ATOMIC_HPP__ */
+
diff --git a/backend/src/sys/barrier.hpp b/backend/src/sys/barrier.hpp
new file mode 100644 (file)
index 0000000..9182a98
--- /dev/null
@@ -0,0 +1,62 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_BARRIER_H__
+#define __PF_BARRIER_H__
+
+#include "sys/condition.hpp"
+
+namespace pf
+{
+  /*! system barrier using operating system */
+  class BarrierSys
+  {
+  public:
+
+    void init(size_t count) {
+      this->count = 0;
+      this->full_size = count;
+    }
+
+    int wait() {
+      count_mutex.lock();
+      count++;
+      if (count == full_size) {
+        count = 0;
+        cond.broadcast();
+        count_mutex.unlock();
+        return 1;
+      }
+      cond.wait(count_mutex);
+      count_mutex.unlock();
+      return 0;
+    }
+
+  protected:
+    size_t count, full_size;
+    MutexSys count_mutex;
+    ConditionSys cond;
+    PF_CLASS(BarrierSys);
+  };
+
+  /* default barrier type */
+  class Barrier : public BarrierSys {};
+}
+
+#endif
diff --git a/backend/src/sys/condition.cpp b/backend/src/sys/condition.cpp
new file mode 100644 (file)
index 0000000..27923f2
--- /dev/null
@@ -0,0 +1,139 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/condition.hpp"
+
+#if defined(__WIN32__)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#if defined(__GNUC__)
+
+namespace pf
+{
+  // This is an implementation of POSIX "compatible" condition variables for
+  // Win32, as described by Douglas C. Schmidt and Irfan Pyarali:
+  // http://www.cs.wustl.edu/~schmidt/win32-cv-1.html. The code is directly
+  // readapted from the glfw source code that may be found here:
+  // http://www.glfw.org
+  enum {
+    MINGW32_COND_SIGNAL     = 0,
+    MINGW32_COND_BROADCAST  = 1
+  };
+
+  /*! Implement the internal condition variable implementation Mingw lacks */
+  struct Mingw32Cond
+  {
+    HANDLE events[2];                   //<! Signal and broadcast event HANDLEs
+    unsigned int waiters_count;         //<! Count of the number of waiters
+    CRITICAL_SECTION waiters_count_lock;//!< Serialize access to <waiters_count>
+  };
+
+  ConditionSys::ConditionSys ()
+  {
+    cond = (Mingw32Cond *) PF_NEW(Mingw32Cond);
+    ((Mingw32Cond *)cond)->waiters_count = 0;
+    ((Mingw32Cond *)cond)->events[MINGW32_COND_SIGNAL]    = CreateEvent(NULL, FALSE, FALSE, NULL);
+    ((Mingw32Cond *)cond)->events[MINGW32_COND_BROADCAST] = CreateEvent(NULL, TRUE, FALSE, NULL);
+    InitializeCriticalSection(&((Mingw32Cond *)cond)->waiters_count_lock);
+  }
+
+  ConditionSys::~ConditionSys ()
+  {
+    CloseHandle(((Mingw32Cond *)cond)->events[MINGW32_COND_SIGNAL]);
+    CloseHandle(((Mingw32Cond *)cond)->events[MINGW32_COND_BROADCAST]);
+    DeleteCriticalSection(&((Mingw32Cond *)cond)->waiters_count_lock);
+    PF_DELETE((Mingw32Cond *)cond);
+  }
+
+  void ConditionSys::wait(MutexSys& mutex)
+  {
+    Mingw32Cond *cv = (Mingw32Cond *) cond;
+    int result, last_waiter;
+    DWORD timeout_ms;
+
+    // Avoid race conditions
+    EnterCriticalSection(&cv->waiters_count_lock);
+    cv->waiters_count ++;
+    LeaveCriticalSection(&cv->waiters_count_lock);
+
+    // It's ok to release the mutex here since Win32 manual-reset events
+    // maintain state when used with SetEvent()
+    LeaveCriticalSection((CRITICAL_SECTION *) mutex.mutex);
+    timeout_ms = INFINITE;
+
+    // Wait for either event to become signaled
+    result = WaitForMultipleObjects(2, cv->events, FALSE, timeout_ms);
+
+    // Check if we are the last waiter
+    EnterCriticalSection(&cv->waiters_count_lock);
+    cv->waiters_count --;
+    last_waiter = (result == WAIT_OBJECT_0 + MINGW32_COND_BROADCAST) &&
+                  (cv->waiters_count == 0);
+    LeaveCriticalSection(&cv->waiters_count_lock);
+
+    // Some thread called broadcast
+    if (last_waiter) {
+      // We're the last waiter to be notified or to stop waiting, so
+      // reset the manual event
+      ResetEvent(cv->events[MINGW32_COND_BROADCAST]);
+    }
+
+    // Reacquire the mutex
+    EnterCriticalSection((CRITICAL_SECTION *) mutex.mutex);
+  }
+
+  void ConditionSys::broadcast()
+  {
+    Mingw32Cond *cv = (Mingw32Cond *) cond;
+    int have_waiters;
+
+    // Avoid race conditions
+    EnterCriticalSection(&cv->waiters_count_lock);
+    have_waiters = cv->waiters_count > 0;
+    LeaveCriticalSection(&cv->waiters_count_lock);
+
+    if (have_waiters)
+      SetEvent(cv->events[MINGW32_COND_BROADCAST]);
+  }
+} /* namespace pf */
+#else
+
+namespace pf
+{
+  /*! system condition using windows API */
+  ConditionSys::ConditionSys () { cond = PF_NEW(CONDITION_VARIABLE); InitializeConditionVariable((CONDITION_VARIABLE*)cond); }
+  ConditionSys::~ConditionSys() { PF_DELETE((CONDITION_VARIABLE*)cond); }
+  void ConditionSys::wait(MutexSys& mutex) { SleepConditionVariableCS((CONDITION_VARIABLE*)cond, (CRITICAL_SECTION*)mutex.mutex, INFINITE); }
+  void ConditionSys::broadcast() { WakeAllConditionVariable((CONDITION_VARIABLE*)cond); }
+} /* namespace pf */
+#endif /* __GNUC__ */
+#endif /* __WIN32__ */
+
+#if defined(__UNIX__)
+#include <pthread.h>
+namespace pf
+{
+  ConditionSys::ConditionSys () { cond = PF_NEW(pthread_cond_t); pthread_cond_init((pthread_cond_t*)cond,NULL); }
+  ConditionSys::~ConditionSys() { PF_DELETE((pthread_cond_t*)cond); }
+  void ConditionSys::wait(MutexSys& mutex) { pthread_cond_wait((pthread_cond_t*)cond, (pthread_mutex_t*)mutex.mutex); }
+  void ConditionSys::broadcast() { pthread_cond_broadcast((pthread_cond_t*)cond); }
+} /* namespace pf */
+#endif /* __UNIX__ */
+
diff --git a/backend/src/sys/condition.hpp b/backend/src/sys/condition.hpp
new file mode 100644 (file)
index 0000000..a6d71f7
--- /dev/null
@@ -0,0 +1,40 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_CONDITION_HPP__
+#define __PF_CONDITION_HPP__
+
+#include "sys/mutex.hpp"
+
+namespace pf
+{
+  class ConditionSys
+  {
+  public:
+    ConditionSys(void);
+    ~ConditionSys(void);
+    void wait(class MutexSys& mutex);
+    void broadcast(void);
+  protected:
+    void* cond;
+  };
+}
+
+#endif
+
diff --git a/backend/src/sys/constants.hpp b/backend/src/sys/constants.hpp
new file mode 100644 (file)
index 0000000..9849d11
--- /dev/null
@@ -0,0 +1,144 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_CONSTANTS_HPP__
+#define __PF_CONSTANTS_HPP__
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#include <limits>
+
+namespace pf
+{
+  static struct NullTy {
+  } null MAYBE_UNUSED;
+
+  static struct TrueTy {
+    INLINE operator bool( ) const { return true; }
+  } True MAYBE_UNUSED;
+
+  static struct FalseTy {
+    INLINE operator bool( ) const { return false; }
+  } False MAYBE_UNUSED;
+
+  static struct ZeroTy
+  {
+    INLINE operator double( ) const { return 0; }
+    INLINE operator float ( ) const { return 0; }
+    INLINE operator int64 ( ) const { return 0; }
+    INLINE operator uint64( ) const { return 0; }
+    INLINE operator int32 ( ) const { return 0; }
+    INLINE operator uint32( ) const { return 0; }
+    INLINE operator int16 ( ) const { return 0; }
+    INLINE operator uint16( ) const { return 0; }
+    INLINE operator int8  ( ) const { return 0; }
+    INLINE operator uint8 ( ) const { return 0; }
+#ifndef __MSVC__
+    INLINE operator size_t( ) const { return 0; }
+#endif
+
+  } zero MAYBE_UNUSED;
+
+  static struct OneTy
+  {
+    INLINE operator double( ) const { return 1; }
+    INLINE operator float ( ) const { return 1; }
+    INLINE operator int64 ( ) const { return 1; }
+    INLINE operator uint64( ) const { return 1; }
+    INLINE operator int32 ( ) const { return 1; }
+    INLINE operator uint32( ) const { return 1; }
+    INLINE operator int16 ( ) const { return 1; }
+    INLINE operator uint16( ) const { return 1; }
+    INLINE operator int8  ( ) const { return 1; }
+    INLINE operator uint8 ( ) const { return 1; }
+#ifndef __MSVC__
+    INLINE operator size_t( ) const { return 1; }
+#endif
+  } one MAYBE_UNUSED;
+
+  static struct NegInfTy
+  {
+    INLINE operator double( ) const { return -std::numeric_limits<double>::infinity(); }
+    INLINE operator float ( ) const { return -std::numeric_limits<float>::infinity(); }
+    INLINE operator int64 ( ) const { return std::numeric_limits<int64>::min(); }
+    INLINE operator uint64( ) const { return std::numeric_limits<uint64>::min(); }
+    INLINE operator int32 ( ) const { return std::numeric_limits<int32>::min(); }
+    INLINE operator uint32( ) const { return std::numeric_limits<uint32>::min(); }
+    INLINE operator int16 ( ) const { return std::numeric_limits<int16>::min(); }
+    INLINE operator uint16( ) const { return std::numeric_limits<uint16>::min(); }
+    INLINE operator int8  ( ) const { return std::numeric_limits<int8>::min(); }
+    INLINE operator uint8 ( ) const { return std::numeric_limits<uint8>::min(); }
+#ifndef __MSVC__
+    INLINE operator size_t( ) const { return std::numeric_limits<size_t>::min(); }
+#endif
+
+  } neg_inf MAYBE_UNUSED;
+
+  static struct PosInfTy
+  {
+    INLINE operator double( ) const { return std::numeric_limits<double>::infinity(); }
+    INLINE operator float ( ) const { return std::numeric_limits<float>::infinity(); }
+    INLINE operator int64 ( ) const { return std::numeric_limits<int64>::max(); }
+    INLINE operator uint64( ) const { return std::numeric_limits<uint64>::max(); }
+    INLINE operator int32 ( ) const { return std::numeric_limits<int32>::max(); }
+    INLINE operator uint32( ) const { return std::numeric_limits<uint32>::max(); }
+    INLINE operator int16 ( ) const { return std::numeric_limits<int16>::max(); }
+    INLINE operator uint16( ) const { return std::numeric_limits<uint16>::max(); }
+    INLINE operator int8  ( ) const { return std::numeric_limits<int8>::max(); }
+    INLINE operator uint8 ( ) const { return std::numeric_limits<uint8>::max(); }
+#ifndef _WIN32
+    INLINE operator size_t( ) const { return std::numeric_limits<size_t>::max(); }
+#endif
+  } inf MAYBE_UNUSED, pos_inf MAYBE_UNUSED;
+
+  static struct NaNTy
+  {
+    INLINE operator double( ) const { return std::numeric_limits<double>::quiet_NaN(); }
+    INLINE operator float ( ) const { return std::numeric_limits<float>::quiet_NaN(); }
+  } nan MAYBE_UNUSED;
+
+  static struct UlpTy
+  {
+    INLINE operator double( ) const { return std::numeric_limits<double>::epsilon(); }
+    INLINE operator float ( ) const { return std::numeric_limits<float>::epsilon(); }
+  } ulp MAYBE_UNUSED;
+
+  static struct PiTy
+  {
+    INLINE operator double( ) const { return 3.14159265358979323846; }
+    INLINE operator float ( ) const { return 3.14159265358979323846f; }
+  } pi MAYBE_UNUSED;
+
+  static struct StepTy {
+  } step MAYBE_UNUSED;
+
+  static struct EmptyTy {
+  } empty MAYBE_UNUSED;
+
+  static struct FullTy {
+  } full MAYBE_UNUSED;
+
+  static const size_t KB = 1024u;
+  static const size_t MB = KB*KB;
+  static const size_t GB = KB*MB;
+}
+
+#endif
diff --git a/backend/src/sys/default_path.cpp b/backend/src/sys/default_path.cpp
new file mode 100644 (file)
index 0000000..3661fee
--- /dev/null
@@ -0,0 +1,38 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/default_path.hpp"
+#include "platform.hpp"
+
+namespace pf
+{
+  const char *defaultPath[] = {
+    "./share/",
+    "../share/",
+    "../../share/",
+    "./",
+    "../",
+    "../../",
+    "./data/",
+    "../data/",
+    "../../data/"
+  };
+  const size_t defaultPathNum = ARRAY_ELEM_NUM(defaultPath);
+} /* namespace pf */
+
diff --git a/backend/src/sys/default_path.hpp b/backend/src/sys/default_path.hpp
new file mode 100644 (file)
index 0000000..5f84179
--- /dev/null
@@ -0,0 +1,34 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __DEFAULT_PATH_HPP__
+#define __DEFAULT_PATH_HPP__
+
+#include <cstdlib>
+
+namespace pf
+{
+  /*! Where you may find data files and shaders */
+  extern const char *defaultPath[];
+  /*! Number of default paths */
+  extern const size_t defaultPathNum;
+} /* namespace pf */
+
+#endif /* __DEFAULT_PATH_HPP__ */
+
diff --git a/backend/src/sys/filename.cpp b/backend/src/sys/filename.cpp
new file mode 100644 (file)
index 0000000..58221f5
--- /dev/null
@@ -0,0 +1,123 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/platform.hpp"
+#include "sys/filename.hpp"
+
+namespace pf
+{
+#ifdef __WIN32__
+  const char path_sep = '\\';
+#else
+  const char path_sep = '/';
+#endif
+
+  /*! little helper to not depend on math */
+  static size_t maxInt(size_t a, size_t b) { return index_t(a) < index_t(b) ? b : a; }
+
+  /*! create an empty filename */
+  FileName::FileName () {}
+
+  /*! create a valid filename from a string */
+  FileName::FileName (const char* in) {
+    filename = in;
+    for (size_t i=0; i<filename.size(); i++)
+      if (filename[i] == '\\' || filename[i] == '/')
+        filename[i] = path_sep;
+    while (!filename.empty() && filename[filename.size()-1] == path_sep)
+      filename.resize(filename.size()-1);
+  }
+
+  /*! create a valid filename from a string */
+  FileName::FileName (const std::string& in) {
+    filename = in;
+    for (size_t i=0; i<filename.size(); i++)
+      if (filename[i] == '\\' || filename[i] == '/')
+        filename[i] = path_sep;
+    while (!filename.empty() && filename[filename.size()-1] == path_sep)
+      filename.resize(filename.size()-1);
+  }
+
+  /*! returns the path */
+  FileName FileName::path() const {
+    size_t pos = maxInt(filename.find_last_of('\\'),filename.find_last_of('/'));
+    if (pos == std::string::npos) return FileName();
+    return filename.substr(0,pos);
+  }
+
+  /*! returns the basename */
+  std::string FileName::base() const {
+    size_t pos = maxInt(filename.find_last_of('\\'),filename.find_last_of('/'));
+    if (pos == std::string::npos) return filename;
+    return filename.substr(pos+1);
+  }
+
+  /*! returns the extension */
+  std::string FileName::ext() const {
+    size_t pos = filename.find_last_of('.');
+    if (pos == std::string::npos) return "";
+    return filename.substr(pos+1);
+  }
+
+  /*! returns the basename without extension */
+  std::string FileName::name() const {
+    size_t start = maxInt(filename.find_last_of('\\'),filename.find_last_of('/')) + 1;
+    if (start == std::string::npos) start = 0;
+    size_t end = filename.find_last_of('.');
+    if (end == std::string::npos || end < start) end = filename.size();
+    return filename.substr(start, end - start);
+  }
+
+  /*! replaces the extension */
+  FileName FileName::setExt(const std::string& ext) const {
+    size_t start = maxInt(filename.find_last_of('\\'),filename.find_last_of('/')) + 1;
+    if (start == std::string::npos) start = 0;
+    size_t end = filename.find_last_of('.');
+    if (end == std::string::npos || end < start) return FileName(filename+ext);
+    return FileName(filename.substr(0,end)+ext);
+  }
+
+  /*! adds the extension */
+  FileName FileName::addExt(const std::string& ext) const {
+    return FileName(filename+ext);
+  }
+
+  /*! concatenates two filenames to this/other */
+  FileName FileName::operator +( const FileName& other ) const {
+    if (filename == "") return FileName(other);
+    else return FileName(filename + path_sep + other.filename);
+  }
+
+  /*! concatenates two filenames to this/other */
+  FileName FileName::operator +( const std::string& other ) const {
+    return operator+(FileName(other));
+  }
+
+  /*! removes the base from a filename (if possible) */
+  FileName FileName::operator -( const FileName& base ) const {
+    size_t pos = filename.find_first_of(base);
+    if (pos == std::string::npos) return *this;
+    return FileName(filename.substr(pos+1));
+  }
+
+  /*! output operator */
+  std::ostream& operator<<(std::ostream& cout, const FileName& filename) {
+    return cout << filename.filename;
+  }
+}
diff --git a/backend/src/sys/filename.hpp b/backend/src/sys/filename.hpp
new file mode 100644 (file)
index 0000000..4f4fb39
--- /dev/null
@@ -0,0 +1,72 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_FILENAME_HPP__
+#define __PF_FILENAME_HPP__
+
+#include "platform.hpp"
+#include <string>
+#include <cstdio>
+
+namespace pf
+{
+  /*! Convenience class for handling file names and paths. */
+  class FileName
+  {
+  public:
+    /*! create an empty filename */
+    FileName ();
+    /*! create a valid filename from a string */
+    FileName (const char* filename);
+    /*! create a valid filename from a string */
+    FileName (const std::string& filename);
+    /*! auto convert into a string */
+    operator std::string() const { return filename; }
+    /*! returns a string of the filename */
+    const std::string str() const { return filename; }
+    /*! returns a c-string of the filename */
+    const char* c_str() const { return filename.c_str(); }
+    /*! returns the path of a filename */
+    FileName path() const;
+    /*! returns the file of a filename  */
+    std::string base() const;
+    /*! returns the base of a filename without extension */
+    std::string name() const;
+    /*! returns the file extension */
+    std::string ext() const;
+    /*! replaces the file extension */
+    FileName setExt(const std::string& ext = "") const;
+    /*! adds file extension */
+    FileName addExt(const std::string& ext = "") const;
+    /*! concatenates two filenames to this/other */
+    FileName operator +( const FileName& other ) const;
+    /*! concatenates two filenames to this/other */
+    FileName operator +( const std::string& other ) const;
+    /*! removes the base from a filename (if possible) */
+    FileName operator -( const FileName& base ) const;
+    /*! output operator */
+    friend std::ostream& operator<<(std::ostream& cout, const FileName& filename);
+  private:
+    std::string filename;
+    PF_CLASS(FileName);
+  };
+}
+
+#endif /* __PF_FILENAME_HPP__ */
+
diff --git a/backend/src/sys/fixed_array.hpp b/backend/src/sys/fixed_array.hpp
new file mode 100644 (file)
index 0000000..68593ec
--- /dev/null
@@ -0,0 +1,79 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_FIXED_ARRAY_HPP__
+#define __PF_FIXED_ARRAY_HPP__
+
+#include "platform.hpp"
+#include <cstring>
+
+namespace pf
+{
+  /*! Regular C array but with bound checks */
+  template<typename T, size_t N>
+  class fixed_array
+  {
+  public:
+    /*! Do not initialize the data */
+    fixed_array(void) {}
+    /*! Copy the input array */
+    fixed_array(const T array[N]) { std::memcpy(elem, array, N * sizeof(T)); }
+    /*! First element (non const) */
+    T* begin(void) { return &elem[0]; }
+    /*! First non-valid element (non const) */
+    T* end(void) { return begin() + N; }
+    /*! First element (const) */
+    const T* begin(void) const { return &elem[0]; }
+    /*! First non-valid element (const) */
+    const T* end(void) const { return begin() + N; }
+    /*! Number of elements in the array */
+    size_t size(void) const { return N; }
+    /*! Get the pointer to the data (non-const) */
+    T* data(void) { return &elem[0]; }
+    /*! Get the pointer to the data (const) */
+    const T* data(void) const { return &elem[0]; }
+    /*! First element (const) */
+    const T& front(void) const { return *begin(); }
+    /*! Last element (const) */
+    const T& back(void) const { return *(end() - 1); }
+    /*! First element (non-const) */
+    T& front(void) { return *begin(); }
+    /*! Last element (non-const) */
+    T& back(void) { return *(end() - 1); }
+    /*! Get element at position index (with bound check) */
+    INLINE T& operator[] (size_t index) {
+      PF_ASSERT(index < size());
+      return elem[index];
+    }
+    /*! Get element at position index (with bound check) */
+    INLINE const T& operator[] (size_t index) const {
+      PF_ASSERT(index < size());
+      return elem[index];
+    }
+  private:
+    T elem[N];            //!< Store the elements
+    STATIC_ASSERT(N > 0); //!< zero element is not allowed
+    PF_CLASS(fixed_array);
+  };
+
+} /* namespace pf */
+
+#endif /* __PF_FIXED_ARRAY_HPP__ */
+
+
diff --git a/backend/src/sys/hash_map.hpp b/backend/src/sys/hash_map.hpp
new file mode 100644 (file)
index 0000000..ab1a317
--- /dev/null
@@ -0,0 +1,73 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_HASH_MAP_HPP__
+#define __PF_HASH_MAP_HPP__
+
+#include "sys/platform.hpp"
+
+#ifdef __MSVC__
+#include <unordered_map>
+#else
+#include <tr1/unordered_map>
+#endif /* __MSVC__ */
+
+namespace pf
+{
+  /*! Add specific allocator to the hash map */
+  template <class Key,
+            class T,
+            class Hash = std::hash<Key>,
+            class Pred = std::equal_to<Key>>
+  class hash_map : public std::tr1::unordered_map<Key,T,Hash,Pred,Allocator<std::pair<const Key,T>>>
+  {
+  public:
+    // Typedefs
+    typedef std::pair<const Key, T> value_type;
+    typedef Allocator<value_type> allocator_type;
+    typedef std::tr1::unordered_map<Key,T,Hash,Pred,allocator_type> parent_type;
+    typedef typename allocator_type::size_type size_type;
+    typedef Key key_type;
+    typedef T mapped_type;
+    typedef Hash hasher;
+    typedef Pred key_equal;
+
+    /*! Default constructor */
+    INLINE explicit hash_map(size_type n = 3,
+                             const hasher& hf = hasher(),
+                             const key_equal& eql = key_equal(),
+                             const allocator_type& a = allocator_type()) :
+      parent_type(n, hf, eql, a) {}
+    /*! Iteration constructor */
+    template <class InputIterator>
+    INLINE hash_map(InputIterator first,
+                    InputIterator last,
+                    size_type n = 3,
+                    const hasher& hf = hasher(),
+                    const key_equal& eql = key_equal(),
+                    const allocator_type& a = allocator_type()) :
+      parent_type(first,last,n,hf,eql,a) {}
+    /*! Copy constructor */
+    INLINE hash_map(const hash_map &other) : parent_type(other) {}
+    PF_CLASS(hash_map);
+  };
+} /* namespace pf */
+
+#endif /* __PF_HASH_MAP_HPP__ */
+
diff --git a/backend/src/sys/intrinsics.hpp b/backend/src/sys/intrinsics.hpp
new file mode 100644 (file)
index 0000000..99f5552
--- /dev/null
@@ -0,0 +1,210 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_INTRINSICS_H__
+#define __PF_INTRINSICS_H__
+
+#include "sys/platform.hpp"
+#include <xmmintrin.h>
+#include <emmintrin.h>
+
+#if defined(__MSVC__)
+
+#include <intrin.h>
+
+#define PF_COMPILER_WRITE_BARRIER       _WriteBarrier()
+#define PF_COMPILER_READ_WRITE_BARRIER  _ReadWriteBarrier()
+
+#if _MSC_VER >= 1400
+#pragma intrinsic(_ReadBarrier)
+#define PF_COMPILER_READ_BARRIER        _ReadBarrier()
+#else
+#define PF_COMPILER_READ_BARRIER        _ReadWriteBarrier()
+#endif /* _MSC_VER >= 1400 */
+
+INLINE int __bsf(int v) {
+  unsigned long r = 0; _BitScanForward(&r,v); return r;
+}
+
+INLINE int __bsr(int v) {
+  unsigned long r = 0; _BitScanReverse(&r,v); return r;
+}
+
+INLINE int __btc(int v, int i) {
+  long r = v; _bittestandcomplement(&r,i); return r;
+}
+
+INLINE int __bts(int v, int i) {
+  long r = v; _bittestandset(&r,i); return r;
+}
+
+INLINE int __btr(int v, int i) {
+  long r = v; _bittestandreset(&r,i); return r;
+}
+
+INLINE void memoryFence(void) { _mm_mfence(); }
+
+#if defined(__X86_64__) && !defined(__INTEL_COMPILER)
+
+INLINE size_t __bsf(size_t v) {
+  unsigned long r = 0; _BitScanForward64(&r,v); return r;
+}
+
+INLINE size_t __bsr(size_t v) {
+  unsigned long r = 0; _BitScanReverse64(&r,v); return r;
+}
+
+INLINE size_t __btc(size_t v, size_t i) {
+  __int64 r = v; _bittestandcomplement64(&r,i); return r;
+}
+
+INLINE size_t __bts(size_t v, size_t i) {
+  __int64 r = v; _bittestandset64(&r,i); return r;
+}
+
+INLINE size_t __btr(size_t v, size_t i) {
+  __int64 r = v; _bittestandreset64(&r,i); return r;
+}
+
+#endif /* defined(__X86_64__) && !defined(__INTEL_COMPILER) */
+
+typedef int32 atomic32_t;
+
+INLINE int32 atomic_add(volatile int32* m, const int32 v) {
+  return _InterlockedExchangeAdd((volatile long*)m,v);
+}
+
+INLINE int32 atomic_cmpxchg(volatile int32* m, const int32 v, const int32 c) {
+  return _InterlockedCompareExchange((volatile long*)m,v,c);
+}
+
+#if defined(__X86_64__)
+
+typedef int64 atomic_t;
+
+INLINE int64 atomic_add(volatile int64* m, const int64 v) {
+  return _InterlockedExchangeAdd64(m,v);
+}
+
+INLINE int64 atomic_cmpxchg(volatile int64* m, const int64 v, const int64 c) {
+  return _InterlockedCompareExchange64(m,v,c);
+}
+
+#else
+
+typedef int32 atomic_t;
+
+#endif /* defined(__X86_64__) */
+
+#else
+
+INLINE unsigned int __popcnt(unsigned int in) {
+  int r = 0; asm ("popcnt %1,%0" : "=r"(r) : "r"(in)); return r;
+}
+
+INLINE int __bsf(int v) {
+  int r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
+}
+
+INLINE int __bsr(int v) {
+  int r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r;
+}
+
+INLINE int __btc(int v, int i) {
+  int r = 0; asm ("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+}
+
+INLINE int __bts(int v, int i) {
+  int r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+}
+
+INLINE int __btr(int v, int i) {
+  int r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+}
+
+INLINE size_t __bsf(size_t v) {
+  size_t r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
+}
+
+INLINE size_t __bsr(size_t v) {
+  size_t r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r;
+}
+
+INLINE size_t __btc(size_t v, size_t i) {
+  size_t r = 0; asm ("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+}
+
+INLINE size_t __bts(size_t v, size_t i) {
+  size_t r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+}
+
+INLINE size_t __btr(size_t v, size_t i) {
+  size_t r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+}
+
+INLINE void memoryFence(void) { _mm_mfence(); }
+
+typedef int32 atomic32_t;
+
+INLINE int32 atomic_add(int32 volatile* value, int32 input)
+{  asm volatile("lock xadd %0,%1" : "+r" (input), "+m" (*value) : "r" (input), "m" (*value)); return input; }
+
+INLINE int32 atomic_cmpxchg(int32 volatile* value, const int32 input, int32 comparand)
+{  asm volatile("lock cmpxchg %2,%0" : "=m" (*value), "=a" (comparand) : "r" (input), "m" (*value), "a" (comparand) : "flags"); return comparand; }
+
+#if defined(__X86_64__)
+
+  typedef int64 atomic_t;
+
+  INLINE int64 atomic_add(int64 volatile* value, int64 input)
+  {  asm volatile("lock xaddq %0,%1" : "+r" (input), "+m" (*value) : "r" (input), "m" (*value));  return input;  }
+
+  INLINE int64 atomic_cmpxchg(int64 volatile* value, const int64 input, int64 comparand)
+  {  asm volatile("lock cmpxchgq %2,%0" : "+m" (*value), "+a" (comparand) : "r" (input), "m" (*value), "r" (comparand) : "flags"); return comparand;  }
+
+#else
+
+  typedef int32 atomic_t;
+
+#endif /* defined(__X86_64__) */
+
+#define PF_COMPILER_READ_WRITE_BARRIER    asm volatile("" ::: "memory");
+#define PF_COMPILER_WRITE_BARRIER         PF_COMPILER_READ_WRITE_BARRIER
+#define PF_COMPILER_READ_BARRIER          PF_COMPILER_READ_WRITE_BARRIER
+
+#endif /* __MSVC__ */
+
+template <typename T>
+INLINE T __load_acquire(volatile T *ptr)
+{
+  PF_COMPILER_READ_WRITE_BARRIER;
+  T x = *ptr; // for x86, load == load_acquire
+  PF_COMPILER_READ_WRITE_BARRIER;
+  return x;
+}
+
+template <typename T>
+INLINE void __store_release(volatile T *ptr, T x)
+{
+  PF_COMPILER_READ_WRITE_BARRIER;
+  *ptr = x; // for x86, store == store_release
+  PF_COMPILER_READ_WRITE_BARRIER;
+}
+#endif /* __PF_INTRINSICS_H__ */
+
diff --git a/backend/src/sys/library.cpp b/backend/src/sys/library.cpp
new file mode 100644 (file)
index 0000000..815bd59
--- /dev/null
@@ -0,0 +1,91 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/library.hpp"
+#include "sys/sysinfo.hpp"
+#include "sys/filename.hpp"
+
+////////////////////////////////////////////////////////////////////////////////
+/// Windows Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__WIN32__)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace pf
+{
+  /* opens a shared library */
+  lib_t openLibrary(const std::string& file)
+  {
+    std::string fullName = file+".dll";
+    HMODULE handle = LoadLibraryA(fullName.c_str());
+    if (handle) return lib_t(handle);
+    handle = LoadLibrary((getExecutableFileName() + fullName).c_str());
+    return lib_t(handle);
+  }
+
+  /* returns address of a symbol from the library */
+  void* getSymbol(lib_t lib, const std::string& sym) {
+    return (void*) GetProcAddress(HMODULE(lib),sym.c_str());
+  }
+
+  /* closes the shared library */
+  void closeLibrary(lib_t lib) {
+    FreeLibrary(HMODULE(lib));
+  }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Unix Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__UNIX__)
+
+#include <dlfcn.h>
+
+namespace pf
+{
+  /* opens a shared library */
+  lib_t openLibrary(const std::string& file)
+  {
+#if defined(__MACOSX__)
+    std::string fullName = "lib"+file+".dylib";
+#else
+    std::string fullName = "lib"+file+".so";
+#endif
+    void* lib = dlopen(fullName.c_str(),RTLD_NOW);
+    if (lib) return lib_t(lib);
+    lib = dlopen((getExecutableFileName() + fullName).c_str(),RTLD_NOW);
+    return lib_t(lib);
+  }
+
+  /* returns address of a symbol from the library */
+  void* getSymbol(lib_t lib, const std::string& sym) {
+    return dlsym(lib,sym.c_str());
+  }
+
+  /* closes the shared library */
+  void closeLibrary(lib_t lib) {
+    dlclose(lib);
+  }
+}
+#endif
diff --git a/backend/src/sys/library.hpp b/backend/src/sys/library.hpp
new file mode 100644 (file)
index 0000000..8dcb1a9
--- /dev/null
@@ -0,0 +1,40 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_LIBRARY_HPP__
+#define __PF_LIBRARY_HPP__
+
+#include <string>
+
+#include "sys/platform.hpp"
+
+namespace pf
+{
+  /*! type for shared library */
+  typedef struct opaque_lib_t* lib_t;
+  /*! loads a shared library */
+  lib_t openLibrary(const std::string& file);
+  /*! returns address of a symbol from the library */
+  void* getSymbol(lib_t lib, const std::string& sym);
+  /*! unloads a shared library */
+  void closeLibrary(lib_t lib);
+} /* namespace pf */
+
+#endif /* __PF_LIBRARY_HPP__ */
+
diff --git a/backend/src/sys/list.hpp b/backend/src/sys/list.hpp
new file mode 100644 (file)
index 0000000..6f479d2
--- /dev/null
@@ -0,0 +1,60 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_LIST_HPP__
+#define __PF_LIST_HPP__
+
+#include "sys/platform.hpp"
+#include <list>
+
+namespace pf
+{
+  /*! Use custom allocator instead of std one */
+  template <typename T>
+  class list : public std::list<T, Allocator<T>>
+  {
+  public:
+    // Typedefs
+    typedef T value_type;
+    typedef Allocator<value_type> allocator_type;
+    typedef std::list<T, allocator_type> parent_type;
+    typedef typename allocator_type::size_type size_type;
+
+    /*! Default constructor */
+    INLINE explicit list(const allocator_type &a = allocator_type()) :
+      parent_type(a) {}
+    /*! Repetitive constructor */
+    INLINE explicit list(size_type n,
+                         const T &value = T(),
+                         const allocator_type &a = allocator_type()) :
+      parent_type(n, value, a) {}
+    /*! Iteration constructor */
+    template <class InputIterator>
+    INLINE list(InputIterator first,
+                InputIterator last,
+                const allocator_type &a = allocator_type()) :
+      parent_type(first, last, a) {}
+    /*! Copy constructor */
+    INLINE list(const list &x) : parent_type(x) {}
+    PF_CLASS(list);
+  };
+} /* namespace pf */
+
+#endif /* __PF_LIST_HPP__ */
+
diff --git a/backend/src/sys/logging.cpp b/backend/src/sys/logging.cpp
new file mode 100644 (file)
index 0000000..6f4c840
--- /dev/null
@@ -0,0 +1,87 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/logging.hpp"
+#include "sys/filename.hpp"
+
+namespace pf
+{
+  LoggerStream::LoggerStream(void) : next(NULL) {}
+  LoggerStream::~LoggerStream(void) {}
+
+  LoggerBuffer::LoggerBuffer(void) : logger(NULL) {}
+
+  LoggerBuffer& LoggerBuffer::operator<< (LoggerFlushTy) {
+    logger->output(ss.str());
+    ss.str("");
+    return *this;
+  }
+
+  LoggerBuffer& LoggerBuffer::operator<< (const LoggerInfo &info) {
+    FileName fileName(info.file);
+    return *this << fileName.base() << " at " << info.function << " line " << info.line;
+  }
+
+  Logger::Logger(void) : streams(NULL) {
+    const uint32 threadNum = 1;
+    this->buffers = PF_NEW_ARRAY(LoggerBuffer, threadNum);
+    for (uint32 i = 0; i < threadNum; ++i) this->buffers[i].logger = this;
+    this->startTime = getSeconds();
+  }
+
+  Logger::~Logger(void) {
+    FATAL_IF(streams != NULL, "Remove all streams before deleting the logger");
+    PF_DELETE_ARRAY(buffers);
+  }
+
+  void Logger::output(const std::string &str) {
+    Lock<MutexSys> lock(mutex);
+    LoggerStream *stream = this->streams;
+    while (stream) {
+      *stream << str;
+      stream = stream->next;
+    }
+  }
+
+  void Logger::insert(LoggerStream &stream) {
+    Lock<MutexSys> lock(mutex);
+    stream.next = this->streams;
+    this->streams = &stream;
+  }
+
+  void Logger::remove(LoggerStream &stream) {
+    Lock<MutexSys> lock(mutex);
+    LoggerStream *curr = this->streams;
+    LoggerStream *pred = NULL;
+    while (curr) {
+      if (curr == &stream)
+        break;
+      pred = curr;
+      curr = curr->next;
+    }
+    FATAL_IF (curr == NULL, "Unable to find the given stream");
+    if (pred)
+      pred->next = curr->next;
+    else
+      this->streams = curr->next;
+  }
+
+  Logger *logger = NULL;
+} /* namespace pf */
+
diff --git a/backend/src/sys/logging.hpp b/backend/src/sys/logging.hpp
new file mode 100644 (file)
index 0000000..ae69e32
--- /dev/null
@@ -0,0 +1,141 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_LOGGING_HPP__
+#define __PF_LOGGING_HPP__
+
+#include "sys/mutex.hpp"
+#include "sys/platform.hpp"
+#include <sstream>
+#include <iomanip>
+
+namespace pf
+{
+  class Logger;
+  class LoggerBuffer;
+  class LoggerStream;
+
+  /*! A logger stream is one way to output a string. It can be a file,
+   *  stdout, the in-game console and so on...
+   */
+  class LoggerStream
+  {
+  public:
+    LoggerStream(void);
+    virtual ~LoggerStream(void);
+    virtual LoggerStream& operator<< (const std::string &str) = 0;
+  private:
+    friend class Logger;
+    LoggerStream *next; //!< We chain the logger elements together
+  };
+
+  /*! Helper and proxy structures to display various information */
+  static struct LoggerFlushTy { } loggerFlush MAYBE_UNUSED;
+  struct LoggerInfo {
+    INLINE LoggerInfo(const char *file, const char *function, int line) :
+      file(file), function(function), line(line) {}
+    const char *file, *function;
+    int line;
+    PF_CLASS(LoggerInfo);
+  };
+
+  /*! Used to lazily create strings from the user defined logs. When destroyed
+   *  or flushed, it displays everything in one piece
+   */
+  class LoggerBuffer
+  {
+  public:
+    template <typename T> LoggerBuffer& operator<< (const T &x) {
+      ss << x;
+      return *this;
+    }
+    LoggerBuffer& operator<< (LoggerFlushTy);
+    LoggerBuffer& operator<< (const LoggerInfo&);
+    /*! Output the info a nice format */
+    LoggerBuffer& info(const char *file, const char *function, int line);
+  private:
+    friend class Logger;
+    LoggerBuffer(void);
+    Logger *logger;       //!< The logger that created this buffer
+    std::stringstream ss; //!< Stores all the user strings
+    PF_CLASS(LoggerBuffer);
+  };
+
+  /*! Central class to log anything from the engine */
+  class Logger
+  {
+  public:
+    Logger(void);
+    ~Logger(void);
+    /*! Output the string into all the attached streams */
+    void output(const std::string &str);
+    template <typename T> LoggerBuffer& operator<< (const T &x) {
+      const uint32 bufferID = 0;
+      LoggerBuffer &buffer = buffers[bufferID];
+      buffer << "[" << "thread " << std::setw(2) << bufferID << "] ";
+      buffer << "[" << std::setw(12) << std::fixed << getSeconds() - startTime << "s] " << x;
+      return buffer;
+    }
+    void insert(LoggerStream &stream);
+    void remove(LoggerStream &stream);
+  private:
+    MutexSys mutex;        //!< To insert / remove streams and output strings
+    LoggerStream *streams; //!< All the output streams
+    LoggerBuffer *buffers; //!< One buffer per thread
+    double startTime;      //!< When the logger has been created
+    PF_CLASS(Logger);
+  };
+
+  /*! We have one logger for the application */
+  extern Logger *logger;
+
+} /* namespace pf */
+
+/*! Macros to handle logging information in the code */
+#define PF_LOG_HERE LoggerInfo(__FILE__, __FUNCTION__, __LINE__)
+#define PF_INFO " ######## " << PF_LOG_HERE
+
+/*! Verbose macros: they add logging position and thread ID */
+#define PF_WARNING_V(MSG) do {                                                \
+  if (logger) *logger << "WARNING " << MSG << PF_INFO << "\n" << loggerFlush; \
+} while (0)
+
+#define PF_ERROR_V(MSG)   do {                                                \
+  if (logger) *logger << "ERROR " << MSG << PF_INFO << "\n" << loggerFlush;   \
+} while (0)
+
+#define PF_MSG_V(MSG)     do {                                                \
+  if (logger) *logger << MSG << PF_INFO << "\n" << loggerFlush;               \
+} while (0)
+
+/*! Regular macros: just the user message */
+#define PF_WARNING(MSG) do {                                                  \
+  if (logger) *logger << "WARNING " << MSG << "\n" << loggerFlush;            \
+} while (0)
+
+#define PF_ERROR(MSG)   do {                                                  \
+  if (logger) *logger << "ERROR " << MSG << "\n" << loggerFlush;              \
+} while (0)
+
+#define PF_MSG(MSG)     do {                                                  \
+  if (logger) *logger << MSG << "\n" << loggerFlush;                          \
+} while (0)
+
+#endif /* __PF_LOGGING_HPP__ */
+
diff --git a/backend/src/sys/map.hpp b/backend/src/sys/map.hpp
new file mode 100644 (file)
index 0000000..c673b86
--- /dev/null
@@ -0,0 +1,63 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_MAP_HPP__
+#define __PF_MAP_HPP__
+
+#include "sys/platform.hpp"
+#include <map>
+
+namespace pf
+{
+  /*! Use custom allocator instead of std one */
+  template<class Key, class T, class Pred = std::less<Key>>
+  class map : public std::map<Key,T,Pred,Allocator<std::pair<const Key, T>>>
+  {
+  public:
+    // Typedefs
+    typedef std::pair<const Key, T> value_type;
+    typedef Allocator<value_type> allocator_type;
+    typedef std::map<Key,T,Pred,allocator_type> parent_type;
+    typedef Key key_type;
+    typedef T mapped_type;
+    typedef Pred key_compare;
+    typedef typename allocator_type::pointer pointer;
+    typedef typename allocator_type::const_pointer const_pointer;
+    typedef typename allocator_type::reference reference;
+    typedef typename allocator_type::const_reference const_reference;
+
+    /*! Default constructor */
+    INLINE map(const key_compare &comp = key_compare(),
+               const allocator_type &a = allocator_type()) :
+      parent_type(comp, a) {}
+    /*! Iteration constructor */
+    template<class InputIterator>
+    INLINE map(InputIterator first,
+               InputIterator last,
+               const key_compare &comp = key_compare(),
+               const allocator_type& a = allocator_type()) :
+      parent_type(first, last, comp, a) {}
+    /*! Copy constructor */
+    INLINE map(const map& x) : parent_type(x) {}
+    PF_CLASS(map);
+  };
+} /* namespace pf */
+
+#endif /* __PF_MAP_HPP__ */
+
diff --git a/backend/src/sys/mutex.cpp b/backend/src/sys/mutex.cpp
new file mode 100644 (file)
index 0000000..590ad5d
--- /dev/null
@@ -0,0 +1,49 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/mutex.hpp"
+
+#if defined(__WIN32__)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace pf
+{
+  /*! system mutex using windows API */
+  MutexSys::MutexSys( void ) { mutex = new CRITICAL_SECTION; InitializeCriticalSection((CRITICAL_SECTION*)mutex); }
+  MutexSys::~MutexSys( void ) { DeleteCriticalSection((CRITICAL_SECTION*)mutex); delete ((CRITICAL_SECTION*)mutex); }
+  void MutexSys::lock( void ) { EnterCriticalSection((CRITICAL_SECTION*)mutex); }
+  void MutexSys::unlock( void ) { LeaveCriticalSection((CRITICAL_SECTION*)mutex); }
+}
+#endif
+
+#if defined(__UNIX__)
+#include <pthread.h>
+
+namespace pf
+{
+  /*! system mutex using pthreads */
+  MutexSys::MutexSys( void ) { mutex = new pthread_mutex_t; pthread_mutex_init((pthread_mutex_t*)mutex, NULL); }
+  MutexSys::~MutexSys( void ) { pthread_mutex_destroy((pthread_mutex_t*)mutex); delete ((pthread_mutex_t*)mutex); }
+  void MutexSys::lock( void ) { pthread_mutex_lock((pthread_mutex_t*)mutex); }
+  void MutexSys::unlock( void ) { pthread_mutex_unlock((pthread_mutex_t*)mutex); }
+}
+#endif
+
diff --git a/backend/src/sys/mutex.hpp b/backend/src/sys/mutex.hpp
new file mode 100644 (file)
index 0000000..b29b3c8
--- /dev/null
@@ -0,0 +1,75 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_MUTEX_H__
+#define __PF_MUTEX_H__
+
+#include "platform.hpp"
+#include "atomic.hpp"
+#include <xmmintrin.h>
+
+namespace pf
+{
+  class MutexSys {
+    friend class ConditionSys;
+  public:
+    MutexSys(void);
+    ~MutexSys(void);
+    void lock(void);
+    void unlock(void);
+  protected:
+    void* mutex;
+    MutexSys(const MutexSys&); // don't implement
+    MutexSys& operator= (const MutexSys&); // don't implement
+    PF_CLASS(MutexSys);
+  };
+
+  /*! active mutex */
+  class MutexActive {
+  public:
+    INLINE MutexActive(void) : $lock(LOCK_IS_FREE) {}
+    INLINE void lock(void) {
+      PF_COMPILER_READ_BARRIER;
+      while (cmpxchg($lock, LOCK_IS_TAKEN, LOCK_IS_FREE) != LOCK_IS_FREE)
+        _mm_pause();
+      PF_COMPILER_READ_BARRIER;
+    }
+    INLINE void unlock(void) { $lock.storeRelease(LOCK_IS_FREE); }
+  protected:
+    enum ${ LOCK_IS_FREE = 0, LOCK_IS_TAKEN = 1 };
+    Atomic $lock;
+    MutexActive(const MutexActive&); // don't implement
+    MutexActive& operator=(const MutexActive&); // don't implement
+    PF_CLASS(MutexActive);
+  };
+
+  /*! safe mutex lock and unlock helper */
+  template<typename Mutex> class Lock {
+  public:
+    Lock (Mutex& mutex) : mutex(mutex) { mutex.lock(); }
+    ~Lock() { mutex.unlock(); }
+  protected:
+    Mutex& mutex;
+    Lock(const Lock&); // don't implement
+    Lock& operator= (const Lock&); // don't implement
+    PF_CLASS(Lock);
+  };
+}
+
+#endif
diff --git a/backend/src/sys/platform.cpp b/backend/src/sys/platform.cpp
new file mode 100644 (file)
index 0000000..96fab95
--- /dev/null
@@ -0,0 +1,79 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/platform.hpp"
+#include "sys/intrinsics.hpp"
+#include <string>
+
+////////////////////////////////////////////////////////////////////////////////
+/// Windows Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __WIN32__
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace pf
+{
+  double getSeconds() {
+    LARGE_INTEGER freq, val;
+    QueryPerformanceFrequency(&freq);
+    QueryPerformanceCounter(&val);
+    return (double)val.QuadPart / (double)freq.QuadPart;
+  }
+
+  void FATAL(const std::string &msg) {
+    std::cerr << msg << std::endl;
+    MessageBox(NULL, msg.c_str(), "Fatal Error", MB_OK | MB_ICONEXCLAMATION);
+    PF_ASSERT(0);
+#ifdef __GNUC__
+    exit(-1);
+#else
+    _exit(-1);
+#endif /* __GNUC__ */
+  }
+
+} /* namespace pf */
+#endif /* __WIN32__ */
+
+////////////////////////////////////////////////////////////////////////////////
+/// Unix Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__UNIX__)
+
+#include <sys/time.h>
+
+namespace pf
+{
+  double getSeconds() {
+    struct timeval tp; gettimeofday(&tp,NULL);
+    return double(tp.tv_sec) + double(tp.tv_usec)/1E6;
+  }
+
+  void FATAL(const std::string &msg) {
+    std::cerr << msg << std::endl;
+    PF_ASSERT(0);
+    _exit(-1);
+  }
+} /* namespace pf */
+
+#endif /* __UNIX__ */
+
diff --git a/backend/src/sys/platform.hpp b/backend/src/sys/platform.hpp
new file mode 100644 (file)
index 0000000..ecd205f
--- /dev/null
@@ -0,0 +1,373 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_PLATFORM_HPP__
+#define __PF_PLATFORM_HPP__
+#include <cstddef>
+#include <cstdlib>
+#include <cstdio>
+#include <iostream>
+#include <cassert>
+
+////////////////////////////////////////////////////////////////////////////////
+/// CPU architecture
+////////////////////////////////////////////////////////////////////////////////
+
+/* detect 32 or 64 platform */
+#if defined(__x86_64__) || defined(__ia64__) || defined(_M_X64)
+#define __X86_64__
+#else
+#define __X86__
+#endif
+
+/* We require SSE ... */
+#ifndef __SSE__
+#define __SSE__
+#endif
+
+/* ... and SSE2 */
+#ifndef __SSE2__
+#define __SSE2__
+#endif
+
+#if defined(_INCLUDED_IMM)
+// #define __AVX__
+#endif
+
+#if defined(_MSC_VER) && (_MSC_VER < 1600) && !defined(__INTEL_COMPILER) || defined(_DEBUG) && defined(_WIN32)
+#define __NO_AVX__
+#endif
+
+#if defined(_MSC_VER) && !defined(__SSE4_2__)
+// #define __SSE4_2__  //! activates SSE4.2 support
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Operating system
+////////////////////////////////////////////////////////////////////////////////
+
+/* detect Linux platform */
+#if defined(linux) || defined(__linux__) || defined(__LINUX__)
+#  if !defined(__LINUX__)
+#     define __LINUX__
+#  endif
+#  if !defined(__UNIX__)
+#     define __UNIX__
+#  endif
+#endif
+
+/* detect FreeBSD platform */
+#if defined(__FreeBSD__) || defined(__FREEBSD__)
+#  if !defined(__FREEBSD__)
+#     define __FREEBSD__
+#  endif
+#  if !defined(__UNIX__)
+#     define __UNIX__
+#  endif
+#endif
+
+/* detect Windows 95/98/NT/2000/XP/Vista/7 platform */
+#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)) && !defined(__CYGWIN__)
+#  if !defined(__WIN32__)
+#     define __WIN32__
+#  endif
+#endif
+
+/* detect Cygwin platform */
+#if defined(__CYGWIN__)
+#  if !defined(__UNIX__)
+#     define __UNIX__
+#  endif
+#endif
+
+/* detect MAC OS X platform */
+#if defined(__APPLE__) || defined(MACOSX) || defined(__MACOSX__)
+#  if !defined(__MACOSX__)
+#     define __MACOSX__
+#  endif
+#  if !defined(__UNIX__)
+#     define __UNIX__
+#  endif
+#endif
+
+/* try to detect other Unix systems */
+#if defined(__unix__) || defined (unix) || defined(__unix) || defined(_unix)
+#  if !defined(__UNIX__)
+#     define __UNIX__
+#  endif
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Compiler
+////////////////////////////////////////////////////////////////////////////////
+
+/*! GCC compiler */
+#ifdef __GNUC__
+// #define __GNUC__
+#endif
+
+/*! Intel compiler */
+#ifdef __INTEL_COMPILER
+#define __ICC__
+#endif
+
+/*! Visual C compiler */
+#ifdef _MSC_VER
+#define __MSVC__
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Makros
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __WIN32__
+#define __dllexport extern "C" __declspec(dllexport)
+#define __dllimport extern "C" __declspec(dllimport)
+#else
+#define __dllexport extern "C"
+#define __dllimport extern "C"
+#endif
+
+#ifdef __MSVC__
+#undef NOINLINE
+#define NOINLINE             __declspec(noinline)
+#define INLINE               __forceinline
+#define RESTRICT             __restrict
+#define THREAD               __declspec(thread)
+#define ALIGNED(...)         __declspec(align(__VA_ARGS__))
+//#define __FUNCTION__           __FUNCTION__
+#define debugbreak()         __debugbreak()
+#else
+#undef NOINLINE
+#undef INLINE
+#define NOINLINE        __attribute__((noinline))
+#define INLINE          inline __attribute__((always_inline))
+#define RESTRICT        __restrict
+#define THREAD          __thread
+#define ALIGNED(...)    __attribute__((aligned(__VA_ARGS__)))
+#define __FUNCTION__    __PRETTY_FUNCTION__
+#define debugbreak()    asm ("int $3")
+#endif
+
+/*! Modern x86 processors */
+#define CACHE_LINE 64
+#define CACHE_LINE_ALIGNED ALIGNED(CACHE_LINE)
+
+#ifdef __GNUC__
+  #define MAYBE_UNUSED __attribute__((used))
+#else
+  #define MAYBE_UNUSED
+#endif
+
+#if defined(_MSC_VER)
+#define __builtin_expect(expr,b) expr
+#endif
+
+/*! Debug syntactic sugar */
+#ifdef NDEBUG
+#define IF_DEBUG(EXPR)
+#else
+#define IF_DEBUG(EXPR) EXPR
+#endif /* NDEBUG */
+
+/*! Debug printing macros */
+#define STRING(x) #x
+#define PING std::cout << __FILE__ << " (" << __LINE__ << "): " << __FUNCTION__ << std::endl
+#define PRINT(x) std::cout << STRING(x) << " = " << (x) << std::endl
+
+/*! Branch hint */
+#define LIKELY(x)       __builtin_expect(!!(x),1)
+#define UNLIKELY(x)     __builtin_expect((x),0)
+
+/*! Stringify macros */
+#define JOIN(X, Y) _DO_JOIN(X, Y)
+#define _DO_JOIN(X, Y) _DO_JOIN2(X, Y)
+#define _DO_JOIN2(X, Y) X##Y
+
+/*! Run-time assertion */
+#ifndef NDEBUG
+#define PF_ASSERT(EXPR) do {            \
+  if (UNLIKELY(!(EXPR))) assert(EXPR);  \
+} while (0)
+#else
+#define PF_ASSERT(EXPR) do { } while (0)
+#endif
+
+/*! Compile-time assertion */
+#define STATIC_ASSERT(value)                                     \
+  struct JOIN(__,JOIN(__,__LINE__)) { int x[(value) ? 1 : -1]; }
+
+/*! Fatal error macros */
+#define NOT_IMPLEMENTED FATAL ("Not implemented")
+#define FATAL_IF(COND, MSG)                          \
+do {                                                 \
+  if(UNLIKELY(COND)) FATAL(MSG);                     \
+} while (0)
+
+/* Safe deletion macros */
+#define PF_SAFE_DELETE_ARRAY(x) do { if (x != NULL) PF_DELETE_ARRAY(x); } while (0)
+#define PF_SAFE_DELETE(x) do { if (x != NULL) PF_DELETE(x); } while (0)
+
+/* Number of elements in an array */
+#define ARRAY_ELEM_NUM(x) (sizeof(x) / sizeof(x[0]))
+
+/* Align X on A */
+#define ALIGN(X,A) (((X) % (A)) ? ((X) + (A) - ((X) % (A))) : (X))
+
+/*! Produce a string from the macro locatiom */
+#define HERE (STRING(__LINE__) "@" __FILE__)
+
+/*! Portable AlignOf */
+template <typename T>
+struct AlignOf
+{
+  struct Helper { char x; T t; };
+  static const size_t value = offsetof(Helper, t);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+/// Visibility parameters (DLL export and so on)
+////////////////////////////////////////////////////////////////////////////////
+#if defined __WIN32__
+  #if defined __GNUC__
+    #define PF_EXPORT_SYMBOL __attribute__ ((dllexport))
+    #define PF_IMPORT_SYMBOL __attribute__ ((dllimport))
+  #else
+    #define PF_IMPORT_SYMBOL __declspec(dllimport)
+    #define PF_EXPORT_SYMBOL __declspec(dllexport)
+  #endif /* __GNUC__ */
+#else
+  #define PF_EXPORT_SYMBOL __attribute__ ((visibility ("default")))
+  #define PF_IMPORT_SYMBOL
+#endif /* __WIN32__ */
+
+////////////////////////////////////////////////////////////////////////////////
+/// Basic Types
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__MSVC__)
+typedef          __int64  int64;
+typedef unsigned __int64 uint64;
+typedef          __int32  int32;
+typedef unsigned __int32 uint32;
+typedef          __int16  int16;
+typedef unsigned __int16 uint16;
+typedef          __int8    int8;
+typedef unsigned __int8   uint8;
+#else
+typedef          long long  int64;
+typedef unsigned long long uint64;
+typedef                int  int32;
+typedef unsigned       int uint32;
+typedef              short  int16;
+typedef unsigned     short uint16;
+typedef               char   int8;
+typedef unsigned      char  uint8;
+#endif
+
+#if defined(__X86_64__)
+typedef int64 index_t;
+#else
+typedef int32 index_t;
+#endif
+
+/*! To protect some classes from being copied */
+class NonCopyable
+{
+protected:
+  INLINE NonCopyable(void) {}
+  INLINE ~NonCopyable(void) {}
+private: 
+  INLINE NonCopyable(const NonCopyable&) {}
+  INLINE NonCopyable& operator= (const NonCopyable&) {return *this;}
+};
+
+////////////////////////////////////////////////////////////////////////////////
+/// Disable some compiler warnings
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __ICC__
+#pragma warning(disable:265)  // floating-point operation result is out of range
+#pragma warning(disable:383)  // value copied to temporary, reference to temporary used
+#pragma warning(disable:869)  // parameter was never referenced
+#pragma warning(disable:981)  // operands are evaluated in unspecified order
+#pragma warning(disable:1418) // external function definition with no prior declaration
+#pragma warning(disable:1419) // external declaration in primary source file
+#pragma warning(disable:1572) // floating-point equality and inequality comparisons are unreliable
+#pragma warning(disable:1125) // virtual function override intended?
+#endif /* __ICC__ */
+
+////////////////////////////////////////////////////////////////////////////////
+/// Default Includes and Functions
+////////////////////////////////////////////////////////////////////////////////
+
+#include "sys/constants.hpp"
+#include "sys/alloc.hpp"
+
+namespace pf
+{
+  /*! selects */
+  INLINE bool  select(bool s, bool  t , bool f) { return s ? t : f; }
+  INLINE int   select(bool s, int   t,   int f) { return s ? t : f; }
+  INLINE float select(bool s, float t, float f) { return s ? t : f; }
+
+  /*! Fatal error function */
+  void FATAL(const std::string&);
+
+  /*! Return the next power of 2 */
+  INLINE uint32 nextHighestPowerOf2(uint32 x) {
+    x--;
+    x |= x >> 1;
+    x |= x >> 2;
+    x |= x >> 4;
+    x |= x >> 8;
+    x |= x >> 16;
+    return ++x;
+  }
+
+  INLINE uint32 logi2(uint32 x) {
+    uint32 r = 0;
+    while(x >>= 1) r++;
+    return r;
+  }
+
+  template<uint32 N>
+  INLINE uint32 isPowerOf(uint32 i) {
+    while (i > 1) {
+      if (i%N) return false;
+      i = i/N;
+    }
+    return true;
+  }
+  template<> INLINE uint32 isPowerOf<2>(uint32 i) { return ((i-1)&i) == 0; }
+
+  /*! random functions */
+  template<typename T> T   random() { return T(0); }
+  template<> INLINE int    random() { return int(rand()); }
+  template<> INLINE uint32 random() { return uint32(rand()); }
+  template<> INLINE float  random() { return random<uint32>()/float(RAND_MAX); }
+  template<> INLINE double random() { return random<uint32>()/double(RAND_MAX); }
+
+  /** returns performance counter in seconds */
+  double getSeconds();
+
+} /* namespace pf */
+
+#endif /* __PF_PLATFORM_HPP__ */
+
diff --git a/backend/src/sys/ref.hpp b/backend/src/sys/ref.hpp
new file mode 100644 (file)
index 0000000..1672f54
--- /dev/null
@@ -0,0 +1,99 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_REF_HPP__
+#define __PF_REF_HPP__
+
+#include "sys/atomic.hpp"
+#include "sys/alloc.hpp"
+
+namespace pf
+{
+  class RefCount
+  {
+  public:
+    RefCount() : refCounter(0) {}
+    virtual ~RefCount() {}
+    INLINE void refInc() { refCounter++; }
+    INLINE bool refDec() { return !(--refCounter); }
+    Atomic32 refCounter;
+  };
+
+  ////////////////////////////////////////////////////////////////////////////////
+  /// Reference to single object
+  ////////////////////////////////////////////////////////////////////////////////
+
+  template<typename Type>
+  class Ref {
+  public:
+    Type* const ptr;
+
+    ////////////////////////////////////////////////////////////////////////////////
+    /// Constructors, Assignment & Cast Operators
+    ////////////////////////////////////////////////////////////////////////////////
+
+    INLINE Ref(void) : ptr(NULL) {}
+    INLINE Ref(NullTy) : ptr(NULL) {}
+    INLINE Ref(const Ref& input) : ptr(input.ptr) { if ( ptr ) ptr->refInc(); }
+    INLINE Ref(Type* const input) : ptr(input) { if (ptr) ptr->refInc(); }
+    INLINE ~Ref(void) { if (ptr && ptr->refDec()) PF_DELETE(ptr); }
+
+    INLINE Ref& operator= (const Ref &input) {
+      if (input.ptr) input.ptr->refInc();
+      if (ptr && ptr->refDec()) PF_DELETE(ptr);
+      *(Type**)&ptr = input.ptr;
+      return *this;
+    }
+
+    INLINE Ref& operator= (NullTy) {
+      if (ptr && ptr->refDec()) DELETE(ptr);
+      *(Type**)&ptr = NULL;
+      return *this;
+    }
+
+    INLINE operator bool(void) const { return ptr != NULL; }
+    INLINE operator Type*(void) const { return ptr; }
+
+    ////////////////////////////////////////////////////////////////////////////////
+    /// Properties
+    ////////////////////////////////////////////////////////////////////////////////
+
+    INLINE const Type& operator*  (void) const { return *ptr; }
+    INLINE const Type* operator-> (void) const { return  ptr; }
+    INLINE Type& operator*  (void) { return *ptr; }
+    INLINE Type* operator-> (void) { return  ptr; }
+
+    template<typename TypeOut>
+    INLINE       Ref<TypeOut> cast()       { return Ref<TypeOut>(static_cast<TypeOut*>(ptr)); }
+    template<typename TypeOut>
+    INLINE const Ref<TypeOut> cast() const { return Ref<TypeOut>(static_cast<TypeOut*>(ptr)); }
+    PF_CLASS(Ref);
+  };
+
+  template<typename Type> INLINE bool operator< ( const Ref<Type>& a, const Ref<Type>& b ) { return a.ptr <  b.ptr ; }
+  template<typename Type> INLINE bool operator== ( const Ref<Type>& a, NullTy             ) { return a.ptr == NULL  ; }
+  template<typename Type> INLINE bool operator== ( NullTy            , const Ref<Type>& b ) { return NULL  == b.ptr ; }
+  template<typename Type> INLINE bool operator== ( const Ref<Type>& a, const Ref<Type>& b ) { return a.ptr == b.ptr ; }
+  template<typename Type> INLINE bool operator!= ( const Ref<Type>& a, NullTy             ) { return a.ptr != NULL  ; }
+  template<typename Type> INLINE bool operator!= ( NullTy            , const Ref<Type>& b ) { return NULL  != b.ptr ; }
+  template<typename Type> INLINE bool operator!= ( const Ref<Type>& a, const Ref<Type>& b ) { return a.ptr != b.ptr ; }
+}
+
+#endif /* __PF_REF_HPP__ */
+
diff --git a/backend/src/sys/set.hpp b/backend/src/sys/set.hpp
new file mode 100644 (file)
index 0000000..efaf7ed
--- /dev/null
@@ -0,0 +1,59 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_SET_HPP__
+#define __PF_SET_HPP__
+
+#include "sys/platform.hpp"
+#include <set>
+
+namespace pf
+{
+  /*! Add our custom allocator to std::set */
+  template<class Key, class Pred = std::less<Key>>
+  class set : public std::set<Key,Pred,Allocator<Key>>
+  {
+  public:
+    // Typedefs
+    typedef Key value_type;
+    typedef Allocator<value_type> allocator_type;
+    typedef std::set<Key,Pred,Allocator<Key>> parent_type;
+    typedef Key key_type;
+    typedef Pred key_compare;
+
+    /*! Default constructor */
+    INLINE set(const key_compare &comp = key_compare(),
+               const allocator_type &a = allocator_type()) :
+      parent_type(comp, a) {}
+    /*! Iteration constructor */
+    template<class InputIterator>
+    INLINE set(InputIterator first,
+               InputIterator last,
+               const key_compare &comp = key_compare(),
+               const allocator_type& a = allocator_type()) :
+      parent_type(first, last, comp, a) {}
+    /*! Copy constructor */
+    INLINE set(const set& x) : parent_type(x) {}
+    PF_CLASS(set);
+  };
+
+} /* namespace pf */
+
+#endif /* __PF_SET_HPP__ */
+
diff --git a/backend/src/sys/string.cpp b/backend/src/sys/string.cpp
new file mode 100644 (file)
index 0000000..093bb26
--- /dev/null
@@ -0,0 +1,130 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/string.hpp"
+#include "sys/filename.hpp"
+
+#include <cstdio>
+#include <cctype>
+#include <istream>
+#include <fstream>
+#include <algorithm>
+
+namespace std
+{
+  char to_lower(char c) { return char(tolower(int(c))); }
+  char to_upper(char c) { return char(toupper(int(c))); }
+  string strlwr(const string& s) {
+    string dst(s);
+    std::transform(dst.begin(), dst.end(), dst.begin(), to_lower);
+    return dst;
+  }
+  string strupr(const string& s) {
+    string dst(s);
+    std::transform(dst.begin(), dst.end(), dst.begin(), to_upper);
+    return dst;
+  }
+
+}
+namespace pf
+{
+  /* $Id: strtok_r.c,v 1.1 2003/12/03 15:22:23 chris_reid Exp $ */
+  /*
+   * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Hgskolan
+   * (Royal Institute of Technology, Stockholm, Sweden).
+   * 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 the Institute 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 THE INSTITUTE AND 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 THE INSTITUTE OR 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.
+   */
+  char* tokenize(char *s1, const char *s2, char **lasts)
+  {
+   char *ret;
+
+   if (s1 == NULL)
+     s1 = *lasts;
+   while(*s1 && strchr(s2, *s1))
+     ++s1;
+   if(*s1 == '\0')
+     return NULL;
+   ret = s1;
+   while(*s1 && !strchr(s2, *s1))
+     ++s1;
+   if(*s1)
+     *s1++ = '\0';
+   *lasts = s1;
+   return ret;
+  }
+
+  bool strequal(const char *s1, const char *s2) {
+    if (strcmp(s1, s2) == 0) return true;
+    return false;
+  }
+
+  bool contains(const char *haystack, const char *needle) {
+    if (strstr(haystack, needle) == NULL) return false;
+    return true;
+  }
+
+  std::string loadFile(const FileName &path)
+  {
+    std::ifstream stream(path.c_str(), std::istream::in);
+    if (stream.is_open() == false)
+      return std::string();
+    std::string str = loadFile(stream);
+    stream.close();
+    return str;
+  }
+
+  std::string loadFile(std::ifstream &stream)
+  {
+    PF_ASSERT(stream.is_open());
+    std::string line;
+    std::stringstream text;
+    while (std::getline(stream, line))
+      text << "\n" << line;
+    stream.close();
+    return text.str();
+  }
+}
+
diff --git a/backend/src/sys/string.hpp b/backend/src/sys/string.hpp
new file mode 100644 (file)
index 0000000..0447966
--- /dev/null
@@ -0,0 +1,53 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_STRING_H__
+#define __PF_STRING_H__
+
+#include "sys/platform.hpp"
+#include "sys/filename.hpp"
+
+#include <cstring>
+#include <string>
+#include <sstream>
+#include <fstream>
+
+namespace std
+{
+  string strlwr(const string& s);
+  string strupr(const string& s);
+
+  template<typename T> INLINE string stringOf(const T& v) {
+    stringstream s; s << v; return s.str();
+  }
+}
+namespace pf
+{
+  /*! Compare two strings */
+  bool strequal(const char *s1, const char *s2);
+  /*! Say if needle is in haystack */
+  bool contains(const char *haystack, const char *needle);
+  /*! Tokenize a string (like strtok_r does) */
+  char* tokenize(char *s1, const char *s2, char **lasts);
+  /*! Load a file from its path and copies it into a string */
+  std::string loadFile(const FileName &path);
+  /*! Load a file from a stream and copies it into a string */
+  std::string loadFile(std::ifstream &stream);
+}
+#endif
diff --git a/backend/src/sys/sysinfo.cpp b/backend/src/sys/sysinfo.cpp
new file mode 100644 (file)
index 0000000..15a5609
--- /dev/null
@@ -0,0 +1,148 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/sysinfo.hpp"
+
+////////////////////////////////////////////////////////////////////////////////
+/// All Platforms
+////////////////////////////////////////////////////////////////////////////////
+
+namespace pf
+{
+  /* return platform name */
+  std::string getPlatformName() {
+#if defined(__LINUX__) && !defined(__X86_64__)
+    return "Linux (32bit)";
+#elif defined(__LINUX__) && defined(__X86_64__)
+    return "Linux (64bit)";
+#elif defined(__FREEBSD__) && !defined(__X86_64__)
+    return "FreeBSD (32bit)";
+#elif defined(__FREEBSD__) && defined(__X86_64__)
+    return "FreeBSD (64bit)";
+#elif defined(__CYGWIN__) && !defined(__X86_64__)
+    return "Cygwin (32bit)";
+#elif defined(__CYGWIN__) && defined(__X86_64__)
+    return "Cygwin (64bit)";
+#elif defined(__WIN32__) && !defined(__X86_64__)
+    return "Windows (32bit)";
+#elif defined(__WIN32__) && defined(__X86_64__)
+    return "Windows (64bit)";
+#elif defined(__MACOSX__) && !defined(__X86_64__)
+    return "MacOS (32bit)";
+#elif defined(__MACOSX__) && defined(__X86_64__)
+    return "MacOS (64bit)";
+#elif defined(__UNIX__) && !defined(__X86_64__)
+    return "Unix (32bit)";
+#elif defined(__UNIX__) && defined(__X86_64__)
+    return "Unix (64bit)";
+#else
+    return "Unknown";
+#endif
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Windows Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __WIN32__
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace pf
+{
+  /* get the full path to the running executable */
+  std::string getExecutableFileName() {
+    char filename[1024];
+    if (!GetModuleFileName(NULL, filename, sizeof(filename))) return std::string();
+    return std::string(filename);
+  }
+
+  /* return the number of logical threads of the system */
+  int getNumberOfLogicalThreads() {
+    SYSTEM_INFO sysinfo;
+    GetSystemInfo(&sysinfo);
+    return sysinfo.dwNumberOfProcessors;
+  }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Linux Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __LINUX__
+
+#include <stdio.h>
+#include <unistd.h>
+
+namespace pf
+{
+  /* get the full path to the running executable */
+  std::string getExecutableFileName() {
+    char pid[32]; sprintf(pid, "/proc/%d/exe", getpid());
+    char buf[1024];
+    int bytes = readlink(pid, buf, sizeof(buf)-1);
+    if (bytes != -1) buf[bytes] = '\0';
+    return std::string(buf);
+  }
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// MacOS Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __MACOSX__
+
+#include <mach-o/dyld.h>
+
+namespace pf
+{
+  /* get the full path to the running executable */
+  std::string getExecutableFileName()
+  {
+    char buf[1024];
+    uint32_t size = sizeof(buf);
+    if (_NSGetExecutablePath(buf, &size) != 0) return std::string();
+    return std::string(buf);
+  }
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Unix Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#if defined(__UNIX__)
+
+#include <unistd.h>
+
+namespace pf
+{
+  /* return the number of logical threads of the system */
+  int getNumberOfLogicalThreads() {
+    return sysconf(_SC_NPROCESSORS_CONF);
+  }
+}
+#endif
+
diff --git a/backend/src/sys/sysinfo.hpp b/backend/src/sys/sysinfo.hpp
new file mode 100644 (file)
index 0000000..5679ddb
--- /dev/null
@@ -0,0 +1,37 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_SYSINFO_H__
+#define __PF_SYSINFO_H__
+
+#include "sys/platform.hpp"
+
+#include <string>
+
+namespace pf
+{
+  /*! get the full path to the running executable */
+  std::string getExecutableFileName();
+  /*! return platform name */
+  std::string getPlatformName();
+  /*! return the number of logical threads of the system */
+  int getNumberOfLogicalThreads();
+}
+
+#endif
diff --git a/backend/src/sys/thread.cpp b/backend/src/sys/thread.cpp
new file mode 100644 (file)
index 0000000..12503ce
--- /dev/null
@@ -0,0 +1,213 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include <iostream>
+
+#include "sys/thread.hpp"
+#include "sys/sysinfo.hpp"
+
+////////////////////////////////////////////////////////////////////////////////
+/// Windows Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __WIN32__
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+namespace pf
+{
+  /*! creates a hardware thread running on specific core */
+  thread_t createThread(thread_func f, void* arg, size_t stack_size, int affinity)
+  {
+    HANDLE handle = CreateThread(NULL,stack_size,(LPTHREAD_START_ROUTINE)f,arg,0,NULL);
+    if (handle == NULL)
+      FATAL("createThread error");
+    if (affinity < 0) return thread_t(handle);
+
+    // set thread affinity
+    int thread = affinity % 64;
+    SetThreadAffinityMask(handle, DWORD_PTR(1L << thread));
+
+    return thread_t(handle);
+  }
+
+  void setAffinity(int affinity) {
+    if (affinity >= 0) SetThreadAffinityMask(GetCurrentThread(), DWORD_PTR(1L << affinity));
+  }
+
+  void yield(int time) { Sleep(time); }
+
+  void join(thread_t tid) {
+    WaitForSingleObject(HANDLE(tid), INFINITE);
+    CloseHandle(HANDLE(tid));
+  }
+
+  void destroyThread(thread_t tid) {
+    TerminateThread(HANDLE(tid),0);
+    CloseHandle(HANDLE(tid));
+  }
+
+  tls_t createTls() { return tls_t(TlsAlloc()); }
+
+  void setTls(tls_t tls, void* const ptr) {
+    TlsSetValue(DWORD(size_t(tls)), ptr);
+  }
+
+  void* getTls(tls_t tls) {
+    return TlsGetValue(DWORD(size_t(tls)));
+  }
+
+  void destroyTls(tls_t tls) {
+    TlsFree(DWORD(size_t(tls)));
+  }
+}
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Linux Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __LINUX__
+namespace pf
+{
+  /*! set affinity of the calling thread */
+  void setAffinity(int affinity)
+  {
+    int wrap = getNumberOfLogicalThreads()/2;
+    affinity = (affinity/2) + wrap*(affinity%2);
+    if (affinity >= 0 && affinity < 64*64) {
+      union { uint64 u; cpu_set_t set; } mask[64];
+      for (size_t i=0; i<64; i++) mask[i].u = 0;
+      mask[affinity/64].u= uint64(1) << (affinity % 64);
+      if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask[0].set) < 0)
+        std::cerr << "Thread: cannot set affinity" << std::endl;
+    }
+  }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// MacOSX Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __MACOSX__
+
+#include <mach/thread_act.h>
+#include <mach/thread_policy.h>
+#include <mach/mach_init.h>
+
+namespace pf
+{
+  /*! set affinity of the calling thread */
+  void setAffinity(int affinity)
+  {
+    if (affinity >= 0) {
+      thread_affinity_policy ap;
+      ap.affinity_tag = affinity;
+      if (thread_policy_set(mach_thread_self(),THREAD_AFFINITY_POLICY,(integer_t*)&ap,THREAD_AFFINITY_POLICY_COUNT) != KERN_SUCCESS)
+        std::cerr << "Thread: cannot set affinity" << std::endl;
+    }
+  }
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/// Unix Platform
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __UNIX__
+
+#include <pthread.h>
+#include <sched.h>
+
+namespace pf
+{
+  struct ThreadStartupData {
+    int affinity;
+    thread_func f;
+    void* arg;
+  };
+
+  static void* threadStartup(ThreadStartupData* parg)
+  {
+    ThreadStartupData arg = *parg; PF_DELETE(parg); parg = NULL;
+    setAffinity(arg.affinity);
+    arg.f(arg.arg);
+    return NULL;
+  }
+
+  thread_t createThread(thread_func f, void* arg, size_t stack_size, int affinity)
+  {
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    if (stack_size > 0) pthread_attr_setstacksize (&attr, stack_size);
+
+    pthread_t* tid = PF_NEW(pthread_t);
+    ThreadStartupData* startup = PF_NEW(ThreadStartupData);
+    startup->f = f;
+    startup->arg = arg;
+    startup->affinity = affinity;
+
+    if (pthread_create(tid,&attr,(void*(*)(void*))threadStartup,startup) != 0)
+      FATAL("Thread creation error");
+
+    return thread_t(tid);
+  }
+
+  void yield(int time) {
+    if (time == 0) sched_yield();
+    else usleep(time * 1000);
+  }
+
+  void join(thread_t tid) {
+    if (pthread_join(*(pthread_t*)tid, NULL) != 0)
+      FATAL("pthread_join error");
+    PF_DELETE((pthread_t*)tid);
+  }
+
+  void destroyThread(thread_t tid) {
+    pthread_cancel(*(pthread_t*)tid);
+    PF_DELETE((pthread_t*)tid);
+  }
+
+  tls_t createTls() {
+    pthread_key_t* key = PF_NEW(pthread_key_t);
+    if (pthread_key_create(key,NULL) != 0)
+      FATAL("pthread_key_create error");
+    return tls_t(key);
+  }
+
+  void* getTls(tls_t tls) {
+    return pthread_getspecific(*(pthread_key_t*)tls);
+  }
+
+  void setTls(tls_t tls, void* const ptr) {
+    if (pthread_setspecific(*(pthread_key_t*)tls, ptr) != 0)
+      FATAL("pthread_setspecific error");
+  }
+
+  void destroyTls(tls_t tls) {
+    if (pthread_key_delete(*(pthread_key_t*)tls) != 0)
+      FATAL("pthread_key_delete error");
+    PF_DELETE((pthread_key_t*)tls);
+  }
+}
+#endif
diff --git a/backend/src/sys/thread.hpp b/backend/src/sys/thread.hpp
new file mode 100644 (file)
index 0000000..0611ef7
--- /dev/null
@@ -0,0 +1,54 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_THREAD_HPP__
+#define __PF_THREAD_HPP__
+
+#include "sys/platform.hpp"
+
+namespace pf
+{
+  /*! Type for thread */
+  typedef struct opaque_thread_t* thread_t;
+  /*! Signature of thread start function */
+  typedef void (*thread_func)(void*);
+  /*! Creates a hardware thread running on specific logical thread */
+  thread_t createThread(thread_func f, void* arg, size_t stack_size = 0, int affinity = -1);
+  /*! Set affinity of the calling thread */
+  void setAffinity(int affinity);
+  /*! The thread calling this function gets yielded for a number of seconds */
+  void yield(int time = 0);
+  /*! Waits until the given thread has terminated */
+  void join(thread_t tid);
+  /*! Destroy handle of a thread */
+  void destroyThread(thread_t tid);
+  /*! Type for handle to thread local storage */
+  typedef struct opaque_tls_t* tls_t;
+  /*! Creates thread local storage */
+  tls_t createTls();
+  /*! Set the thread local storage pointer */
+  void setTls(tls_t tls, void* const ptr);
+  /*! Return the thread local storage pointer */
+  void* getTls(tls_t tls);
+  /*! Destroys thread local storage identifier */
+  void destroyTls(tls_t tls);
+}
+
+#endif /* __PF_THREAD_HPP__ */
+
diff --git a/backend/src/sys/vector.hpp b/backend/src/sys/vector.hpp
new file mode 100644 (file)
index 0000000..a100770
--- /dev/null
@@ -0,0 +1,72 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_VECTOR_HPP__
+#define __PF_VECTOR_HPP__
+
+#include "sys/platform.hpp"
+#include <vector>
+
+namespace pf
+{
+  /*! Add bound checks to the standard vector class and use the internal
+   *  allocator
+   */
+  template<class T>
+  class vector : public std::vector<T, Allocator<T>>
+  {
+  public:
+    // Typedefs
+    typedef std::vector<T, Allocator<T>>       parent_type;
+    typedef Allocator<T>                       allocator_type;
+    typedef typename allocator_type::size_type size_type;
+    typedef typename parent_type::iterator     iterator;
+
+    /*! Default constructor */
+    INLINE explicit vector(const allocator_type &a = allocator_type()) :
+      parent_type(a) {}
+    /*! Copy constructor */
+    INLINE vector(const vector &x) : parent_type(x) {}
+    /*! Repetitive sequence constructor */
+    INLINE explicit vector(size_type n,
+                           const T& value= T(),
+                           const allocator_type &a = allocator_type()) :
+      parent_type(n, value, a) {}
+    /*! Iteration constructor */
+    template <class InputIterator>
+    INLINE vector(InputIterator first,
+                  InputIterator last,
+                  const allocator_type &a = allocator_type()) :
+      parent_type(first, last, a) {}
+    /*! Get element at position index (with a bound check) */
+    T &operator[] (size_t index) {
+      PF_ASSERT(index < this->size());
+      return parent_type::operator[] (index);
+    }
+    /*! Get element at position index (with a bound check) */
+    const T &operator[] (size_t index) const {
+      PF_ASSERT(index < this->size());
+      return parent_type::operator[] (index);
+    }
+    PF_CLASS(vector);
+  };
+} /* namespace pf */
+
+#endif /* __PF_VECTOR_HPP__ */
+
diff --git a/backend/src/utest/utest.cpp b/backend/src/utest/utest.cpp
new file mode 100644 (file)
index 0000000..8fca968
--- /dev/null
@@ -0,0 +1,57 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "utest.hpp"
+#include "sys/string.hpp"
+
+namespace pf
+{
+  std::vector<UTest> *UTest::utestList = NULL;
+  void releaseUTestList(void) { if (UTest::utestList) delete UTest::utestList; }
+
+  UTest::UTest(Function fn, const char *name) : fn(fn), name(name) {
+    if (utestList == NULL) {
+      utestList = new std::vector<UTest>;
+      atexit(releaseUTestList);
+    }
+    utestList->push_back(*this);
+  }
+
+  UTest::UTest(void) : fn(NULL), name(NULL) {}
+
+  void UTest::run(const char *name) {
+    if (name == NULL) return;
+    if (utestList == NULL) return;
+    for (size_t i = 0; i < utestList->size(); ++i) {
+      const UTest &utest = (*utestList)[i];
+      if (utest.name == NULL || utest.fn == NULL) continue;
+      if (strequal(utest.name, name)) (utest.fn)();
+    }
+  }
+
+  void UTest::runAll(void) {
+    if (utestList == NULL) return;
+    for (size_t i = 0; i < utestList->size(); ++i) {
+      const UTest &utest = (*utestList)[i];
+      if (utest.fn == NULL) continue;
+      (utest.fn)();
+    }
+  }
+} /* namespace pf */
+
diff --git a/backend/src/utest/utest.hpp b/backend/src/utest/utest.hpp
new file mode 100644 (file)
index 0000000..fea1bbc
--- /dev/null
@@ -0,0 +1,53 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#ifndef __PF_UTEST_HPP__
+#define __PF_UTEST_HPP__
+
+#include <vector>
+
+namespace pf
+{
+  /*! Quick and dirty Unit test system with registration */
+  struct UTest
+  {
+    /*! A unit test function to run */
+    typedef void (*Function) (void);
+    /*! Empty test */
+    UTest(void);
+    /*! Build a new unit test and append it to the unit test list */
+    UTest(Function fn, const char *name);
+    /*! Function to execute */
+    Function fn;
+    /*! Name of the test */
+    const char *name;
+    /*! The tests that are registered */
+    static std::vector<UTest> *utestList;
+    /*! Run the test with the given name */
+    static void run(const char *name);
+    /*! Run all the tests */
+    static void runAll(void);
+  };
+} /* namespace pf */
+
+/*! Register a new unit test */
+#define UTEST_REGISTER(FN) static const pf::UTest __##NAME##__(FN, #FN);
+
+#endif /* __PF_UTEST_HPP__ */
+
diff --git a/backend/src/utest/utest_console.cpp b/backend/src/utest/utest_console.cpp
new file mode 100644 (file)
index 0000000..5107594
--- /dev/null
@@ -0,0 +1,95 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "utest/utest.hpp"
+#include "sys/command.hpp"
+#include "sys/console.hpp"
+#include "sys/logging.hpp"
+#include "sys/windowing.hpp"
+#include "sys/script.hpp"
+#include <string>
+
+namespace pf
+{
+  /*! Output everything in the terminal */
+  class UTestConsoleDisplay : public ConsoleDisplay
+  {
+  public:
+    UTestConsoleDisplay (void) {
+      last = lastBlink = getSeconds();
+      cursor = 0;
+    }
+    virtual void line(Console &console, const std::string &line) {
+      const double curr = getSeconds();
+      std::string patched = line;
+      if (curr - lastBlink > .5) {
+        cursor ^= 1;
+        lastBlink = curr;
+      }
+      const uint32 pos = console.cursorPosition();
+      if (cursor) {
+        if (pos >= patched.size())
+          patched.push_back('_');
+        else
+          patched[pos] = '_';
+      }
+      if (curr - last > 0.02) {
+        std::cout << '\r' << "> " << patched;
+        for (int i = 0; i < 80; ++i) std::cout << ' ';
+        std::cout << '\r';
+        fflush(stdout);
+        last = curr;
+      }
+    }
+    virtual void out(Console &console, const std::string &str) {
+      std::cout << str << std::endl;
+    }
+    double last;
+    double lastBlink;
+    uint32 cursor;
+  };
+} /* namespace pf */
+
+void utest_console(void)
+{
+  using namespace pf;
+  WinOpen(640, 480);
+  ScriptSystem *scriptSystem = LuaScriptSystemCreate();
+  CommandSystemStart(*scriptSystem);
+  UTestConsoleDisplay *display = PF_NEW(UTestConsoleDisplay);
+  Console *console = ConsoleNew(*scriptSystem, *display);
+  console->addCompletion("while");
+  console->addCompletion("whilewhile");
+  for (;;) {
+    Ref<InputControl> input = PF_NEW(InputControl);
+    input->processEvents();
+    if (input->getKey(PF_KEY_ASCII_ESC))
+      break;
+    console->update(*input);
+    WinSwapBuffers();
+  }
+  CommandSystemEnd();
+  PF_DELETE(console);
+  PF_DELETE(scriptSystem);
+  PF_DELETE(display);
+  WinClose();
+}
+
+UTEST_REGISTER(utest_console);
+
diff --git a/backend/src/utest/utest_font.cpp b/backend/src/utest/utest_font.cpp
new file mode 100644 (file)
index 0000000..d6b0fa9
--- /dev/null
@@ -0,0 +1,41 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "renderer/font.hpp"
+#include "sys/default_path.hpp"
+#include "utest/utest.hpp"
+
+#include <string>
+
+using namespace pf;
+static const std::string fontName = "font.fnt";
+
+void utest_font(void)
+{
+  Font font;
+  size_t i = 0;
+  for (; i < defaultPathNum; ++i) {
+    const FileName path(std::string(defaultPath[i]) + fontName);
+    if (font.load(path)) break;
+  }
+  PF_ASSERT(i < defaultPathNum);
+}
+
+UTEST_REGISTER(utest_font);
+
diff --git a/backend/src/utest/utest_lua.cpp b/backend/src/utest/utest_lua.cpp
new file mode 100644 (file)
index 0000000..289ef7f
--- /dev/null
@@ -0,0 +1,58 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/script.hpp"
+#include "sys/command.hpp"
+#include "sys/logging.hpp"
+#include "sys/tasking.hpp"
+#include "utest/utest.hpp"
+
+using namespace pf;
+
+VARI(coucou, 0, 2, 3, "coucou");
+VARS(player0, "ben", "player name");
+
+#define _RUN_SCRIPT(STR, RUN_MODE) do {\
+  ScriptStatus status;\
+  scriptSystem->RUN_MODE(STR, status);\
+  if (!status.success) PF_ERROR(status.msg);\
+} while (0)
+#define RUN(STR) _RUN_SCRIPT(STR,run)
+#define RUN_NON_PROTECTED(STR) _RUN_SCRIPT(STR,runNonProtected)
+
+void utest_lua(void)
+{
+  ScriptSystem *scriptSystem = LuaScriptSystemCreate();
+  ScriptStatus status;
+  scriptSystem->run("local x = 0", status);
+  CommandSystemStart(*scriptSystem);
+
+  // Run some code. This may modify console variables
+  RUN("cv.coucou = 1");
+  RUN_NON_PROTECTED("print(pf.cv.coucou)");
+  RUN("cv.player0 = \"hop\"");
+  RUN_NON_PROTECTED("print(pf.cv.player0)");
+  if (coucou() == 1) PF_MSG("coucou is equal to 1");
+
+  CommandSystemEnd();
+  PF_DELETE(scriptSystem);
+}
+
+UTEST_REGISTER(utest_lua)
+
diff --git a/backend/src/utest/utest_rt.cpp b/backend/src/utest/utest_rt.cpp
new file mode 100644 (file)
index 0000000..cf2db0a
--- /dev/null
@@ -0,0 +1,193 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "renderer/renderer_obj.hpp"
+#include "renderer/renderer.hpp"
+#include "rt/bvh2_traverser.hpp"
+#include "rt/bvh2.hpp"
+#include "rt/rt_triangle.hpp"
+#include "rt/rt_camera.hpp"
+#include "models/obj.hpp"
+#include "game/camera.hpp"
+#include "image/stb_image.hpp"
+
+#include "sys/alloc.hpp"
+#include "sys/tasking.hpp"
+#include "sys/tasking_utility.hpp"
+#include "sys/logging.hpp"
+#include "sys/default_path.hpp"
+
+#include "utest/utest.hpp"
+
+#include <cstring>
+#include <GL/freeglut.h>
+#include <cstdio>
+#include <iostream>
+
+namespace pf
+{
+  static Ref<Intersector> intersector  = NULL;
+  static const int CAMW = 1024, CAMH = 1024;
+
+  static const FileName objName("f000.obj");
+  //static const FileName objName("arabic_city_II.obj");
+  //static const FileName objName("conference.obj");
+  //static const FileName objName("sibenik.obj");
+  //static const FileName objName("sponza.obj");
+
+  static RTTriangle *ObjComputeTriangle(const Obj &obj) {
+    RTTriangle *tris = PF_NEW_ARRAY(RTTriangle, obj.triNum);
+    for (size_t i = 0; i < obj.triNum; ++i) {
+      const vec3f &v0 = obj.vert[obj.tri[i].v[0]].p; 
+      const vec3f &v1 = obj.vert[obj.tri[i].v[1]].p; 
+      const vec3f &v2 = obj.vert[obj.tri[i].v[2]].p; 
+      tris[i] = RTTriangle(v0,v1,v2);
+    }
+    return tris;
+  }
+
+  /*! Task set that computes a frame buffer with ray tracing */
+  template <bool singleRay>
+  class TaskRayTrace : public TaskSet
+  {
+  public:
+    INLINE TaskRayTrace(const Intersector &intersector,
+                        const RTCamera &cam,
+                        const uint32 *c,
+                        uint32 *rgba,
+                        uint32 w, uint32 jobNum) :
+      TaskSet(jobNum, "TaskRayTrace"),
+      intersector(intersector), cam(cam), c(c), rgba(rgba),
+      w(w), h(jobNum * RayPacket::height) {}
+
+    virtual void run(size_t jobID)
+    {
+      if (singleRay) {
+        RTCameraRayGen gen;
+        cam.createGenerator(gen, w, h);
+        for (uint32 row = 0; row < RayPacket::height; ++row) {
+          const uint32 y = row + jobID * RayPacket::height;
+          for (uint32 x = 0; x < w; ++x) {
+            Ray ray;
+            Hit hit;
+            gen.generate(ray, x, y);
+            intersector.traverse(ray, hit);
+            rgba[x + y*w] = hit ? c[hit.id0] : 0u;
+          }
+        }
+      } else {
+        RTCameraPacketGen gen;
+        cam.createGenerator(gen, w, h);
+        const uint32 y = jobID * RayPacket::height;
+        for (uint32 x = 0; x < w; x += RayPacket::width) {
+          RayPacket pckt;
+          PacketHit hit;
+          gen.generate(pckt, x, y);
+          intersector.traverse(pckt, hit);
+          const int32 *IDs = (const int32 *) &hit.id0[0][0];
+          uint32 curr = 0;
+          for (uint32 j = 0; j < pckt.height; ++j) {
+            for (uint32 i = 0; i < pckt.width; ++i, ++curr) {
+              const uint32 offset = x + i + (y + j) * w;
+              rgba[offset] = IDs[curr] != -1 ? c[IDs[curr]] : 0u;
+            }
+          }
+        }
+      }
+    }
+
+    const Intersector &intersector; //!< To traverse the scene
+    const RTCamera &cam;            //!< Parameterize the view
+    const uint32 *c;                //!< One color per triangle
+    uint32 *rgba;                   //!< Frame buffer
+    uint32 w, h;                    //!< Frame buffer dimensions
+  };
+
+  /*! Ray trace the loaded scene */
+  template <bool singleRay>
+  static void rayTrace(int w, int h, const uint32 *c) {
+    FPSCamera fpsCam;
+    const RTCamera cam(fpsCam.org, fpsCam.up, fpsCam.view, fpsCam.fov, fpsCam.ratio);
+    uint32 *rgba = PF_NEW_ARRAY(uint32, w * h);
+    std::memset(rgba, 0, sizeof(uint32) * w * h);
+    PF_COMPILER_READ_WRITE_BARRIER;
+    const double t = getSeconds();
+    Task *rayTask = PF_NEW(TaskRayTrace<singleRay>, *intersector,
+                           cam, c, rgba, w, h/RayPacket::height);
+    Task *returnToMain = PF_NEW(TaskInterruptMain);
+    rayTask->starts(returnToMain);
+    rayTask->scheduled();
+    returnToMain->scheduled();
+    TaskingSystemEnter();
+    const double dt = getSeconds() - t;
+    PF_MSG_V(dt * 1000. << " msec - " << CAMW * CAMH / dt << " rays/s");
+    if (singleRay)
+      stbi_write_bmp("single.bmp", w, h, 4, rgba);
+    else
+      stbi_write_bmp("packet.bmp", w, h, 4, rgba);
+    PF_DELETE_ARRAY(rgba);
+  }
+
+  static void RTStart(void)
+  {
+    Obj obj;
+    size_t path = 0;
+    for (path = 0; path < defaultPathNum; ++path)
+      if (obj.load(FileName(defaultPath[path]) + objName)) {
+        PF_MSG_V("Obj: " << objName << " loaded from " << defaultPath[path]);
+        break;
+      }
+    if (path == defaultPathNum)
+      PF_WARNING_V("Obj: " << objName << " not found");
+
+    // Build the BVH
+    RTTriangle *tris = ObjComputeTriangle(obj);
+    Ref<BVH2<RTTriangle>> bvh = PF_NEW(BVH2<RTTriangle>);
+    buildBVH2(tris, obj.triNum, *bvh);
+    PF_DELETE_ARRAY(tris);
+
+    // Now we have an intersector on the triangle soup
+    intersector = PF_NEW(BVH2Traverser<RTTriangle>, bvh);
+
+    // Compute some triangle color
+    uint32 *c = PF_NEW_ARRAY(uint32, bvh->primNum);
+    for (uint32 i = 0; i < bvh->primNum; ++i) {
+      c[i] = rand();
+      c[i] |= 0xff000000;
+    }
+
+    // Ray trace now
+    PF_MSG_V("Packet ray tracing");
+    for (int i = 0; i < 16; ++i) rayTrace<false>(CAMW, CAMH, c);
+    PF_MSG_V("Single ray tracing");
+    for (int i = 0; i < 16; ++i) rayTrace<true>(CAMW, CAMH, c);
+    PF_DELETE_ARRAY(c);
+  }
+
+  static void RTEnd(void) { intersector = NULL; }
+}
+
+void utest_rt(void)
+{
+  using namespace pf;
+  RTStart();
+  RTEnd();
+}
+
+UTEST_REGISTER(utest_rt);
diff --git a/backend/src/utest/utest_tasking.cpp b/backend/src/utest/utest_tasking.cpp
new file mode 100644 (file)
index 0000000..419c3d7
--- /dev/null
@@ -0,0 +1,653 @@
+/* 
+ * Copyright © 2012 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Benjamin Segovia <benjamin.segovia@intel.com>
+ */
+
+#include "sys/tasking.hpp"
+#include "sys/tasking_utility.hpp"
+#include "sys/ref.hpp"
+#include "sys/thread.hpp"
+#include "sys/mutex.hpp"
+#include "sys/sysinfo.hpp"
+#include "math/random.hpp"
+
+#include "utest/utest.hpp"
+
+#define START_UTEST(TEST_NAME)                          \
+void TEST_NAME(void)                                    \
+{                                                       \
+  std::cout << std::endl << "starting " <<              \
+              #TEST_NAME << std::endl;
+
+#define END_UTEST(TEST_NAME)                            \
+  std::cout << "ending " << #TEST_NAME << std::endl;    \
+}
+
+using namespace pf;
+
+///////////////////////////////////////////////////////////////////////////////
+// Very simple test which basically does nothing
+///////////////////////////////////////////////////////////////////////////////
+class TaskDone : public Task {
+public:
+  virtual Task* run(void) {
+    TaskingSystemInterruptMain();
+    return NULL;
+  }
+};
+
+START_UTEST(TestDummy)
+  Task *done = PF_NEW(TaskDone);
+  Task *nothing = PF_NEW(TaskDummy);
+  nothing->starts(done);
+  done->scheduled();
+  nothing->scheduled();
+  TaskingSystemEnter();
+END_UTEST(TestDummy)
+
+///////////////////////////////////////////////////////////////////////////////
+// Simplest taskset test. An array is filled by each worker
+///////////////////////////////////////////////////////////////////////////////
+class TaskSetSimple : public TaskSet {
+public:
+  INLINE TaskSetSimple(size_t elemNum, uint32 *array_) :
+    TaskSet(elemNum), array(array_) {}
+  virtual void run(size_t elemID) { array[elemID] = 1u; }
+  uint32 *array;
+};
+
+START_UTEST(TestTaskSet)
+  const size_t elemNum = 1 << 20;
+  uint32 *array = PF_NEW_ARRAY(uint32, elemNum);
+  for (size_t i = 0; i < elemNum; ++i) array[i] = 0;
+  double t = getSeconds();
+  Task *done = PF_NEW(TaskDone);
+  Task *taskSet = PF_NEW(TaskSetSimple, elemNum, array);
+  taskSet->starts(done);
+  done->scheduled();
+  taskSet->scheduled();
+  TaskingSystemEnter();
+  t = getSeconds() - t;
+  std::cout << t * 1000. << " ms" << std::endl;
+  for (size_t i = 0; i < elemNum; ++i)
+    FATAL_IF(array[i] == 0, "TestTaskSet failed");
+  PF_DELETE_ARRAY(array);
+END_UTEST(TestTaskSet)
+
+///////////////////////////////////////////////////////////////////////////////
+// We create a binary tree of tasks here. Each task spawn a two children upto a
+// given maximum level. Then, a atomic value is updated per leaf. In that test,
+// all tasks complete the ROOT directly
+///////////////////////////////////////////////////////////////////////////////
+enum { maxLevel = 20u };
+
+/*! One node task per node in the tree. Task completes the root */
+class TaskNode : public Task {
+public:
+  INLINE TaskNode(Atomic &value_, uint32 lvl_, Task *root_=NULL) :
+    value(value_), lvl(lvl_) {
+    this->root = root_ == NULL ? this : root_;
+  }
+  virtual Task* run(void);
+  Atomic &value;
+  Task *root;
+  uint32 lvl;
+};
+
+Task* TaskNode::run(void) {
+  if (this->lvl == maxLevel)
+    this->value++;
+  else {
+    Task *left  = PF_NEW(TaskNode, this->value, this->lvl+1, this->root);
+    Task *right = PF_NEW(TaskNode, this->value, this->lvl+1, this->root);
+    left->ends(this->root);
+    right->ends(this->root);
+    left->scheduled();
+    right->scheduled();
+  }
+  return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Same as TaskNode but we use a continuation passing style strategy to improve
+// the system throughtput
+///////////////////////////////////////////////////////////////////////////////
+
+/*! One node task per node in the tree. Task completes the root */
+class TaskNodeOpt : public Task {
+public:
+  INLINE TaskNodeOpt(Atomic &value_, uint32 lvl_, Task *root_=NULL) :
+    value(value_), lvl(lvl_) {
+    this->root = root_ == NULL ? this : root_;
+  }
+  virtual Task* run(void);
+  Atomic &value;
+  Task *root;
+  uint32 lvl;
+};
+
+Task* TaskNodeOpt::run(void) {
+  if (this->lvl == maxLevel) {
+    this->value++;
+    return NULL;
+  } else {
+    Task *left  = PF_NEW(TaskNode, this->value, this->lvl+1, this->root);
+    Task *right = PF_NEW(TaskNode, this->value, this->lvl+1, this->root);
+    left->ends(this->root);
+    right->ends(this->root);
+    left->scheduled();
+    return right;
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Same as TaskNode but here each task completes its parent task directly. This
+// stresses the completion system but strongly limits cache line contention
+///////////////////////////////////////////////////////////////////////////////
+
+/*! One node task per node in the tree. Task completes its parent */
+class TaskCascadeNode : public Task {
+public:
+  INLINE TaskCascadeNode(Atomic &value_, uint32 lvl_, Task *root_=NULL) :
+    value(value_), lvl(lvl_) {}
+  virtual Task* run(void);
+  Atomic &value;
+  uint32 lvl;
+};
+
+Task *TaskCascadeNode::run(void) {
+  if (this->lvl == maxLevel)
+    this->value++;
+  else {
+    Task *left  = PF_NEW(TaskCascadeNode, this->value, this->lvl+1);
+    Task *right = PF_NEW(TaskCascadeNode, this->value, this->lvl+1);
+    left->ends(this);
+    right->ends(this);
+    left->scheduled();
+    right->scheduled();
+  }
+  return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Same as TaskCascadeNode but with continuation passing style tasks
+///////////////////////////////////////////////////////////////////////////////
+class TaskCascadeNodeOpt : public Task {
+public:
+  INLINE TaskCascadeNodeOpt(Atomic &value_, uint32 lvl_, Task *root_=NULL) :
+    value(value_), lvl(lvl_) {}
+  virtual Task* run(void);
+  Atomic &value;
+  uint32 lvl;
+};
+
+Task *TaskCascadeNodeOpt::run(void) {
+  if (this->lvl == maxLevel) {
+    this->value++;
+    return NULL;
+  } else {
+    Task *left  = PF_NEW(TaskCascadeNode, this->value, this->lvl+1);
+    Task *right = PF_NEW(TaskCascadeNode, this->value, this->lvl+1);
+    left->ends(this);
+    right->ends(this);
+    left->scheduled();
+    return right;
+  }
+}
+
+/*! For all tree tests */
+template<typename NodeType>
+START_UTEST(TestTree)
+  Atomic value(0u);
+  std::cout << "nodeNum = " << (2 << maxLevel) - 1 << std::endl;
+  double t = getSeconds();
+  Task *done = PF_NEW(TaskDone);
+  Task *root = PF_NEW(NodeType, value, 0);
+  root->starts(done);
+  done->scheduled();
+  root->scheduled();
+  TaskingSystemEnter();
+  t = getSeconds() - t;
+  std::cout << t * 1000. << " ms" << std::endl;
+  FATAL_IF(value != (1 << maxLevel), "TestTree failed");
+END_UTEST(TestTree)
+
+///////////////////////////////////////////////////////////////////////////////
+// We try to stress the internal allocator here
+///////////////////////////////////////////////////////////////////////////////
+class TaskAllocate : public TaskSet {
+public:
+  TaskAllocate(size_t elemNum) : TaskSet(elemNum) {}
+  virtual void run(size_t elemID);
+  enum { allocNum = 1 << 10 };
+  enum { iterNum = 1 << 5 };
+};
+
+void TaskAllocate::run(size_t elemID) {
+  Task *tasks[allocNum];
+  for (int j = 0; j < iterNum; ++j) {
+    const int taskNum = rand() % allocNum;
+    for (int i = 0; i < taskNum; ++i) tasks[i] = PF_NEW(TaskDummy);
+    for (int i = 0; i < taskNum; ++i) PF_DELETE(tasks[i]);
+  }
+}
+
+START_UTEST(TestAllocator)
+  Task *done = PF_NEW(TaskDone);
+  Task *allocate = PF_NEW(TaskAllocate, 1 << 10);
+  double t = getSeconds();
+  allocate->starts(done);
+  done->scheduled();
+  allocate->scheduled();
+  TaskingSystemEnter();
+  t = getSeconds() - t;
+  std::cout << t * 1000. << " ms" << std::endl;
+END_UTEST(TestAllocator)
+
+///////////////////////////////////////////////////////////////////////////////
+// We are making the queue full to make the system recurse to empty it
+///////////////////////////////////////////////////////////////////////////////
+class TaskFull : public Task {
+public:
+  enum { taskToSpawn = 1u << 16u };
+  TaskFull(const char *name, Atomic &counter, int lvl = 0) :
+    Task(name), counter(counter), lvl(lvl) {}
+  virtual Task* run(void) {
+    if (lvl == 0)
+      for (size_t i = 0; i < taskToSpawn; ++i) {
+        Task *task = PF_NEW(TaskFull, "TaskFullLvl1", counter, 1);
+        task->ends(this);
+        task->scheduled();
+      }
+    else
+      counter++;
+    return NULL;
+  }
+  Atomic &counter;
+  int lvl;
+};
+
+START_UTEST(TestFullQueue)
+  Atomic counter(0u);
+  double t = getSeconds();
+  Task *done = PF_NEW(TaskDone);
+  for (size_t i = 0; i < 64; ++i) {
+    Task *task = PF_NEW(TaskFull, "TaskFull", counter);
+    task->starts(done);
+    task->scheduled();
+  }
+  done->scheduled();
+  TaskingSystemEnter();
+  t = getSeconds() - t;
+  std::cout << t * 1000. << " ms" << std::endl;
+  FATAL_IF (counter != 64 * TaskFull::taskToSpawn, "TestFullQueue failed");
+END_UTEST(TestFullQueue)
+
+///////////////////////////////////////////////////////////////////////////////
+// We spawn a lot of affinity jobs to saturate the affinity queues
+///////////////////////////////////////////////////////////////////////////////
+class TaskAffinity : public Task {
+public:
+  enum { taskToSpawn = 2048u };
+  TaskAffinity(Task *done, Atomic &counter, int lvl = 0) :
+    Task("TaskAffinity"), counter(counter), lvl(lvl) {}
+  virtual Task *run(void) {
+    if (lvl == 1)
+      counter++;
+    else {
+      const uint32 threadNum = TaskingSystemGetThreadNum();
+      for (uint32 i = 0; i < taskToSpawn; ++i) {
+        Task *task = PF_NEW(TaskAffinity, done.ptr, counter, 1);
+        task->setAffinity(i % threadNum);
+        task->ends(this);
+        task->scheduled();
+      }
+    }
+    return NULL;
+  }
+  Atomic &counter;
+  Ref<Task> done;
+  int lvl;
+};
+
+START_UTEST(TestAffinity)
+  enum { batchNum = 512 };
+  for (int i = 0; i < 8; ++i) {
+    Atomic counter(0u);
+    double t = getSeconds();
+    Ref<Task> done = PF_NEW(TaskDone);
+    for (size_t i = 0; i < batchNum; ++i) {
+      Task *task = PF_NEW(TaskAffinity, done.ptr, counter);
+      task->starts(done.ptr);
+      task->scheduled();
+    }
+    done->scheduled();
+    TaskingSystemEnter();
+    t = getSeconds() - t;
+    std::cout << t * 1000. << " ms" << std::endl;
+    std::cout << counter << std::endl;
+    FATAL_IF (counter != batchNum * TaskAffinity::taskToSpawn, "TestAffinity failed");
+  }
+END_UTEST(TestAffinity)
+
+///////////////////////////////////////////////////////////////////////////////
+// Exponential Fibonnaci to stress the task spawning and the completions
+///////////////////////////////////////////////////////////////////////////////
+static Atomic fiboNum(0u);
+class TaskFiboSpawn : public Task {
+public:
+  TaskFiboSpawn(uint64 rank, uint64 *root = NULL) :
+    Task("TaskFiboSpawn"), rank(rank), root(root) {fiboNum++;}
+  virtual Task* run(void);
+  uint64 rank, sumLeft, sumRight;
+  uint64 *root;
+};
+
+class FiboSumTask : public Task {
+public:
+  FiboSumTask(TaskFiboSpawn *fibo) : Task("FiboSumTask"), fibo(fibo) {}
+  virtual Task* run(void);
+  TaskFiboSpawn *fibo;
+};
+
+Task *TaskFiboSpawn::run(void) {
+  if (rank > 1) {
+    TaskFiboSpawn *left = PF_NEW(TaskFiboSpawn, rank-1, &this->sumLeft);
+    TaskFiboSpawn *right = PF_NEW(TaskFiboSpawn, rank-2, &this->sumRight);
+    FiboSumTask *sum = PF_NEW(FiboSumTask, this);
+    left->starts(sum);
+    right->starts(sum);
+    sum->ends(this);
+    sum->scheduled();
+    left->scheduled();
+    return right;
+  } else if (rank == 1) {
+    if (root) *root = 1;
+    return NULL;
+  } else {
+    if (root) *root = 0;
+    return NULL;
+  }
+}
+
+Task *FiboSumTask::run(void) {
+  assert(fibo);
+  if (fibo->root) *fibo->root = fibo->sumLeft + fibo->sumRight;
+  return NULL;
+}
+
+static uint64 fiboLinear(uint64 rank)
+{
+  uint64 rn0 = 0, rn1 = 1;
+  if (rank == 0) return rn0;
+  if (rank == 1) return rn1;
+  for (uint64 i = 2; i <= rank; ++i) {
+    uint64 sum = rn0 + rn1;
+    rn0 = rn1;
+    rn1 = sum;
+  }
+  return rn1;
+}
+
+START_UTEST(TestFibo)
+{
+  const uint64 rank = rand() % 32;
+  uint64 sum;
+  double t = getSeconds();
+  fiboNum = 0u;
+  Ref<TaskFiboSpawn> fibo = PF_NEW(TaskFiboSpawn, rank, &sum);
+  Task *done = PF_NEW(TaskDone);
+  fibo->starts(done);
+  fibo->scheduled();
+  done->scheduled();
+  TaskingSystemEnter();
+  t = getSeconds() - t;
+  std::cout << t * 1000. << " ms" << std::endl;
+  std::cout << "Fibonacci Task Num: "<< fiboNum << std::endl;
+  FATAL_IF (sum != fiboLinear(rank), "TestFibonacci failed");
+}
+END_UTEST(TestFibo)
+
+///////////////////////////////////////////////////////////////////////////////
+// Task with multiple dependencies
+///////////////////////////////////////////////////////////////////////////////
+class TaskMultiTrigger : public Task,
+                         public MultiDependencyPolicy<TaskMultiTrigger>
+{
+public:
+  TaskMultiTrigger(int32 *valueToSet) : valueToSet(valueToSet) {}
+  virtual Task *run(void) { *valueToSet = 1; return NULL; }
+private:
+  int32 *valueToSet;
+};
+
+class TaskTriggered : public Task
+{
+public:
+  TaskTriggered(const int32 *valueToRead, Atomic32 &dst) :
+    valueToRead(valueToRead), dst(dst) {}
+  virtual Task *run(void) { dst += *valueToRead; return NULL; }
+private:
+  const int32 *valueToRead;
+  Atomic32 &dst;
+};
+
+START_UTEST(TestMultiDependency)
+{
+  static const uint32 multiTaskToSpawn = 512;
+  static const uint32 triggeredTaskToSpawn = 512;
+  static const uint32 valueToSetNum = multiTaskToSpawn;
+
+  int32 *toSet = PF_NEW_ARRAY(int32, valueToSetNum);
+  Atomic32 dst(0);
+  Task *doneTask = PF_NEW(TaskDone);
+  for (uint32 i = 0; i < valueToSetNum; ++i) toSet[i] = 0;
+  for (uint32 i = 0; i < multiTaskToSpawn; ++i) {
+    Ref<TaskMultiTrigger> task = PF_NEW(TaskMultiTrigger, toSet + i);
+    for (uint32 j = 0; j < triggeredTaskToSpawn; ++j) {
+      Ref<Task> triggered = PF_NEW(TaskTriggered, toSet + i, dst);
+      Ref<Task> dummy = PF_NEW(TaskDummy);
+      task->multiStarts(dummy);
+      dummy->starts(triggered);
+      triggered->starts(doneTask);
+      triggered->scheduled();
+      dummy->scheduled();
+    }
+    task->scheduled();
+  }
+  doneTask->scheduled();
+  TaskingSystemEnter();
+  PF_DELETE_ARRAY(toSet);
+  const uint32 result = dst;
+  std::cout << "result: " << result << std::endl;
+  FATAL_IF(result != multiTaskToSpawn * triggeredTaskToSpawn,
+           "MultiDependency failed");
+}
+END_UTEST(TestMultiDependency)
+
+START_UTEST(TestMultiDependencyTwoStage)
+{
+  static const uint32 multiTaskToSpawn = 512;
+  static const uint32 triggeredTaskToSpawn = 512;
+  static const uint32 valueToSetNum = multiTaskToSpawn;
+
+  int32 *toSet = PF_NEW_ARRAY(int32, valueToSetNum);
+  Atomic32 dst(0);
+  Task *doneTask = PF_NEW(TaskDone);
+  for (uint32 i = 0; i < valueToSetNum; ++i) toSet[i] = 0;
+  for (uint32 i = 0; i < multiTaskToSpawn; ++i) {
+    Ref<TaskMultiTrigger> task = PF_NEW(TaskMultiTrigger, toSet + i);
+    for (uint32 j = 0; j < triggeredTaskToSpawn; ++j) {
+      Ref<Task> triggered = PF_NEW(TaskTriggered, toSet + i, dst);
+      task->multiStarts(triggered);
+      triggered->starts(doneTask);
+      triggered->scheduled();
+    }
+    task->scheduled();
+  }
+  doneTask->scheduled();
+  TaskingSystemEnter();
+  PF_DELETE_ARRAY(toSet);
+  const uint32 result = dst;
+  std::cout << "result: " << result << std::endl;
+  FATAL_IF(result != multiTaskToSpawn * triggeredTaskToSpawn,
+           "MultiDependency failed");
+}
+END_UTEST(TestMultiDependencyTwoStage)
+
+START_UTEST(TestMultiDependencyRandomStart)
+{
+  static const uint32 multiTaskToSpawn = 512;
+  static const uint32 triggeredTaskToSpawn = 512;
+  static const uint32 valueToSetNum = multiTaskToSpawn;
+  static const uint32 repeatNum = 8;
+  Random rand;
+  for (uint32 i = 0; i < repeatNum; ++i) {
+    int32 *toSet = PF_NEW_ARRAY(int32, valueToSetNum);
+    Atomic32 dst(0);
+    Ref<Task> doneTask = PF_NEW(TaskDone);
+    for (uint32 i = 0; i < valueToSetNum; ++i) toSet[i] = 0;
+    for (uint32 i = 0; i < multiTaskToSpawn; ++i) {
+      Ref<TaskMultiTrigger> task = PF_NEW(TaskMultiTrigger, toSet + i);
+      bool isScheduled = false;
+      for (uint32 j = 0; j < triggeredTaskToSpawn; ++j) {
+        Ref<Task> triggered = PF_NEW(TaskTriggered, toSet + i, dst);
+        task->multiStarts(triggered);
+        triggered->starts(doneTask);
+        triggered->scheduled();
+        if (rand.getFloat() < 0.8 && isScheduled == false) {
+          task->scheduled();
+          isScheduled = true;
+        }
+      }
+      if (isScheduled == false) task->scheduled();
+    }
+    doneTask->scheduled();
+    TaskingSystemEnter();
+    PF_DELETE_ARRAY(toSet);
+    const uint32 result = dst;
+    std::cout << "result: " << result << std::endl;
+    FATAL_IF(result != multiTaskToSpawn * triggeredTaskToSpawn,
+             "MultiDependencyRandomStart failed");
+  }
+}
+END_UTEST(TestMultiDependencyRandomStart)
+
+///////////////////////////////////////////////////////////////////////////////
+// Test tasking lock and unlock
+///////////////////////////////////////////////////////////////////////////////
+class TaskLockUnlock : public Task
+{
+public:
+  TaskLockUnlock(int32 *shared) : shared(shared) {}
+  virtual Task *run(void) {
+    TaskingSystemLock();
+    *shared = *shared + 1;
+    TaskingSystemUnlock();
+    return NULL;
+  }
+  int32 *shared;
+};
+
+START_UTEST(TestLockUnlock)
+{
+  static const uint32 taskNum = 1024;
+  int32 shared = 0;
+  Ref<Task> doneTask = PF_NEW(TaskDone);
+  for (uint32 i = 0; i < taskNum; ++i) {
+    Task *updateTask = PF_NEW(TaskLockUnlock, &shared);
+    updateTask->starts(doneTask);
+    updateTask->scheduled();
+  }
+  doneTask->scheduled();
+  TaskingSystemEnter();
+  FATAL_IF(shared != int32(taskNum), "TestLockUnlock failed");
+}
+END_UTEST(TestLockUnlock)
+
+///////////////////////////////////////////////////////////////////////////////
+// Test tasking profiler
+///////////////////////////////////////////////////////////////////////////////
+#if PF_TASK_PROFILER
+class UTestProfiler : public TaskProfiler
+{
+public:
+  UTestProfiler(void) : 
+    sleepNum(0), wakeUpNum(0),
+    lockNum(0), unlockNum(0),
+    runStartNum(0), runEndNum(0), endNum(0) {}
+  virtual void onSleep(uint32 threadID)  {sleepNum++;}
+  virtual void onWakeUp(uint32 threadID) {wakeUpNum++;}
+  virtual void onLock(uint32 threadID)   {lockNum++;}
+  virtual void onUnlock(uint32 threadID) {unlockNum++;}
+  virtual void onRunStart(const char *taskName, uint32 threadID) {runStartNum++;}
+  virtual void onRunEnd(const char *taskName, uint32 threadID)   {runEndNum++;}
+  virtual void onEnd(const char *taskName, uint32 threadID)      {endNum++;}
+  Atomic sleepNum;
+  Atomic wakeUpNum;
+  Atomic lockNum;
+  Atomic unlockNum;
+  Atomic runStartNum;
+  Atomic runEndNum;
+  Atomic endNum;
+};
+
+START_UTEST(TestProfiler)
+{
+  UTestProfiler *profiler = PF_NEW(UTestProfiler);
+  TaskingSystemSetProfiler(profiler);
+  TestFibo();
+  TestTaskSet();
+  TestMultiDependency();
+  TestLockUnlock();
+#define OUTPUT_FIELD(FIELD) \
+  std::cout << #FIELD ": " << profiler->FIELD << std::endl
+  OUTPUT_FIELD(sleepNum);
+  OUTPUT_FIELD(wakeUpNum);
+  OUTPUT_FIELD(lockNum);
+  OUTPUT_FIELD(unlockNum);
+  OUTPUT_FIELD(runStartNum);
+  OUTPUT_FIELD(runEndNum);
+  OUTPUT_FIELD(endNum);    
+#undef OUTPUT_FIELD
+  TaskingSystemSetProfiler(NULL);
+  PF_DELETE(profiler);
+}
+END_UTEST(TestProfiler)
+#endif /* PF_TASK_PROFILER */
+
+/*! Run all tasking tests */
+void utest_tasking(void)
+{
+  TestDummy();
+  TestTree<TaskNodeOpt>();
+  TestTree<TaskNode>();
+  TestTree<TaskCascadeNodeOpt>();
+  TestTree<TaskCascadeNode>();
+  TestTaskSet();
+  TestAllocator();
+  TestFullQueue();
+  TestAffinity();
+  TestFibo();
+  TestMultiDependency();
+  TestMultiDependencyTwoStage();
+  TestMultiDependencyRandomStart();
+  TestLockUnlock();
+  TestProfiler();
+}
+
+UTEST_REGISTER(utest_tasking);