summaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
Diffstat (limited to 'backend')
-rw-r--r--backend/CMakeLists.txt104
-rw-r--r--backend/src/CMakeLists.txt42
-rw-r--r--backend/src/ir/function.cpp19
-rw-r--r--backend/src/ir/function.hpp19
-rw-r--r--backend/src/ir/instruction.cpp19
-rw-r--r--backend/src/ir/instruction.hpp19
-rw-r--r--backend/src/ir/register.cpp19
-rw-r--r--backend/src/ir/register.hpp19
-rw-r--r--backend/src/ir/scope.cpp19
-rw-r--r--backend/src/ir/scope.hpp19
-rw-r--r--backend/src/ir/unit.cpp19
-rw-r--r--backend/src/ir/unit.hpp19
-rw-r--r--backend/src/sys/alloc.cpp261
-rw-r--r--backend/src/sys/alloc.hpp229
-rw-r--r--backend/src/sys/array.hpp108
-rw-r--r--backend/src/sys/atomic.hpp57
-rw-r--r--backend/src/sys/barrier.hpp62
-rw-r--r--backend/src/sys/condition.cpp139
-rw-r--r--backend/src/sys/condition.hpp40
-rw-r--r--backend/src/sys/constants.hpp144
-rw-r--r--backend/src/sys/default_path.cpp38
-rw-r--r--backend/src/sys/default_path.hpp34
-rw-r--r--backend/src/sys/filename.cpp123
-rw-r--r--backend/src/sys/filename.hpp72
-rw-r--r--backend/src/sys/fixed_array.hpp79
-rw-r--r--backend/src/sys/hash_map.hpp73
-rw-r--r--backend/src/sys/intrinsics.hpp210
-rw-r--r--backend/src/sys/library.cpp91
-rw-r--r--backend/src/sys/library.hpp40
-rw-r--r--backend/src/sys/list.hpp60
-rw-r--r--backend/src/sys/logging.cpp87
-rw-r--r--backend/src/sys/logging.hpp141
-rw-r--r--backend/src/sys/map.hpp63
-rw-r--r--backend/src/sys/mutex.cpp49
-rw-r--r--backend/src/sys/mutex.hpp75
-rw-r--r--backend/src/sys/platform.cpp79
-rw-r--r--backend/src/sys/platform.hpp373
-rw-r--r--backend/src/sys/ref.hpp99
-rw-r--r--backend/src/sys/set.hpp59
-rw-r--r--backend/src/sys/string.cpp130
-rw-r--r--backend/src/sys/string.hpp53
-rw-r--r--backend/src/sys/sysinfo.cpp148
-rw-r--r--backend/src/sys/sysinfo.hpp37
-rw-r--r--backend/src/sys/thread.cpp213
-rw-r--r--backend/src/sys/thread.hpp54
-rw-r--r--backend/src/sys/vector.hpp72
-rw-r--r--backend/src/utest/utest.cpp57
-rw-r--r--backend/src/utest/utest.hpp53
-rw-r--r--backend/src/utest/utest_console.cpp95
-rw-r--r--backend/src/utest/utest_font.cpp41
-rw-r--r--backend/src/utest/utest_lua.cpp58
-rw-r--r--backend/src/utest/utest_rt.cpp193
-rw-r--r--backend/src/utest/utest_tasking.cpp653
53 files changed, 5078 insertions, 0 deletions
diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt
new file mode 100644
index 00000000..73a79edb
--- /dev/null
+++ b/backend/CMakeLists.txt
@@ -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
index 00000000..5a3b20b6
--- /dev/null
+++ b/backend/src/CMakeLists.txt
@@ -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
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/function.cpp
@@ -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
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/function.hpp
@@ -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
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/instruction.cpp
@@ -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
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/instruction.hpp
@@ -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
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/register.cpp
@@ -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
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/register.hpp
@@ -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
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/scope.cpp
@@ -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
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/scope.hpp
@@ -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
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/unit.cpp
@@ -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
index 00000000..12001d60
--- /dev/null
+++ b/backend/src/ir/unit.hpp
@@ -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
index 00000000..e23ae8e6
--- /dev/null
+++ b/backend/src/sys/alloc.cpp
@@ -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
index 00000000..5b686343
--- /dev/null
+++ b/backend/src/sys/alloc.hpp
@@ -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
index 00000000..04cc3c6c
--- /dev/null
+++ b/backend/src/sys/array.hpp
@@ -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
index 00000000..07b2fdaf
--- /dev/null
+++ b/backend/src/sys/atomic.hpp
@@ -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
index 00000000..9182a98c
--- /dev/null
+++ b/backend/src/sys/barrier.hpp
@@ -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
index 00000000..27923f22
--- /dev/null
+++ b/backend/src/sys/condition.cpp
@@ -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
index 00000000..a6d71f72
--- /dev/null
+++ b/backend/src/sys/condition.hpp
@@ -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
index 00000000..9849d11d
--- /dev/null
+++ b/backend/src/sys/constants.hpp
@@ -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
index 00000000..3661feed
--- /dev/null
+++ b/backend/src/sys/default_path.cpp
@@ -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
index 00000000..5f841790
--- /dev/null
+++ b/backend/src/sys/default_path.hpp
@@ -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
index 00000000..58221f5c
--- /dev/null
+++ b/backend/src/sys/filename.cpp
@@ -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
index 00000000..4f4fb391
--- /dev/null
+++ b/backend/src/sys/filename.hpp
@@ -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
index 00000000..68593ecf
--- /dev/null
+++ b/backend/src/sys/fixed_array.hpp
@@ -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
index 00000000..ab1a317d
--- /dev/null
+++ b/backend/src/sys/hash_map.hpp
@@ -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
index 00000000..99f55527
--- /dev/null
+++ b/backend/src/sys/intrinsics.hpp
@@ -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
index 00000000..815bd592
--- /dev/null
+++ b/backend/src/sys/library.cpp
@@ -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
index 00000000..8dcb1a93
--- /dev/null
+++ b/backend/src/sys/library.hpp
@@ -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
index 00000000..6f479d28
--- /dev/null
+++ b/backend/src/sys/list.hpp
@@ -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
index 00000000..6f4c8401
--- /dev/null
+++ b/backend/src/sys/logging.cpp
@@ -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
index 00000000..ae69e321
--- /dev/null
+++ b/backend/src/sys/logging.hpp
@@ -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
index 00000000..c673b86f
--- /dev/null
+++ b/backend/src/sys/map.hpp
@@ -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
index 00000000..590ad5d4
--- /dev/null
+++ b/backend/src/sys/mutex.cpp
@@ -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
index 00000000..b29b3c88
--- /dev/null
+++ b/backend/src/sys/mutex.hpp
@@ -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
index 00000000..96fab95a
--- /dev/null
+++ b/backend/src/sys/platform.cpp
@@ -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
index 00000000..ecd205fb
--- /dev/null
+++ b/backend/src/sys/platform.hpp
@@ -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
index 00000000..1672f543
--- /dev/null
+++ b/backend/src/sys/ref.hpp
@@ -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
index 00000000..efaf7ed3
--- /dev/null
+++ b/backend/src/sys/set.hpp
@@ -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
index 00000000..093bb267
--- /dev/null
+++ b/backend/src/sys/string.cpp
@@ -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
index 00000000..04479667
--- /dev/null
+++ b/backend/src/sys/string.hpp
@@ -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
index 00000000..15a56095
--- /dev/null
+++ b/backend/src/sys/sysinfo.cpp
@@ -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
index 00000000..5679ddb0
--- /dev/null
+++ b/backend/src/sys/sysinfo.hpp
@@ -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
index 00000000..12503ce3
--- /dev/null
+++ b/backend/src/sys/thread.cpp
@@ -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
index 00000000..0611ef72
--- /dev/null
+++ b/backend/src/sys/thread.hpp
@@ -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
index 00000000..a100770d
--- /dev/null
+++ b/backend/src/sys/vector.hpp
@@ -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
index 00000000..8fca9682
--- /dev/null
+++ b/backend/src/utest/utest.cpp
@@ -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
index 00000000..fea1bbcd
--- /dev/null
+++ b/backend/src/utest/utest.hpp
@@ -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
index 00000000..51075944
--- /dev/null
+++ b/backend/src/utest/utest_console.cpp
@@ -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
index 00000000..d6b0fa9f
--- /dev/null
+++ b/backend/src/utest/utest_font.cpp
@@ -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
index 00000000..289ef7f3
--- /dev/null
+++ b/backend/src/utest/utest_lua.cpp
@@ -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
index 00000000..cf2db0ab
--- /dev/null
+++ b/backend/src/utest/utest_rt.cpp
@@ -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
index 00000000..419c3d73
--- /dev/null
+++ b/backend/src/utest/utest_tasking.cpp
@@ -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);