├── tests ├── exception_propagation_test.cpp ├── main.cpp ├── cpptasktest.h ├── parallel_for_each_test.cpp ├── parallel_reduce_test.cpp ├── test_data.h ├── sync_test.cpp ├── async_test.cpp ├── process_lock_test.cpp ├── spsc_queue_test.cpp └── event_manager_test.cpp ├── .gitignore ├── LICENSE ├── include └── cpptask │ ├── alignedalloc.h │ ├── tlskey.h │ ├── cpptask.h │ ├── init.h │ ├── Win │ ├── alignedalloc.h │ ├── winerrmsg.h │ └── tlskey.h │ ├── mutex.h │ ├── taskthread.h │ ├── exception.h │ ├── Unix │ └── tlskey.h │ ├── parallelfor.h │ ├── taskmanager.h │ ├── eventmanager.h │ ├── taskthreadimpl.h │ ├── task.h │ ├── threadpool.h │ ├── range.h │ ├── event.h │ ├── processlock.h │ ├── parallelreduce.h │ ├── semaphor.h │ ├── taskmanagerlimpl.h │ ├── spscqueue.h │ └── async.h ├── 3rdparty └── gtest │ ├── src │ ├── gtest_main.cc │ ├── gtest-all.cc │ ├── gtest-typed-test.cc │ └── gtest-test-part.cc │ └── include │ └── gtest │ ├── gtest_prod.h │ ├── gtest-test-part.h │ ├── internal │ ├── gtest-string.h │ ├── gtest-linked_ptr.h │ ├── gtest-filepath.h │ ├── gtest-type-util.h.pump │ ├── gtest-param-util-generated.h.pump │ └── gtest-tuple.h.pump │ ├── gtest-message.h │ └── gtest-spi.h ├── CMakeLists.txt └── README.md /tests/exception_propagation_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | TEST(ExceptionsTest, Propagation) 8 | { 9 | cpptask::initializer init(4); 10 | auto f = cpptask::async(std::launch::async, 11 | []() 12 | { 13 | throw cpptask::exception("Test exception message"); 14 | }); 15 | ASSERT_THROW(f.get(), cpptask::exception); 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | #temopraries 31 | *.user 32 | 33 | #Directories 34 | build/ 35 | build-debug/ 36 | build-release/ -------------------------------------------------------------------------------- /tests/main.cpp: -------------------------------------------------------------------------------- 1 | #include "test_data.h" 2 | 3 | #include 4 | 5 | class GlobalEnvironment : public testing::Environment 6 | { 7 | public: 8 | virtual void SetUp() 9 | { 10 | CppTaskTestData::instance().init(); 11 | } 12 | 13 | virtual void TearDown() {} 14 | }; 15 | 16 | 17 | int main(int argc, char* argv[]) 18 | { 19 | ::testing::InitGoogleTest(&argc, argv); 20 | auto genv = new GlobalEnvironment(); 21 | if (::testing::AddGlobalTestEnvironment(genv) == genv) 22 | { 23 | return RUN_ALL_TESTS(); 24 | } 25 | return -1; 26 | } 27 | -------------------------------------------------------------------------------- /tests/cpptasktest.h: -------------------------------------------------------------------------------- 1 | #ifndef CPPTASKTEST_H 2 | #define CPPTASKTEST_H 3 | 4 | #include "test_data.h" 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | class CppTaskTest : public ::testing::Test 11 | { 12 | protected: 13 | CppTaskTestData::ArrayType testArray; 14 | char pad[64]; 15 | CppTaskTestData::ArrayType testArray2; 16 | 17 | virtual void SetUp() 18 | { 19 | testArray = CppTaskTestData::instance().getTestArray(); 20 | testArray2 = CppTaskTestData::instance().getTestArray(); 21 | } 22 | 23 | virtual void TearDown() 24 | { 25 | } 26 | }; 27 | 28 | #endif // CPPTASKTEST_H 29 | 30 | -------------------------------------------------------------------------------- /tests/parallel_for_each_test.cpp: -------------------------------------------------------------------------------- 1 | #include "cpptasktest.h" 2 | 3 | #include 4 | 5 | TEST_F(CppTaskTest, ForEach_Serial) 6 | { 7 | cpptask::initializer init(0); 8 | 9 | ASSERT_NO_THROW(cpptask::for_each(testArray.begin(), testArray.end(), CppTaskTestData::DoubleSqrt())); 10 | 11 | ASSERT_EQ(CppTaskTestData::instance().getResultArray(), testArray); 12 | } 13 | 14 | TEST_F(CppTaskTest, ForEach_Parallel) 15 | { 16 | cpptask::initializer init(4); 17 | 18 | ASSERT_NO_THROW(cpptask::for_each(testArray.begin(), testArray.end(), CppTaskTestData::DoubleSqrt())); 19 | 20 | ASSERT_EQ(CppTaskTestData::instance().getResultArray(), testArray); 21 | } 22 | 23 | -------------------------------------------------------------------------------- /tests/parallel_reduce_test.cpp: -------------------------------------------------------------------------------- 1 | #include "cpptasktest.h" 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace 8 | { 9 | double process_func(const cpptask::range& range) 10 | { 11 | double res = 0; 12 | std::for_each(range.start, range.end, 13 | [&res](double x) 14 | { 15 | CppTaskTestData::DoubleSqrt()(x); 16 | res += x; 17 | }); 18 | return res; 19 | } 20 | 21 | double join_func(double a, double b) 22 | { 23 | return a + b; 24 | } 25 | } 26 | 27 | TEST_F(CppTaskTest, Reduce_Serial) 28 | { 29 | cpptask::initializer init(0); 30 | 31 | double sum = cpptask::reduce(testArray.begin(), testArray.end(), process_func, join_func); 32 | 33 | ASSERT_EQ(CppTaskTestData::instance().getSum(), sum); 34 | } 35 | 36 | 37 | TEST_F(CppTaskTest, Reduce_Parallel) 38 | { 39 | cpptask::initializer init(4); 40 | 41 | double sum = cpptask::reduce(testArray.begin(), testArray.end(), process_func, join_func); 42 | 43 | ASSERT_EQ(CppTaskTestData::instance().getSum(), sum); 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | https://github.com/Kolkir/cpptask 2 | Copyright (c) 2015, Kyrylo Kolodiazhnyi 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions 5 | are met: 6 | 1. Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 13 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 16 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 17 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 18 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 19 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 20 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 21 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 22 | POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /tests/test_data.h: -------------------------------------------------------------------------------- 1 | #ifndef CPPTASKTEST_DATA_H 2 | #define CPPTASKTEST_DATA_H 3 | 4 | #include 5 | #include 6 | 7 | class CppTaskTestData 8 | { 9 | public: 10 | typedef std::vector ArrayType; 11 | 12 | const int N = 25000000; 13 | 14 | struct DoubleSqrt 15 | { 16 | void operator()(double& x) 17 | { 18 | x = std::sqrt(std::sqrt(x)); 19 | x = std::sqrt(std::sqrt(x)); 20 | } 21 | }; 22 | 23 | CppTaskTestData(const CppTaskTestData&) = delete; 24 | CppTaskTestData& operator=(const CppTaskTestData&) = delete; 25 | 26 | static CppTaskTestData& instance() 27 | { 28 | static CppTaskTestData data; 29 | return data; 30 | } 31 | 32 | double getSum() const 33 | { 34 | return sum; 35 | } 36 | 37 | const ArrayType& getTestArray() const 38 | { 39 | return testArray; 40 | } 41 | 42 | const ArrayType& getResultArray() const 43 | { 44 | return resultArray; 45 | } 46 | 47 | void init() 48 | { 49 | for (int i = 0; i < sum; ++i) 50 | { 51 | testArray[i] = resultArray[i] = static_cast(i); 52 | DoubleSqrt()(resultArray[i]); 53 | sum += resultArray[i]; 54 | } 55 | } 56 | 57 | private: 58 | 59 | CppTaskTestData() 60 | : testArray(N, 0) 61 | , resultArray(N, 0) 62 | , sum(0) 63 | { 64 | } 65 | 66 | private: 67 | ArrayType testArray; 68 | ArrayType resultArray; 69 | double sum; 70 | }; 71 | 72 | #endif // CPPTASKTEST_H 73 | 74 | -------------------------------------------------------------------------------- /tests/sync_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | TEST(SyncTest, Event) 8 | { 9 | int count = 0; 10 | cpptask::event e1; 11 | cpptask::event e2; 12 | { 13 | auto f = std::async(std::launch::async, [&]() 14 | { 15 | while (count != 5) 16 | { 17 | e1.wait(); 18 | ++count; 19 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); 20 | e2.notify(); 21 | } 22 | }); 23 | 24 | for (int i = 0; i < 5; ++i) 25 | { 26 | e1.notify(); 27 | e2.wait(); 28 | } 29 | f.wait(); 30 | } 31 | ASSERT_EQ(5, count); 32 | } 33 | 34 | TEST(SyncTest, Semaphore) 35 | { 36 | cpptask::semaphore s(2,2); 37 | { 38 | auto f1 = std::async(std::launch::async,[&]() 39 | { 40 | s.lock(); 41 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); 42 | s.unlock(); 43 | }); 44 | 45 | auto f2 = std::async(std::launch::async,[&]() 46 | { 47 | s.lock(); 48 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); 49 | s.unlock(); 50 | }); 51 | 52 | auto f3 = std::async(std::launch::async,[&]() 53 | { 54 | s.lock(); 55 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); 56 | s.unlock(); 57 | }); 58 | 59 | f1.wait(); 60 | f2.wait(); 61 | f3.wait(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /include/cpptask/alignedalloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2011, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_ALIGNED_ALLOC_SELECT_H_ 29 | #define _CPP_TASK_ALIGNED_ALLOC_SELECT_H_ 30 | 31 | #ifdef _WIN32 32 | #include "Win/alignedalloc.h" 33 | #endif 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /include/cpptask/tlskey.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2012, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_TLSKEY_SELECT_H_ 29 | #define _CPP_TASK_TLSKEY_SELECT_H_ 30 | 31 | #ifdef _WIN32 32 | #include "Win/tlskey.h" 33 | #else 34 | #include "Unix/tlskey.h" 35 | #endif 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /3rdparty/gtest/src/gtest_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2006, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | 32 | #include "gtest/gtest.h" 33 | 34 | GTEST_API_ int main(int argc, char **argv) { 35 | printf("Running main() from gtest_main.cc\n"); 36 | testing::InitGoogleTest(&argc, argv); 37 | return RUN_ALL_TESTS(); 38 | } 39 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(cpptask) 3 | 4 | include_directories("${PROJECT_SOURCE_DIR}/3rdparty/gtest/include/") 5 | include_directories("${PROJECT_SOURCE_DIR}/3rdparty/gtest/") 6 | include_directories("${PROJECT_SOURCE_DIR}/include/") 7 | 8 | if(MSVC) 9 | set(CMAKE_CXX_FLAGS "/W4 /EHsc") 10 | set(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1 /MP2") 11 | set(CMAKE_CXX_FLAGS_MINSIZEREL "/MT /O1 /Ob1 /D NDEBUG /MP") 12 | set(CMAKE_CXX_FLAGS_RELEASE "/MT /O2 /Ob2 /D NDEBUG /MP") 13 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MT /Zi /O2 /Ob1 /D NDEBUG /MP") 14 | else() 15 | SET (CMAKE_C_FLAGS "-Wall -std=c99") 16 | SET (CMAKE_C_FLAGS_DEBUG "-g") 17 | SET (CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG") 18 | SET (CMAKE_C_FLAGS_RELEASE "-O4 -DNDEBUG") 19 | SET (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g") 20 | 21 | SET (CMAKE_CXX_FLAGS "-Wall -std=c++11 -pthread -fPIE -fpie") 22 | #-fsanitize=thread 23 | SET (CMAKE_CXX_FLAGS_DEBUG "-g") 24 | SET (CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG") 25 | SET (CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG") 26 | SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") 27 | endif() 28 | 29 | file(GLOB SRC_FILES include/cpptask/* 30 | "*.h" 31 | ) 32 | 33 | if(MSVC) 34 | file(GLOB SRC_PLATFORM_FILES include/cpptask/Win/* 35 | "*.h" 36 | ) 37 | else() 38 | file(GLOB SRC_PLATFORM_FILES include/cpptask/Unix/* 39 | "*.h" 40 | ) 41 | endif() 42 | 43 | 44 | file(GLOB SRC_TESTS_FILES tests/* 45 | "*.h" 46 | "*.cpp" 47 | ) 48 | 49 | set(GTEST_SOURCES 50 | ${PROJECT_SOURCE_DIR}/3rdparty/gtest/src/gtest-all.cc 51 | ) 52 | 53 | add_library(gtest STATIC ${GTEST_SOURCES}) 54 | 55 | add_executable(tests ${SRC_FILES} ${SRC_PLATFORM_FILES} ${SRC_TESTS_FILES}) 56 | target_link_libraries (tests gtest) 57 | -------------------------------------------------------------------------------- /include/cpptask/cpptask.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2012, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_H_ 29 | #define _CPP_TASK_H_ 30 | 31 | #define _CPP_TASK_CACHE_LINE_SIZE_ 64 32 | 33 | #include "taskmanager.h" 34 | #include "taskthreadimpl.h" 35 | #include "taskmanagerlimpl.h" 36 | #include "threadpool.h" 37 | #include "init.h" 38 | #include "async.h" 39 | #include "event.h" 40 | #include "semaphor.h" 41 | #include "mutex.h" 42 | #include "processlock.h" 43 | 44 | #include "parallelfor.h" 45 | #include "parallelreduce.h" 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /include/cpptask/init.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2015, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_INIT_H_ 29 | #define _CPP_TASK_INIT_H_ 30 | 31 | #include "threadpool.h" 32 | 33 | namespace cpptask 34 | { 35 | 36 | class initializer 37 | { 38 | public: 39 | initializer(size_t threadsNum) 40 | : threadPool(threadsNum) 41 | { 42 | } 43 | 44 | 45 | 46 | initializer(const initializer&) = delete; 47 | 48 | const initializer& operator=(const initializer&) = delete; 49 | 50 | private: 51 | internal::TaskThreadPool threadPool; 52 | }; 53 | 54 | } 55 | #endif 56 | -------------------------------------------------------------------------------- /include/cpptask/Win/alignedalloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2011, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_ALIGNED_ALLOC_H_ 29 | #define _CPP_TASK_ALIGNED_ALLOC_H_ 30 | 31 | #include 32 | 33 | namespace cpptask { namespace internal { 34 | 35 | inline void* aligned_alloc(size_t align_size, size_t size) 36 | { 37 | #ifdef __GNUC__ 38 | return __mingw_aligned_malloc(size, align_size); 39 | #else 40 | return _aligned_malloc(size, align_size); 41 | #endif 42 | } 43 | 44 | inline void free(void* ptr) 45 | { 46 | #ifdef __GNUC__ 47 | return __mingw_aligned_free(ptr); 48 | #else 49 | return _aligned_free(ptr); 50 | #endif 51 | } 52 | 53 | }} 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /3rdparty/gtest/src/gtest-all.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: mheule@google.com (Markus Heule) 31 | // 32 | // Google C++ Testing Framework (Google Test) 33 | // 34 | // Sometimes it's desirable to build Google Test by compiling a single file. 35 | // This file serves this purpose. 36 | 37 | // This line ensures that gtest.h can be compiled on its own, even 38 | // when it's fused. 39 | #include "gtest/gtest.h" 40 | 41 | // The following lines pull in the real gtest *.cc files. 42 | #include "src/gtest.cc" 43 | #include "src/gtest-death-test.cc" 44 | #include "src/gtest-filepath.cc" 45 | #include "src/gtest-port.cc" 46 | #include "src/gtest-printers.cc" 47 | #include "src/gtest-test-part.cc" 48 | #include "src/gtest-typed-test.cc" 49 | -------------------------------------------------------------------------------- /include/cpptask/Win/winerrmsg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2013, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _WINERRMSG_H_ 29 | #define _WINERRMSG_H_ 30 | 31 | #include 32 | #include 33 | 34 | namespace cpptask 35 | { 36 | 37 | inline std::string GetLastWinErrMsg() 38 | { 39 | DWORD err = ::GetLastError(); 40 | void* cstr = nullptr; 41 | FormatMessage( 42 | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 43 | NULL, 44 | err, 45 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 46 | (LPTSTR) &cstr, 47 | 0, 48 | NULL 49 | ); 50 | std::string res; 51 | try 52 | { 53 | res = reinterpret_cast(cstr); 54 | } 55 | catch(...) 56 | { 57 | LocalFree(cstr); 58 | throw; 59 | } 60 | LocalFree(cstr); 61 | return res; 62 | } 63 | 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /include/cpptask/mutex.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2015, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_MUTEX_H_ 29 | #define _CPP_TASK_MUTEX_H_ 30 | 31 | #include "taskmanager.h" 32 | 33 | #include 34 | 35 | namespace cpptask 36 | { 37 | 38 | //use this class only if you have corresponding process_lock object 39 | class mutex 40 | { 41 | public: 42 | typedef internal::EventManager EventManagerType; 43 | 44 | mutex() noexcept 45 | {} 46 | 47 | ~mutex() 48 | {} 49 | 50 | mutex(const mutex&) = delete; 51 | 52 | const mutex& operator=(const mutex&) = delete; 53 | 54 | void lock() 55 | { 56 | guard.lock(); 57 | } 58 | 59 | void unlock() 60 | { 61 | guard.unlock(); 62 | internal::TaskManager::GetCurrent().GetEventManager().notify(internal::EventId::CustomEvent); 63 | } 64 | 65 | bool try_lock() 66 | { 67 | return guard.try_lock(); 68 | } 69 | 70 | private: 71 | std::mutex guard; 72 | }; 73 | 74 | } 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /tests/async_test.cpp: -------------------------------------------------------------------------------- 1 | #include "cpptasktest.h" 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace 8 | { 9 | void processFunc(CppTaskTestData::ArrayType& arr) 10 | { 11 | auto i = arr.begin(); 12 | auto e = arr.end(); 13 | for (; i != e; ++i) 14 | { 15 | CppTaskTestData::DoubleSqrt()(*i); 16 | } 17 | } 18 | } 19 | 20 | TEST_F(CppTaskTest, Async_Deffered) 21 | { 22 | cpptask::initializer init(4); 23 | 24 | auto f1 = cpptask::async(std::launch::deferred, processFunc, std::ref(testArray)); 25 | auto f2 = cpptask::async(std::launch::deferred, processFunc, std::ref(testArray2)); 26 | 27 | ASSERT_TRUE(f1.valid()); 28 | ASSERT_TRUE(f2.valid()); 29 | 30 | ASSERT_NO_THROW(f1.get()); 31 | ASSERT_NO_THROW(f2.get()); 32 | 33 | ASSERT_EQ(CppTaskTestData::instance().getResultArray(), testArray); 34 | ASSERT_EQ(CppTaskTestData::instance().getResultArray(), testArray2); 35 | } 36 | 37 | TEST_F(CppTaskTest, Async_Parallel) 38 | { 39 | cpptask::initializer init(4); 40 | 41 | auto f1 = cpptask::async(std::launch::async, processFunc, std::ref(testArray)); 42 | auto f2 = cpptask::async(std::launch::async, processFunc, std::ref(testArray2)); 43 | 44 | ASSERT_TRUE(f1.valid()); 45 | ASSERT_TRUE(f2.valid()); 46 | 47 | //try don't use future::wait_for - because it's blocking operation which exclude current thread from calculations 48 | //ASSERT_FALSE(f1.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready); 49 | 50 | ASSERT_NO_THROW(f1.get()); 51 | ASSERT_NO_THROW(f2.get()); 52 | 53 | ASSERT_EQ(CppTaskTestData::instance().getResultArray(), testArray); 54 | ASSERT_EQ(CppTaskTestData::instance().getResultArray(), testArray2); 55 | } 56 | 57 | TEST_F(CppTaskTest, Async_ParallelWait) 58 | { 59 | cpptask::initializer init(4); 60 | 61 | auto f1 = cpptask::async(std::launch::async, processFunc, std::ref(testArray)); 62 | auto f2 = cpptask::async(std::launch::async, processFunc, std::ref(testArray2)); 63 | 64 | ASSERT_TRUE(f1.valid()); 65 | ASSERT_TRUE(f2.valid()); 66 | 67 | ASSERT_NO_THROW(f1.wait()); 68 | ASSERT_NO_THROW(f2.wait()); 69 | 70 | ASSERT_NO_THROW(f1.get()); 71 | ASSERT_NO_THROW(f2.get()); 72 | 73 | ASSERT_EQ(CppTaskTestData::instance().getResultArray(), testArray); 74 | ASSERT_EQ(CppTaskTestData::instance().getResultArray(), testArray2); 75 | } 76 | -------------------------------------------------------------------------------- /include/cpptask/taskthread.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2011, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_TASKTHREAD_H_ 29 | #define _CPP_TASK_TASKTHREAD_H_ 30 | 31 | #include "event.h" 32 | #include "eventmanager.h" 33 | #include "taskmanager.h" 34 | 35 | #include 36 | #include 37 | 38 | namespace cpptask { namespace internal { 39 | 40 | class Task; 41 | class TaskThreadPool; 42 | 43 | class TaskThread 44 | { 45 | public: 46 | TaskThread(TaskThreadPool& threadPool, EventManager& eventManager); 47 | 48 | ~TaskThread(); 49 | 50 | TaskThread(const TaskThread&) = delete; 51 | 52 | TaskThread& operator=(const TaskThread&) = delete; 53 | 54 | void Start(); 55 | 56 | void Wait(); 57 | 58 | TaskManager& GetTaskManager(); 59 | 60 | private: 61 | 62 | void Run(); 63 | 64 | private: 65 | EventManager& eventManager; 66 | std::unique_ptr taskManager; 67 | std::thread thread; 68 | }; 69 | 70 | }} 71 | #endif 72 | -------------------------------------------------------------------------------- /include/cpptask/exception.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2011, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_EXCEPTION_H_ 29 | #define _CPP_TASK_EXCEPTION_H_ 30 | 31 | #include 32 | #include 33 | 34 | namespace cpptask 35 | { 36 | 37 | class exception: public std::exception 38 | { 39 | public: 40 | typedef std::exception BaseType; 41 | 42 | exception() throw() {} 43 | virtual ~exception() throw(){} 44 | 45 | explicit exception(const std::string& message) 46 | : message(message) 47 | { 48 | } 49 | 50 | explicit exception(const char *message) 51 | : message(message) 52 | { 53 | } 54 | 55 | exception(const exception& ex) 56 | : message(ex.message) 57 | { 58 | } 59 | 60 | exception& operator = (const exception& ex) 61 | { 62 | this->message = ex.message; 63 | return *this; 64 | } 65 | 66 | virtual const char* what() const noexcept 67 | { 68 | return message.c_str(); 69 | } 70 | private: 71 | std::string message; 72 | }; 73 | 74 | } 75 | #endif 76 | -------------------------------------------------------------------------------- /3rdparty/gtest/include/gtest/gtest_prod.h: -------------------------------------------------------------------------------- 1 | // Copyright 2006, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | // 32 | // Google C++ Testing Framework definitions useful in production code. 33 | 34 | #ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 35 | #define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 36 | 37 | // When you need to test the private or protected members of a class, 38 | // use the FRIEND_TEST macro to declare your tests as friends of the 39 | // class. For example: 40 | // 41 | // class MyClass { 42 | // private: 43 | // void MyMethod(); 44 | // FRIEND_TEST(MyClassTest, MyMethod); 45 | // }; 46 | // 47 | // class MyClassTest : public testing::Test { 48 | // // ... 49 | // }; 50 | // 51 | // TEST_F(MyClassTest, MyMethod) { 52 | // // Can call MyClass::MyMethod() here. 53 | // } 54 | 55 | #define FRIEND_TEST(test_case_name, test_name)\ 56 | friend class test_case_name##_##test_name##_Test 57 | 58 | #endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 59 | -------------------------------------------------------------------------------- /include/cpptask/Unix/tlskey.h: -------------------------------------------------------------------------------- 1 | /* 2 | * http://code.google.com/p/cpptask/ 3 | * Copyright (c) 2012, Kirill Kolodyazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_TLSKEY_H_ 29 | #define _CPP_TASK_TLSKEY_H_ 30 | 31 | #include 32 | #include 33 | #include "../exception.h" 34 | 35 | namespace cpptask { namespace internal { 36 | 37 | class TLSKey 38 | { 39 | public: 40 | TLSKey() 41 | { 42 | int err = pthread_key_create(&key, 0); 43 | if (err != 0) 44 | { 45 | throw exception("Can't create a TLS key"); 46 | } 47 | } 48 | 49 | ~TLSKey() 50 | { 51 | if (pthread_key_delete(key) != 0) 52 | { 53 | assert(false); 54 | } 55 | } 56 | 57 | void* GetValue() const 58 | { 59 | return pthread_getspecific(key); 60 | } 61 | 62 | void SetValue(void* value) 63 | { 64 | if (pthread_setspecific(key, value) != 0) 65 | { 66 | throw exception("Can't set a TLS key"); 67 | } 68 | } 69 | 70 | TLSKey(const TLSKey&) = delete; 71 | const TLSKey& operator=(const TLSKey&) = delete; 72 | private: 73 | pthread_key_t key; 74 | }; 75 | 76 | }} 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /include/cpptask/parallelfor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2011, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_PARALLEL_FOR_H_ 29 | #define _CPP_TASK_PARALLEL_FOR_H_ 30 | 31 | #include "range.h" 32 | #include "async.h" 33 | 34 | #include 35 | 36 | namespace cpptask 37 | { 38 | 39 | template 40 | void for_each(Iterator start, Iterator end, Functor functor, int chunksNum = -1) 41 | { 42 | auto& manager = internal::TaskManager::GetCurrent(); 43 | typedef range RangeType; 44 | typedef std::vector Ranges; 45 | Ranges ranges = split_range(start, end, chunksNum > 1 ? static_cast(chunksNum): manager.GetThreadsNum()); 46 | std::vector> futures; 47 | for (const auto& r : ranges) 48 | { 49 | futures.emplace_back(cpptask::async(std::launch::async, [&](const RangeType& range) 50 | { 51 | typename RangeType::value_type i = range.start; 52 | for (; i != range.end; ++i) 53 | { 54 | functor(get_iterator_value(i)); 55 | }; 56 | }, std::cref(r))); 57 | } 58 | //propagate exceptions 59 | for (auto& f : futures) 60 | { 61 | f.get(); 62 | } 63 | } 64 | 65 | } 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /include/cpptask/taskmanager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2011, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_TASKMANAGER_H_ 29 | #define _CPP_TASK_TASKMANAGER_H_ 30 | 31 | #include "spscqueue.h" 32 | #include "tlskey.h" 33 | #include "eventmanager.h" 34 | 35 | namespace cpptask { namespace internal { 36 | 37 | class Task; 38 | class TaskThreadPool; 39 | class Thread; 40 | class TaskThread; 41 | 42 | inline TLSKey& GetManagerKey() 43 | { 44 | static TLSKey managerKey; 45 | return managerKey; 46 | } 47 | 48 | class TaskManager 49 | { 50 | public: 51 | TaskManager(TaskThreadPool& threadPool, EventManager& eventManager, TaskThread* parentThread); 52 | 53 | ~TaskManager(); 54 | 55 | TaskManager(const TaskManager&) = delete; 56 | 57 | TaskManager& operator=(const TaskManager&) = delete; 58 | 59 | size_t GetThreadsNum() const; 60 | 61 | void AddTask(Task& task); 62 | 63 | Task* GetOwnTask(); 64 | 65 | Task* GetTask(); 66 | 67 | static TaskManager& GetCurrent(); 68 | 69 | EventManager& GetEventManager(); 70 | 71 | void RegisterInTLS(); 72 | 73 | void RemoveFromTLS(); 74 | 75 | void WaitTask(Task& waitTask); 76 | 77 | void DoTask(Task& task); 78 | void DoOneTask(); 79 | 80 | private: 81 | TaskThread* parentThread; 82 | TaskThreadPool& threadPool; 83 | SPSCQueue taskQueue; 84 | std::mutex getGuard; 85 | EventManager& eventManager; 86 | }; 87 | 88 | }} 89 | #endif 90 | -------------------------------------------------------------------------------- /include/cpptask/Win/tlskey.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2012, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_TLSKEY_H_ 29 | #define _CPP_TASK_TLSKEY_H_ 30 | 31 | #include "../exception.h" 32 | 33 | #include 34 | #include 35 | #include "winerrmsg.h" 36 | 37 | namespace cpptask { namespace internal { 38 | 39 | class TLSKey 40 | { 41 | public: 42 | TLSKey() 43 | { 44 | tlsIndex = ::TlsAlloc(); 45 | if (tlsIndex == TLS_OUT_OF_INDEXES) 46 | { 47 | throw exception("Can't create a TLS key - " + GetLastWinErrMsg()); 48 | } 49 | } 50 | 51 | ~TLSKey() 52 | { 53 | if (!::TlsFree(tlsIndex)) 54 | { 55 | assert(false); 56 | } 57 | } 58 | 59 | TLSKey(const TLSKey&) = delete; 60 | 61 | const TLSKey& operator=(const TLSKey&) = delete; 62 | 63 | void* GetValue() const 64 | { 65 | void* rez = TlsGetValue(tlsIndex); 66 | if (rez == nullptr && ::GetLastError() != ERROR_SUCCESS) 67 | { 68 | throw exception("Can't get a TLS value - " + GetLastWinErrMsg()); 69 | } 70 | return rez; 71 | } 72 | 73 | void SetValue(void* value) 74 | { 75 | if (!::TlsSetValue(tlsIndex, value)) 76 | { 77 | throw exception("Can't set a TLS value - " + GetLastWinErrMsg()); 78 | } 79 | } 80 | 81 | private: 82 | DWORD tlsIndex; 83 | }; 84 | 85 | }} 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /include/cpptask/eventmanager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2015, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_EVENT_MANGER_H_ 29 | #define _CPP_TASK_EVENT_MANGER_H_ 30 | 31 | #include 32 | 33 | #include 34 | 35 | namespace cpptask { namespace internal { 36 | 37 | enum class EventId : int 38 | { 39 | NoneEvent = -1, 40 | ThreadStopEvent = 0, 41 | NewTaskEvent = 1, 42 | TaskFinishedEvent = 2, 43 | CustomEvent = 3 44 | }; 45 | 46 | class EventManager 47 | { 48 | public: 49 | explicit EventManager() 50 | : count { 0 } 51 | { 52 | } 53 | 54 | EventManager(const EventManager&) = delete; 55 | EventManager& operator=(const EventManager&) = delete; 56 | 57 | void notify(EventId eventId) 58 | { 59 | std::lock_guard lock { guard }; 60 | ++count; 61 | eventQueue.push(eventId); 62 | cv.notify_all(); 63 | } 64 | 65 | template 66 | void wait(Predicate&& predicate) 67 | { 68 | bool done = false; 69 | while (!done) 70 | { 71 | std::unique_lock lock{ guard }; 72 | cv.wait(lock, [&]() {return count > 0; }); 73 | 74 | if (predicate(eventQueue.front())) 75 | { 76 | eventQueue.pop(); 77 | --count; 78 | done = true; 79 | break; 80 | } 81 | else 82 | { 83 | //rotate events to prevent dead-locks 84 | eventQueue.push(eventQueue.front()); 85 | eventQueue.pop(); 86 | cv.notify_all(); 87 | } 88 | } 89 | 90 | } 91 | 92 | private: 93 | size_t count; 94 | std::queue eventQueue; 95 | std::condition_variable cv; 96 | std::mutex guard; 97 | }; 98 | }} 99 | 100 | #endif 101 | 102 | -------------------------------------------------------------------------------- /include/cpptask/taskthreadimpl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2011, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_TASKTHREADIMPL_H_ 29 | #define _CPP_TASK_TASKTHREADIMPL_H_ 30 | 31 | #include "task.h" 32 | #include "taskthread.h" 33 | 34 | #include 35 | 36 | namespace cpptask { namespace internal { 37 | 38 | inline TaskThread::TaskThread(TaskThreadPool& threadPool, EventManager& eventManager) 39 | : eventManager(eventManager) 40 | , taskManager(new TaskManager(threadPool, eventManager, this)) 41 | { 42 | } 43 | 44 | inline TaskThread::~TaskThread() 45 | { 46 | Wait(); 47 | } 48 | 49 | inline void TaskThread::Run() 50 | { 51 | taskManager->RegisterInTLS(); 52 | 53 | bool done = false; 54 | while (!done) 55 | { 56 | Task* task = taskManager->GetTask(); 57 | if (task == nullptr) 58 | { 59 | EventId eventId = EventId::NoneEvent; 60 | eventManager.wait([&eventId](EventId id) 61 | { 62 | eventId = id; 63 | return id == EventId::NewTaskEvent || 64 | id == EventId::ThreadStopEvent; 65 | }); 66 | 67 | if (eventId == EventId::NewTaskEvent) 68 | { 69 | task = taskManager->GetTask(); 70 | } 71 | else if (eventId == EventId::ThreadStopEvent) 72 | { 73 | done = true; 74 | break; 75 | } 76 | else 77 | { 78 | assert(false); 79 | } 80 | } 81 | if (task != nullptr) 82 | { 83 | task->Run(eventManager); 84 | } 85 | } 86 | } 87 | 88 | inline void TaskThread::Start() 89 | { 90 | thread = std::move(std::thread(std::bind(&TaskThread::Run, this))); 91 | } 92 | 93 | inline void TaskThread::Wait() 94 | { 95 | if (thread.joinable()) 96 | { 97 | thread.join(); 98 | } 99 | } 100 | 101 | inline TaskManager& TaskThread::GetTaskManager() 102 | { 103 | return *taskManager; 104 | } 105 | 106 | }} 107 | #endif 108 | -------------------------------------------------------------------------------- /include/cpptask/task.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2011, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_TASK_H_ 29 | #define _CPP_TASK_TASK_H_ 30 | 31 | #include "event.h" 32 | #include "alignedalloc.h" 33 | #include "eventmanager.h" 34 | #include "exception.h" 35 | 36 | #include 37 | 38 | #ifdef _MSC_VER 39 | #pragma warning( push ) 40 | #pragma warning( disable : 4324 ) 41 | #endif 42 | 43 | namespace cpptask { namespace internal { 44 | 45 | // wait for task finished only with TaskManager::WaitTask 46 | class alignas(_CPP_TASK_CACHE_LINE_SIZE_) Task 47 | { 48 | public: 49 | Task() 50 | : isFinished(false) 51 | {} 52 | 53 | virtual ~Task() 54 | { 55 | } 56 | 57 | Task(const Task&) = delete; 58 | 59 | const Task& operator=(const Task&) = delete; 60 | 61 | virtual void Execute() = 0; 62 | 63 | void Run(EventManager& eventManager) 64 | { 65 | if (IsFinished()) 66 | { 67 | throw exception("Task already finished"); 68 | } 69 | 70 | try 71 | { 72 | Execute(); 73 | } 74 | catch(...) 75 | { 76 | lastException = std::current_exception(); 77 | } 78 | isFinished = true; 79 | eventManager.notify(EventId::TaskFinishedEvent); //required for multiple waits 80 | } 81 | 82 | std::exception_ptr GetLastException() const 83 | { 84 | return lastException; 85 | } 86 | 87 | bool IsFinished() 88 | { 89 | return isFinished == true; 90 | } 91 | 92 | void* operator new(size_t size) 93 | { 94 | return aligned_alloc(_CPP_TASK_CACHE_LINE_SIZE_, size); 95 | } 96 | 97 | void operator delete(void* ptr) 98 | { 99 | free(ptr); 100 | } 101 | 102 | void operator delete(void* ptr, size_t) 103 | { 104 | free(ptr); 105 | } 106 | 107 | private: 108 | std::exception_ptr lastException; 109 | std::atomic isFinished; 110 | }; 111 | 112 | }} 113 | 114 | #ifdef _MSC_VER 115 | #pragma warning( pop ) 116 | #endif 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /tests/process_lock_test.cpp: -------------------------------------------------------------------------------- 1 | #include "cpptasktest.h" 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace 10 | { 11 | std::mutex guard; 12 | cpptask::mutex guard2; 13 | cpptask::lockable_event event1; 14 | cpptask::lockable_semaphore sem1(1,2); 15 | 16 | void processFuncLock() 17 | { 18 | std::lock_guard lock(guard); 19 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); 20 | } 21 | void processFuncLockMutex() 22 | { 23 | cpptask::process_lock lock(guard2); //allow use thread for calculations 24 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); 25 | } 26 | void processFuncLockEvent() 27 | { 28 | cpptask::process_lock lock(event1); //allow use thread for calculations 29 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); 30 | } 31 | void processFuncLockSem() 32 | { 33 | cpptask::process_lock lock(sem1); //allow use thread for calculations 34 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); 35 | } 36 | } 37 | 38 | TEST_F(CppTaskTest, ProcessLock_Serial) 39 | { 40 | cpptask::initializer init(1); 41 | 42 | std::unique_lock lock(guard); 43 | auto f1 = cpptask::async(std::launch::async, processFuncLock); 44 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); // additional thread blocked, he stole task 45 | ASSERT_NO_THROW(cpptask::for_each(testArray2.begin(), testArray2.end(), CppTaskTestData::DoubleSqrt(), 4)); //generate more tasks 46 | lock.unlock(); //unlock after second tasks done 47 | 48 | f1.wait(); 49 | 50 | ASSERT_EQ(CppTaskTestData::instance().getResultArray(), testArray); 51 | ASSERT_EQ(CppTaskTestData::instance().getResultArray(), testArray2); 52 | } 53 | 54 | TEST_F(CppTaskTest, ProcessLock_Parallel) 55 | { 56 | cpptask::initializer init(1); 57 | 58 | std::unique_lock lock(guard2); 59 | auto f1 = cpptask::async(std::launch::async, processFuncLockMutex); 60 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); // additional thread blocked, he stole task 61 | ASSERT_NO_THROW(cpptask::for_each(testArray2.begin(), testArray2.end(), CppTaskTestData::DoubleSqrt(), 4)); //generate more tasks 62 | lock.unlock(); //unlock after second tasks done 63 | 64 | f1.wait(); 65 | 66 | ASSERT_EQ(CppTaskTestData::instance().getResultArray(), testArray2); 67 | } 68 | 69 | TEST_F(CppTaskTest, ProcessLock_ParallelEvent) 70 | { 71 | cpptask::initializer init(1); 72 | 73 | auto f1 = cpptask::async(std::launch::async, processFuncLockEvent); 74 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); // additional thread blocked, he stole task 75 | ASSERT_NO_THROW(cpptask::for_each(testArray2.begin(), testArray2.end(), CppTaskTestData::DoubleSqrt(), 4)); //generate more tasks 76 | event1.notify(); //unlock after second tasks done 77 | 78 | f1.wait(); 79 | 80 | ASSERT_EQ(CppTaskTestData::instance().getResultArray(), testArray2); 81 | } 82 | 83 | TEST_F(CppTaskTest, ProcessLock_ParallelSemaphore) 84 | { 85 | cpptask::initializer init(1); 86 | 87 | std::unique_lock lock(sem1); 88 | auto f1 = cpptask::async(std::launch::async, processFuncLockSem); 89 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); // additional thread blocked, he stole task 90 | ASSERT_NO_THROW(cpptask::for_each(testArray2.begin(), testArray2.end(), CppTaskTestData::DoubleSqrt(), 4)); //generate more tasks 91 | lock.unlock(); //unlock after second tasks done 92 | 93 | f1.wait(); 94 | 95 | ASSERT_EQ(CppTaskTestData::instance().getResultArray(), testArray2); 96 | } 97 | -------------------------------------------------------------------------------- /include/cpptask/threadpool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2012, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_THREADPOOL_H_ 29 | #define _CPP_TASK_THREADPOOL_H_ 30 | 31 | #include "eventmanager.h" 32 | #include "taskthread.h" 33 | #include "taskmanager.h" 34 | #include "tlskey.h" 35 | 36 | #include 37 | 38 | namespace cpptask { namespace internal { 39 | 40 | 41 | class TaskThreadPool 42 | { 43 | public: 44 | TaskThreadPool(size_t threadsNum) 45 | { 46 | taskManager.reset(new TaskManager(*this, eventManager, 0)); 47 | taskManager->RegisterInTLS(); 48 | 49 | for (size_t i = 0; i < threadsNum; ++i) 50 | { 51 | TaskThreadPtr tptr(new TaskThread(*this, eventManager)); 52 | threads.push_back(tptr); 53 | } 54 | 55 | //Deffered start required to prevent race in already started threads during stealing new tasks 56 | for (size_t i = 0; i < threadsNum; ++i) 57 | { 58 | threads[i]->Start(); 59 | } 60 | } 61 | 62 | ~TaskThreadPool() 63 | { 64 | for (size_t i = 0; i < threads.size(); ++i) 65 | { 66 | eventManager.notify(cpptask::internal::EventId::ThreadStopEvent); //notify multiple waits 67 | } 68 | for (auto& t : threads) 69 | { 70 | t->Wait(); 71 | } 72 | taskManager->RemoveFromTLS(); 73 | } 74 | 75 | TaskThreadPool(const TaskThreadPool&) = delete; 76 | 77 | const TaskThreadPool& operator=(const TaskThreadPool&) = delete; 78 | 79 | size_t GetThreadsNum() const 80 | { 81 | return threads.size(); 82 | } 83 | 84 | TaskThread* GetThread(size_t index) 85 | { 86 | if (index < threads.size()) 87 | { 88 | return threads[index].get(); 89 | } 90 | return nullptr; 91 | } 92 | 93 | TaskManager& GetTaskManager() 94 | { 95 | return *taskManager; 96 | } 97 | 98 | private: 99 | typedef std::shared_ptr TaskThreadPtr; 100 | typedef std::vector Threads; 101 | Threads threads; 102 | std::unique_ptr taskManager; 103 | EventManager eventManager; 104 | }; 105 | 106 | }} 107 | #endif 108 | -------------------------------------------------------------------------------- /include/cpptask/range.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2011, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_RANGE_H_ 29 | #define _CPP_TASK_RANGE_H_ 30 | 31 | #include 32 | #include 33 | 34 | namespace cpptask 35 | { 36 | 37 | template 38 | class range 39 | { 40 | public: 41 | typedef Iterator value_type; 42 | range(){} 43 | ~range(){} 44 | range(Iterator start, Iterator end) 45 | : start(start) 46 | , end(end) 47 | { 48 | } 49 | size_t Size() 50 | { 51 | return std::distance(start, end); 52 | } 53 | Iterator start; 54 | Iterator end; 55 | }; 56 | 57 | template 58 | typename I::value_type& get_iterator_value(I i) 59 | { 60 | return *i; 61 | } 62 | 63 | template 64 | typename std::enable_if::value,I>::type& get_iterator_value(I& i) 65 | { 66 | return i; 67 | } 68 | 69 | namespace internal { 70 | template 71 | std::vector > SplitRangeBase(Iterator start, Iterator end, Diff rangeLen, size_t rangesNum) 72 | { 73 | typedef range RANGE; 74 | if (rangesNum != 0) 75 | { 76 | rangeLen /= rangesNum; 77 | } 78 | std::vector ranges; 79 | ranges.reserve(rangesNum); 80 | if (rangesNum > 1) 81 | { 82 | for(size_t i = 0; i < rangesNum; ++i) 83 | { 84 | ranges.push_back(RANGE(start + (i * rangeLen), 85 | start + (i * rangeLen) + rangeLen)); 86 | } 87 | ranges[rangesNum - 1].end = end; 88 | } 89 | else 90 | { 91 | ranges.push_back(RANGE(start, end)); 92 | } 93 | return ranges; 94 | } 95 | } 96 | 97 | template 98 | std::vector > split_range(Iterator start, Iterator end, size_t rangesNum) 99 | { 100 | return internal::SplitRangeBase(start, end, std::distance(start, end), rangesNum); 101 | } 102 | 103 | template 104 | std::vector > split_num_range(Iterator start, Iterator end, size_t rangesNum) 105 | { 106 | assert(start <= end); 107 | return internal::SplitRangeBase(start, end, end - start, rangesNum); 108 | } 109 | 110 | } 111 | #endif 112 | -------------------------------------------------------------------------------- /include/cpptask/event.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2011, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_EVENT_H_ 29 | #define _CPP_TASK_EVENT_H_ 30 | 31 | #include "taskmanager.h" 32 | 33 | #include 34 | 35 | namespace cpptask 36 | { 37 | 38 | class event 39 | { 40 | public: 41 | 42 | event() noexcept 43 | : signaled(false) 44 | {} 45 | 46 | ~event() 47 | {} 48 | 49 | event(const event&) = delete; 50 | const event& operator=(const event&) = delete; 51 | 52 | void notify() 53 | { 54 | std::lock_guard lock(guard); 55 | signaled = true; 56 | cv.notify_all(); 57 | } 58 | 59 | void wait() 60 | { 61 | std::unique_lock lock(guard); 62 | cv.wait(lock, [&] {return signaled; }); 63 | signaled = false; 64 | } 65 | 66 | bool check() 67 | { 68 | std::unique_lock lock(guard); 69 | if (cv.wait_for(lock, std::chrono::milliseconds(0), [&] {return signaled; })) 70 | { 71 | signaled = false; 72 | cv.notify_all(); 73 | return true; 74 | } 75 | return false; 76 | } 77 | 78 | private: 79 | std::condition_variable cv; 80 | std::mutex guard; 81 | bool signaled; 82 | }; 83 | 84 | //use this class only if you have corresponding process_lock object 85 | class lockable_event 86 | { 87 | public: 88 | typedef internal::EventManager EventManagerType; 89 | 90 | lockable_event() noexcept 91 | {} 92 | 93 | ~lockable_event() 94 | {} 95 | 96 | lockable_event(const lockable_event&) = delete; 97 | const lockable_event& operator=(const lockable_event&) = delete; 98 | 99 | void notify() 100 | { 101 | evt.notify(); 102 | internal::TaskManager::GetCurrent().GetEventManager().notify(internal::EventId::CustomEvent); 103 | } 104 | 105 | void lock() 106 | { 107 | evt.wait(); 108 | } 109 | 110 | void unlock() 111 | { 112 | //do nothing 113 | } 114 | 115 | bool try_lock() 116 | { 117 | return evt.check(); 118 | } 119 | 120 | private: 121 | event evt; 122 | }; 123 | 124 | } 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /include/cpptask/processlock.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2015, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_PROCESS_LOCK_H_ 29 | #define _CPP_TASK_PROCESS_LOCK_H_ 30 | 31 | #include "async.h" 32 | #include "eventmanager.h" 33 | 34 | namespace cpptask 35 | { 36 | template 37 | class process_lock 38 | {}; 39 | 40 | template 41 | class process_lock::value>::type> 42 | { 43 | public: 44 | process_lock(SyncPrimitive& _guard) 45 | : guardLock(_guard, std::defer_lock) 46 | { 47 | auto f = cpptask::async(std::launch::async, 48 | [this]() 49 | { 50 | auto& taskManager = internal::TaskManager::GetCurrent(); 51 | auto& eventManager = taskManager.GetEventManager(); 52 | 53 | bool done = false; 54 | while(!done) 55 | { 56 | internal::EventId eventId = internal::EventId::NoneEvent; 57 | eventManager.wait([&eventId](internal::EventId id) 58 | { 59 | eventId = id; 60 | return id == internal::EventId::NewTaskEvent || 61 | id == internal::EventId::CustomEvent; 62 | }); 63 | 64 | if (eventId == internal::EventId::NewTaskEvent) 65 | { 66 | taskManager.DoOneTask(); 67 | } 68 | else if (eventId == internal::EventId::CustomEvent) 69 | { 70 | done = guardLock.try_lock(); 71 | break; 72 | } 73 | else 74 | { 75 | assert(false); 76 | } 77 | } 78 | }); 79 | f.get(); 80 | } 81 | 82 | ~process_lock() 83 | { 84 | if (guardLock) 85 | { 86 | guardLock.unlock(); 87 | } 88 | } 89 | 90 | process_lock(const process_lock&) = delete; 91 | process_lock& operator=(const process_lock&) = delete; 92 | private: 93 | std::unique_lock guardLock; 94 | }; 95 | 96 | } 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /include/cpptask/parallelreduce.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2011, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_PARALLEL_REDUCE_H_ 29 | #define _CPP_TASK_PARALLEL_REDUCE_H_ 30 | 31 | #include "taskmanager.h" 32 | #include "range.h" 33 | 34 | namespace cpptask 35 | { 36 | 37 | namespace internal 38 | { 39 | template 40 | ReturnType reduceFunc(ProcessFunction&& process, JoinFunction&& join, const Range& range, size_t depth, size_t width) 41 | { 42 | if (depth > 0) //we can split more 43 | { 44 | assert(width >= 2); 45 | const size_t splitCount = (std::max)(size_t(2), width); 46 | std::vector ranges = split_range(range.start, range.end, splitCount); 47 | std::vector> futures; 48 | for (size_t i = 0; i < splitCount; ++i) //put tasks to queue - they can be calculated in parallel 49 | { 50 | futures.emplace_back(cpptask::async(std::launch::async, 51 | [&, i]() 52 | { 53 | return reduceFunc(std::forward(process), std::forward(join), ranges[i], depth - 1, width); 54 | })); 55 | } 56 | //wait results 57 | ReturnType result = futures.front().get(); 58 | std::for_each(std::next(futures.begin()), futures.end(), 59 | [&](future& f) 60 | { 61 | result = join(result, f.get()); 62 | }); 63 | return result; 64 | } 65 | else //stop spliting - calculate 66 | { 67 | return process(range); 68 | } 69 | }; 70 | } 71 | 72 | template 73 | ReturnType reduce(Iterator start, Iterator end, ProcessFunction&& process, JoinFunction&& join, size_t depth = 5, size_t width = 2) 74 | { 75 | typedef range RangeType; 76 | 77 | RangeType range(start, end); 78 | 79 | auto f = cpptask::async(std::launch::async, 80 | [&]() 81 | { 82 | return internal::reduceFunc(std::forward(process), std::forward(join), range, depth, width); 83 | }); 84 | return f.get(); 85 | } 86 | 87 | } 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /include/cpptask/semaphor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2012, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_SEMAPHORE_H_ 29 | #define _CPP_TASK_SEMAPHORE_H_ 30 | 31 | #include "taskmanager.h" 32 | 33 | #include 34 | 35 | namespace cpptask 36 | { 37 | class semaphore 38 | { 39 | public: 40 | explicit semaphore(int n = 0, int max = -1) 41 | : maxCount { max } 42 | , count{ n } 43 | {} 44 | 45 | semaphore(const semaphore&) = delete; 46 | 47 | semaphore& operator=(const semaphore&) = delete; 48 | 49 | void unlock() 50 | { 51 | std::lock_guard lock{ guard }; 52 | if ((maxCount > 0 && count < maxCount) || 53 | maxCount <= 0) 54 | { 55 | ++count; 56 | cv.notify_one(); 57 | } 58 | } 59 | 60 | void lock() 61 | { 62 | std::unique_lock lock{ guard }; 63 | cv.wait(lock, [&] { return count > 0; }); 64 | --count; 65 | } 66 | 67 | bool try_lock() 68 | { 69 | std::unique_lock lock{ guard }; 70 | if (cv.wait_for(lock, std::chrono::milliseconds(0), [&] { return count > 0; })) 71 | { 72 | --count; 73 | return true; 74 | } 75 | return false; 76 | } 77 | 78 | private: 79 | int maxCount; 80 | int count; 81 | std::condition_variable cv; 82 | std::mutex guard; 83 | }; 84 | 85 | //use this class only if you have corresponding process_lock object 86 | class lockable_semaphore 87 | { 88 | public: 89 | typedef internal::EventManager EventManagerType; 90 | 91 | explicit lockable_semaphore(int n = 0, int max = -1) noexcept 92 | : sem(n, max) 93 | {} 94 | 95 | ~lockable_semaphore() 96 | {} 97 | 98 | lockable_semaphore(const lockable_semaphore&) = delete; 99 | const lockable_semaphore& operator=(const lockable_semaphore&) = delete; 100 | 101 | void lock() 102 | { 103 | sem.lock(); 104 | } 105 | 106 | void unlock() 107 | { 108 | sem.unlock(); 109 | internal::TaskManager::GetCurrent().GetEventManager().notify(internal::EventId::CustomEvent); 110 | } 111 | 112 | bool try_lock() 113 | { 114 | return sem.try_lock(); 115 | } 116 | 117 | private: 118 | semaphore sem; 119 | }; 120 | } 121 | #endif 122 | -------------------------------------------------------------------------------- /3rdparty/gtest/src/gtest-typed-test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008 Google Inc. 2 | // All Rights Reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | 32 | #include "gtest/gtest-typed-test.h" 33 | #include "gtest/gtest.h" 34 | 35 | namespace testing { 36 | namespace internal { 37 | 38 | #if GTEST_HAS_TYPED_TEST_P 39 | 40 | // Skips to the first non-space char in str. Returns an empty string if str 41 | // contains only whitespace characters. 42 | static const char* SkipSpaces(const char* str) { 43 | while (IsSpace(*str)) 44 | str++; 45 | return str; 46 | } 47 | 48 | // Verifies that registered_tests match the test names in 49 | // defined_test_names_; returns registered_tests if successful, or 50 | // aborts the program otherwise. 51 | const char* TypedTestCasePState::VerifyRegisteredTestNames( 52 | const char* file, int line, const char* registered_tests) { 53 | typedef ::std::set::const_iterator DefinedTestIter; 54 | registered_ = true; 55 | 56 | // Skip initial whitespace in registered_tests since some 57 | // preprocessors prefix stringizied literals with whitespace. 58 | registered_tests = SkipSpaces(registered_tests); 59 | 60 | Message errors; 61 | ::std::set tests; 62 | for (const char* names = registered_tests; names != NULL; 63 | names = SkipComma(names)) { 64 | const std::string name = GetPrefixUntilComma(names); 65 | if (tests.count(name) != 0) { 66 | errors << "Test " << name << " is listed more than once.\n"; 67 | continue; 68 | } 69 | 70 | bool found = false; 71 | for (DefinedTestIter it = defined_test_names_.begin(); 72 | it != defined_test_names_.end(); 73 | ++it) { 74 | if (name == *it) { 75 | found = true; 76 | break; 77 | } 78 | } 79 | 80 | if (found) { 81 | tests.insert(name); 82 | } else { 83 | errors << "No test named " << name 84 | << " can be found in this test case.\n"; 85 | } 86 | } 87 | 88 | for (DefinedTestIter it = defined_test_names_.begin(); 89 | it != defined_test_names_.end(); 90 | ++it) { 91 | if (tests.count(*it) == 0) { 92 | errors << "You forgot to list test " << *it << ".\n"; 93 | } 94 | } 95 | 96 | const std::string& errors_str = errors.GetString(); 97 | if (errors_str != "") { 98 | fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), 99 | errors_str.c_str()); 100 | fflush(stderr); 101 | posix::Abort(); 102 | } 103 | 104 | return registered_tests; 105 | } 106 | 107 | #endif // GTEST_HAS_TYPED_TEST_P 108 | 109 | } // namespace internal 110 | } // namespace testing 111 | -------------------------------------------------------------------------------- /3rdparty/gtest/src/gtest-test-part.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: mheule@google.com (Markus Heule) 31 | // 32 | // The Google C++ Testing Framework (Google Test) 33 | 34 | #include "gtest/gtest-test-part.h" 35 | 36 | // Indicates that this translation unit is part of Google Test's 37 | // implementation. It must come before gtest-internal-inl.h is 38 | // included, or there will be a compiler error. This trick is to 39 | // prevent a user from accidentally including gtest-internal-inl.h in 40 | // his code. 41 | #define GTEST_IMPLEMENTATION_ 1 42 | #include "src/gtest-internal-inl.h" 43 | #undef GTEST_IMPLEMENTATION_ 44 | 45 | namespace testing { 46 | 47 | using internal::GetUnitTestImpl; 48 | 49 | // Gets the summary of the failure message by omitting the stack trace 50 | // in it. 51 | std::string TestPartResult::ExtractSummary(const char* message) { 52 | const char* const stack_trace = strstr(message, internal::kStackTraceMarker); 53 | return stack_trace == NULL ? message : 54 | std::string(message, stack_trace); 55 | } 56 | 57 | // Prints a TestPartResult object. 58 | std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { 59 | return os 60 | << result.file_name() << ":" << result.line_number() << ": " 61 | << (result.type() == TestPartResult::kSuccess ? "Success" : 62 | result.type() == TestPartResult::kFatalFailure ? "Fatal failure" : 63 | "Non-fatal failure") << ":\n" 64 | << result.message() << std::endl; 65 | } 66 | 67 | // Appends a TestPartResult to the array. 68 | void TestPartResultArray::Append(const TestPartResult& result) { 69 | array_.push_back(result); 70 | } 71 | 72 | // Returns the TestPartResult at the given index (0-based). 73 | const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { 74 | if (index < 0 || index >= size()) { 75 | printf("\nInvalid index (%d) into TestPartResultArray.\n", index); 76 | internal::posix::Abort(); 77 | } 78 | 79 | return array_[index]; 80 | } 81 | 82 | // Returns the number of TestPartResult objects in the array. 83 | int TestPartResultArray::size() const { 84 | return static_cast(array_.size()); 85 | } 86 | 87 | namespace internal { 88 | 89 | HasNewFatalFailureHelper::HasNewFatalFailureHelper() 90 | : has_new_fatal_failure_(false), 91 | original_reporter_(GetUnitTestImpl()-> 92 | GetTestPartResultReporterForCurrentThread()) { 93 | GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this); 94 | } 95 | 96 | HasNewFatalFailureHelper::~HasNewFatalFailureHelper() { 97 | GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread( 98 | original_reporter_); 99 | } 100 | 101 | void HasNewFatalFailureHelper::ReportTestPartResult( 102 | const TestPartResult& result) { 103 | if (result.fatally_failed()) 104 | has_new_fatal_failure_ = true; 105 | original_reporter_->ReportTestPartResult(result); 106 | } 107 | 108 | } // namespace internal 109 | 110 | } // namespace testing 111 | -------------------------------------------------------------------------------- /tests/spsc_queue_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace 13 | { 14 | #if defined(_DEBUG) || defined(DEBUG) 15 | template 16 | std::string queueToString(const cpptask::SPSCQueue& queue) 17 | { 18 | std::string qs; 19 | 20 | queue.Iterate([&qs](T val, bool isHead, bool isTail, bool isCacheStart, bool isCacheMid) 21 | { 22 | qs += "["; 23 | if (isHead) 24 | { 25 | qs += "H "; 26 | } 27 | if (isTail) 28 | { 29 | qs += "T "; 30 | } 31 | if (isCacheStart) 32 | { 33 | qs += "CS "; 34 | } 35 | if (isCacheMid) 36 | { 37 | qs += "CM "; 38 | } 39 | qs += ": " + std::to_string(val); 40 | qs += "] "; 41 | }); 42 | 43 | return qs; 44 | } 45 | #endif 46 | } 47 | 48 | TEST(SPSCTest, PushPop) 49 | { 50 | cpptask::internal::SPSCQueue queue; 51 | 52 | queue.Enqueue(1); 53 | queue.Enqueue(2); 54 | queue.Enqueue(3); 55 | 56 | int x = 0; 57 | 58 | ASSERT_TRUE(queue.Dequeue(x)); 59 | ASSERT_EQ(1, x); 60 | 61 | ASSERT_TRUE(queue.Dequeue(x)); 62 | ASSERT_EQ(2, x); 63 | 64 | queue.Enqueue(4); 65 | 66 | ASSERT_TRUE(queue.Dequeue(x)); 67 | ASSERT_EQ(3, x); 68 | 69 | ASSERT_TRUE(queue.Dequeue(x)); 70 | ASSERT_EQ(4, x); 71 | 72 | ASSERT_FALSE(queue.Dequeue(x)); 73 | } 74 | 75 | #if defined(_DEBUG) || defined(DEBUG) 76 | TEST(SPSCTest, Structure) 77 | { 78 | cpptask::internal::SPSCQueue queue(-1); 79 | 80 | queue.Enqueue(1); 81 | queue.Enqueue(2); 82 | queue.Enqueue(3); 83 | queue.Enqueue(4); 84 | 85 | ASSERT_EQ("[H CS CM : -1] [: 1] [: 2] [: 3] [T : 4] ", queueToString(queue)); 86 | 87 | int x = 0; 88 | 89 | ASSERT_TRUE(queue.Dequeue(x)); 90 | ASSERT_EQ(1, x); 91 | 92 | ASSERT_EQ("[CS CM : -1] [H : 1] [: 2] [: 3] [T : 4] ", queueToString(queue)); 93 | 94 | ASSERT_TRUE(queue.Dequeue(x)); 95 | ASSERT_EQ(2, x); 96 | 97 | ASSERT_EQ("[CS CM : -1] [: 1] [H : 2] [: 3] [T : 4] ", queueToString(queue)); 98 | 99 | ASSERT_TRUE(queue.Dequeue(x)); 100 | ASSERT_EQ(3, x); 101 | 102 | ASSERT_EQ("[CS CM : -1] [: 1] [: 2] [H : 3] [T : 4] ", queueToString(queue)); 103 | 104 | queue.Enqueue(5); 105 | 106 | ASSERT_EQ("[CS : 1] [: 2] [H CM : 3] [: 4] [T : 5] ", queueToString(queue)); 107 | 108 | queue.Enqueue(6); //first part of AllocNode works 109 | 110 | ASSERT_EQ("[CS : 2] [H CM : 3] [: 4] [: 5] [T : 6] ", queueToString(queue)); 111 | 112 | ASSERT_TRUE(queue.Dequeue(x)); 113 | ASSERT_EQ(4, x); 114 | 115 | ASSERT_EQ("[CS : 2] [CM : 3] [H : 4] [: 5] [T : 6] ", queueToString(queue)); 116 | 117 | ASSERT_TRUE(queue.Dequeue(x)); 118 | ASSERT_EQ(5, x); 119 | 120 | ASSERT_EQ("[CS : 2] [CM : 3] [: 4] [H : 5] [T : 6] ", queueToString(queue)); 121 | 122 | queue.Enqueue(7); //first part of AllocNode works 123 | 124 | ASSERT_EQ("[CS CM : 3] [: 4] [H : 5] [: 6] [T : 7] ", queueToString(queue)); 125 | } 126 | #endif 127 | 128 | TEST(SPSCTest, Parallel) 129 | { 130 | cpptask::internal::SPSCQueue queue; 131 | const int N = 1000; 132 | 133 | std::random_device rd; 134 | std::mt19937 gen(rd()); 135 | std::uniform_int_distribution<> dis(0, 20); 136 | 137 | std::mutex m; 138 | std::condition_variable cv; 139 | bool producerFinished = false; 140 | 141 | std::thread producerThread([&]() 142 | { 143 | for (int i = 0; i < N; ++i) 144 | { 145 | queue.Enqueue(i); 146 | std::this_thread::sleep_for(std::chrono::milliseconds(dis(gen))); 147 | } 148 | std::unique_lock lk(m); 149 | producerFinished = true; 150 | cv.notify_one(); 151 | }); 152 | 153 | std::vector x; 154 | x.reserve(N); 155 | auto inserter = std::back_inserter(x); 156 | 157 | std::thread consumerThread([&]() 158 | { 159 | bool done = false; 160 | while (!done) 161 | { 162 | { 163 | std::unique_lock lk(m); 164 | done = cv.wait_for(lk, std::chrono::milliseconds(5), [&] {return producerFinished; }); 165 | } 166 | 167 | int x = 0; 168 | while (queue.Dequeue(x)) 169 | { 170 | *inserter = x; 171 | ++inserter; 172 | } 173 | } 174 | }); 175 | 176 | producerThread.join(); 177 | consumerThread.join(); 178 | 179 | ASSERT_EQ(N, static_cast(x.size())); 180 | 181 | for (int i = 0; i < N; ++i) 182 | { 183 | ASSERT_EQ(i, x[i]); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /include/cpptask/taskmanagerlimpl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2012, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_TASKMANAGERIMPL_H_ 29 | #define _CPP_TASK_TASKMANAGERIMPL_H_ 30 | 31 | #include "taskmanager.h" 32 | #include "threadpool.h" 33 | 34 | #include 35 | 36 | namespace cpptask { namespace internal { 37 | 38 | inline TaskManager::TaskManager(TaskThreadPool& threadPool, EventManager& eventManager, TaskThread* parentThread) 39 | : parentThread(parentThread) 40 | , threadPool(threadPool) 41 | , eventManager(eventManager) 42 | { 43 | } 44 | 45 | inline TaskManager::~TaskManager() 46 | { 47 | } 48 | 49 | inline size_t TaskManager::GetThreadsNum() const 50 | { 51 | return threadPool.GetThreadsNum(); 52 | } 53 | 54 | inline void TaskManager::AddTask(Task& task) 55 | { 56 | taskQueue.Enqueue(&task); 57 | eventManager.notify(EventId::NewTaskEvent); 58 | } 59 | 60 | inline Task* TaskManager::GetOwnTask() 61 | { 62 | Task* res = nullptr; 63 | std::unique_lock lock(getGuard, std::try_to_lock); 64 | if (lock) 65 | { 66 | if (!taskQueue.Dequeue(res)) 67 | { 68 | res = nullptr; 69 | } 70 | } 71 | return res; 72 | } 73 | 74 | inline Task* TaskManager::GetTask() 75 | { 76 | Task* res = GetOwnTask(); 77 | if (res == nullptr) 78 | { 79 | res = threadPool.GetTaskManager().GetOwnTask(); 80 | if (res == nullptr) 81 | { 82 | for (size_t i = 0; i < threadPool.GetThreadsNum(); ++i) 83 | { 84 | TaskThread* thread = threadPool.GetThread(i); 85 | assert(thread != nullptr); 86 | if (thread != parentThread) 87 | { 88 | res = thread->GetTaskManager().GetOwnTask(); 89 | if (res != nullptr) 90 | { 91 | break; 92 | } 93 | } 94 | } 95 | } 96 | } 97 | return res; 98 | } 99 | 100 | inline TaskManager& TaskManager::GetCurrent() 101 | { 102 | void* pvalue = GetManagerKey().GetValue(); 103 | if (pvalue != nullptr) 104 | { 105 | return *reinterpret_cast(pvalue); 106 | } 107 | else 108 | { 109 | throw exception("Can't acquire current task manager"); 110 | } 111 | } 112 | 113 | inline EventManager& TaskManager::GetEventManager() 114 | { 115 | return eventManager; 116 | } 117 | 118 | inline void TaskManager::RegisterInTLS() 119 | { 120 | GetManagerKey().SetValue(this); 121 | } 122 | 123 | inline void TaskManager::RemoveFromTLS() 124 | { 125 | GetManagerKey().SetValue(nullptr); 126 | } 127 | 128 | inline void TaskManager::DoOneTask() 129 | { 130 | Task* task = GetTask(); 131 | if (task != nullptr) 132 | { 133 | DoTask(*task); 134 | } 135 | } 136 | 137 | inline void TaskManager::DoTask(Task& task) 138 | { 139 | task.Run(eventManager); 140 | } 141 | 142 | inline void TaskManager::WaitTask(Task& waitTask) 143 | { 144 | bool done {false}; 145 | while (!done) 146 | { 147 | Task* task = GetTask(); 148 | if (task == nullptr) 149 | { 150 | EventId eventId = EventId::NoneEvent; 151 | eventManager.wait([&](EventId id) 152 | { 153 | eventId = id; 154 | return id == EventId::NewTaskEvent || 155 | (id == EventId::TaskFinishedEvent && waitTask.IsFinished()); 156 | }); 157 | 158 | if (eventId == EventId::NewTaskEvent) 159 | { 160 | task = GetTask(); 161 | } 162 | else if(eventId == EventId::TaskFinishedEvent) 163 | { 164 | done = true; 165 | break; 166 | } 167 | else 168 | { 169 | assert(false); 170 | } 171 | } 172 | 173 | if (task != nullptr) 174 | { 175 | task->Run(eventManager); 176 | } 177 | } 178 | } 179 | 180 | }} 181 | #endif 182 | -------------------------------------------------------------------------------- /include/cpptask/spscqueue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2012, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | //Idea taken from http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue 29 | 30 | #ifndef _CPP_TASK_SPSCQUEUE_H_ 31 | #define _CPP_TASK_SPSCQUEUE_H_ 32 | 33 | #include 34 | #include 35 | 36 | namespace cpptask { namespace internal { 37 | 38 | template 39 | class SPSCQueue 40 | { 41 | public: 42 | 43 | #if defined(_DEBUG) || defined(DEBUG) 44 | SPSCQueue(T defaultValue) 45 | { 46 | Node* n = new Node; 47 | n->value = defaultValue; 48 | n->next.store(nullptr, std::memory_order_relaxed); 49 | head.store(n, std::memory_order_relaxed); 50 | tail = n; 51 | cache_start = cache_mid = n; 52 | } 53 | #endif 54 | 55 | SPSCQueue() 56 | { 57 | Node* n = new Node(); 58 | n->next.store(nullptr, std::memory_order_relaxed); 59 | head.store(n, std::memory_order_relaxed); 60 | tail = n; 61 | cache_start = cache_mid = n; 62 | } 63 | 64 | ~SPSCQueue() 65 | { 66 | Node* n = cache_start; 67 | do 68 | { 69 | Node* next = n->next.load(std::memory_order_relaxed); 70 | delete n; 71 | n = next; 72 | } 73 | while (n != nullptr); 74 | } 75 | 76 | SPSCQueue(SPSCQueue const&) = delete; 77 | 78 | SPSCQueue& operator = (SPSCQueue const&) = delete; 79 | 80 | #if defined(_DEBUG) || defined(DEBUG) 81 | //not thread safe - for testing purposes 82 | template 83 | void Iterate(IF func) const 84 | { 85 | auto h = head.load(std::memory_order_relaxed); 86 | 87 | Node* n = cache_start; 88 | do 89 | { 90 | func(n->value, n == h, n == tail, n == cache_start, n == cache_mid); 91 | Node* next = n->next.load(std::memory_order_relaxed); 92 | n = next; 93 | } while (n != nullptr); 94 | } 95 | #endif 96 | 97 | void Enqueue(T v) 98 | { 99 | Node* n = AllocNode(); 100 | n->next = nullptr; 101 | n->value = v; 102 | tail->next.store(n, std::memory_order_release); 103 | tail = n; 104 | } 105 | 106 | bool Dequeue(T& v) 107 | { 108 | auto h = head.load(std::memory_order_acquire); 109 | auto h_next = h->next.load(std::memory_order_acquire); 110 | if (h_next != nullptr) 111 | { 112 | v = h_next->value; 113 | head.store(h_next, std::memory_order_release); 114 | return true; 115 | } 116 | else 117 | { 118 | return false; 119 | } 120 | } 121 | 122 | private: 123 | // internal node structure 124 | struct Node 125 | { 126 | std::atomic next; 127 | T value; 128 | }; 129 | 130 | Node* AllocNode() 131 | { 132 | // cache_start tries to allocate node from internal node cache, 133 | // if attempt fails, allocates node via ::operator new() 134 | 135 | if (cache_start != cache_mid) 136 | { 137 | Node* n = cache_start; 138 | cache_start = cache_start->next.load(std::memory_order_acquire); 139 | return n; 140 | } 141 | 142 | cache_mid = head.load(std::memory_order_acquire); 143 | 144 | if (cache_start != cache_mid) 145 | { 146 | Node* n = cache_start; 147 | cache_start = cache_start->next.load(std::memory_order_acquire); 148 | return n; 149 | } 150 | Node* n = new Node; 151 | return n; 152 | } 153 | 154 | // consumer part 155 | // accessed mainly by consumer, infrequently be producer 156 | std::atomic head; // head of the queue 157 | 158 | // delimiter between consumer part and producer part, 159 | // so that they situated on different cache lines 160 | char cache_line_pad[_CPP_TASK_CACHE_LINE_SIZE_]; 161 | 162 | // producer part 163 | // accessed only by producer 164 | Node* tail; // tail of the queue 165 | Node* cache_start; // first unused node (head of node cache) 166 | Node* cache_mid; // points somewhere between cache_start and head - minimize accesses to the head node during allocation 167 | }; 168 | 169 | }} 170 | 171 | #endif 172 | 173 | -------------------------------------------------------------------------------- /include/cpptask/async.h: -------------------------------------------------------------------------------- 1 | /* 2 | * https://github.com/Kolkir/cpptask/ 3 | * Copyright (c) 2015, Kyrylo Kolodiazhnyi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CPP_TASK_ASYNC_H_ 29 | #define _CPP_TASK_ASYNC_H_ 30 | 31 | #include 32 | #include 33 | 34 | namespace cpptask 35 | { 36 | template 37 | class future 38 | { 39 | public: 40 | future() noexcept 41 | {} 42 | 43 | //contructor for internal use only 44 | future(std::unique_ptr task, std::future f, bool deffered) noexcept 45 | : task(std::move(task)) 46 | , realFuture(std::move(f)) 47 | , deffered(deffered) 48 | {} 49 | 50 | future(future&& f) 51 | : task(std::move(f.task)) 52 | , realFuture(std::move(f.realFuture)) 53 | , deffered(f.deffered) 54 | {} 55 | 56 | future(const future& rhs) = delete; 57 | 58 | future& operator=(const future& rhs) = delete; 59 | 60 | ~future() 61 | {} 62 | 63 | future& operator=(future&& f) noexcept 64 | { 65 | task = std::move(f.task); 66 | realFuture = std::move(f.realFuture); 67 | deffered = f.deffered; 68 | } 69 | 70 | R get() 71 | { 72 | auto& manager = internal::TaskManager::GetCurrent(); 73 | if (deffered) 74 | { 75 | manager.DoTask(*task); 76 | return realFuture.get(); 77 | } 78 | else 79 | { 80 | if (!task->IsFinished()) 81 | { 82 | manager.WaitTask(*task); 83 | } 84 | return realFuture.get(); 85 | } 86 | } 87 | 88 | bool valid() const noexcept 89 | { 90 | return realFuture.valid(); 91 | } 92 | 93 | void wait() const 94 | { 95 | if (!task->IsFinished()) 96 | { 97 | if (!deffered) 98 | { 99 | auto& manager = internal::TaskManager::GetCurrent(); 100 | manager.WaitTask(*task); 101 | } 102 | } 103 | } 104 | 105 | template 106 | std::future_status wait_for(const std::chrono::duration& rel_time) const 107 | { 108 | return realFuture.wait_for(rel_time); 109 | } 110 | 111 | template 112 | std::future_status wait_until(const std::chrono::time_point& abs_time) const 113 | { 114 | return realFuture.wait_until(abs_time); 115 | } 116 | 117 | private: 118 | std::unique_ptr task; 119 | std::future realFuture; 120 | bool deffered; 121 | }; 122 | 123 | namespace internal 124 | { 125 | template 126 | class AsyncTask : public Task 127 | { 128 | public: 129 | AsyncTask(Functor&& functor) 130 | : functor(std::forward(functor)) 131 | { 132 | } 133 | ~AsyncTask() 134 | { 135 | } 136 | virtual void Execute() 137 | { 138 | functor(); 139 | } 140 | private: 141 | Functor functor; 142 | }; 143 | } 144 | 145 | template< class Function, class... Args > 146 | future::type> async(std::launch policy, Function&& f, Args&&... args) 147 | { 148 | std::packaged_task ::type()> job(std::bind(std::forward(f), std::forward(args)...)); 149 | auto res = job.get_future(); 150 | std::unique_ptr task(new internal::AsyncTask(std::move(job))); 151 | 152 | if (policy == std::launch::deferred) 153 | { 154 | return future::type>(std::move(task), std::move(res), true); 155 | } 156 | else if (policy == std::launch::async) 157 | { 158 | auto& manager = internal::TaskManager::GetCurrent(); 159 | manager.AddTask(*task); 160 | return future::type>(std::move(task), std::move(res), false); 161 | } 162 | else 163 | { 164 | throw exception("Wrong launch policy for async"); 165 | } 166 | } 167 | } 168 | 169 | #endif 170 | -------------------------------------------------------------------------------- /tests/event_manager_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace 10 | { 11 | std::mutex ioGuard; 12 | 13 | template 14 | void writeLog(T&& val) 15 | { 16 | std::cout << std::forward(val); 17 | } 18 | 19 | template 20 | void writeLog(T&& val, Ts&&... vals) 21 | { 22 | writeLog(std::forward(val)); 23 | writeLog(std::forward(vals)...); 24 | } 25 | 26 | template 27 | void log(T&& val, Ts&&... vals) 28 | { 29 | #if defined(_DEBUG) || defined(DEBUG) 30 | std::lock_guard lock(ioGuard); 31 | writeLog(std::forward(val), std::forward(vals)...); 32 | std::cout.flush(); 33 | #endif 34 | } 35 | } 36 | 37 | TEST(EventManagerTest, SendWait) 38 | { 39 | cpptask::internal::EventManager mngr; 40 | 41 | const int N = 10; 42 | 43 | for (int i = 0; i < N; ++i) 44 | { 45 | std::vector> waits; 46 | log("session start\n"); 47 | for (int j = 0; j < 2; ++j) 48 | { 49 | waits.emplace_back(std::async(std::launch::async, [&mngr] 50 | { 51 | mngr.notify(cpptask::internal::EventId::NewTaskEvent); 52 | log("sent NewTask, waiting ThreadStop ", std::this_thread::get_id(), "\n"); 53 | mngr.wait([](cpptask::internal::EventId eventId) 54 | { 55 | return eventId == cpptask::internal::EventId::ThreadStopEvent; 56 | }); 57 | log("ThreadStop received ", std::this_thread::get_id(), "\n"); 58 | })); 59 | } 60 | for (int j = 0; j < 2; ++j) 61 | { 62 | waits.emplace_back(std::async(std::launch::async, [&mngr] 63 | { 64 | log("waiting NewTask ", std::this_thread::get_id(), "\n"); 65 | mngr.wait([](cpptask::internal::EventId eventId) 66 | { 67 | return eventId == cpptask::internal::EventId::NewTaskEvent; 68 | }); 69 | mngr.notify(cpptask::internal::EventId::ThreadStopEvent); 70 | log("sent ThreadStop ", std::this_thread::get_id(), "\n"); 71 | })); 72 | } 73 | 74 | for (auto& f : waits) 75 | { 76 | f.get(); 77 | } 78 | 79 | log("\n"); 80 | } 81 | } 82 | 83 | TEST(EventManagerTest, SendWaitBroadcast) 84 | { 85 | cpptask::internal::EventManager mngr; 86 | 87 | const int N = 10; 88 | 89 | for (int i = 0; i < N; ++i) 90 | { 91 | std::vector> waits; 92 | log("session start\n"); 93 | const int nt = 3; 94 | waits.emplace_back(std::async(std::launch::async, [&nt,&mngr] 95 | { 96 | for (int t = 0; t < nt; ++t) 97 | { 98 | mngr.notify(cpptask::internal::EventId::NewTaskEvent); 99 | log("sent ", static_cast(cpptask::internal::EventId::NewTaskEvent), " ", std::this_thread::get_id(), "\n"); 100 | } 101 | 102 | for (int t = 0; t < nt; ++t) 103 | { 104 | mngr.wait([](cpptask::internal::EventId eventId) 105 | { 106 | return eventId == cpptask::internal::EventId::TaskFinishedEvent; 107 | }); 108 | log(static_cast(cpptask::internal::EventId::TaskFinishedEvent), " received ", std::this_thread::get_id(), "\n"); 109 | } 110 | 111 | for (int t = 0; t < nt; ++t) 112 | { 113 | mngr.notify(cpptask::internal::EventId::ThreadStopEvent); 114 | } 115 | })); 116 | 117 | 118 | for (int t = 0; t < nt; ++t) 119 | { 120 | waits.emplace_back(std::async(std::launch::async, [&mngr] 121 | { 122 | bool done = false; 123 | while (!done) 124 | { 125 | cpptask::internal::EventId id = cpptask::internal::EventId::NoneEvent; 126 | mngr.wait([&id](cpptask::internal::EventId eventId) 127 | { 128 | auto res = eventId == cpptask::internal::EventId::NewTaskEvent || 129 | eventId == cpptask::internal::EventId::ThreadStopEvent; 130 | id = eventId; 131 | return res; 132 | }); 133 | log(static_cast(id), " received ", std::this_thread::get_id(), "\n"); 134 | if (id == cpptask::internal::EventId::ThreadStopEvent) 135 | { 136 | done = true; 137 | } 138 | else 139 | { 140 | mngr.notify(cpptask::internal::EventId::TaskFinishedEvent); 141 | log("sent ", static_cast(cpptask::internal::EventId::TaskFinishedEvent), " ", std::this_thread::get_id(), "\n"); 142 | } 143 | } 144 | })); 145 | } 146 | 147 | for (auto& f : waits) 148 | { 149 | f.get(); 150 | } 151 | 152 | log("\n"); 153 | } 154 | } 155 | 156 | TEST(EventManagerTest, SendWaitRotate) 157 | { 158 | cpptask::internal::EventManager mngr; 159 | 160 | const int N = 10; 161 | 162 | for (int i = 0; i < N; ++i) 163 | { 164 | std::vector> waits; 165 | log("session start\n"); 166 | waits.emplace_back(std::async(std::launch::async, [&mngr] 167 | { 168 | mngr.notify(cpptask::internal::EventId::NewTaskEvent); 169 | mngr.notify(cpptask::internal::EventId::CustomEvent); 170 | log("sent NewTask, waiting ThreadStop ", std::this_thread::get_id(), "\n"); 171 | mngr.wait([](cpptask::internal::EventId eventId) 172 | { 173 | return eventId == cpptask::internal::EventId::ThreadStopEvent; 174 | }); 175 | log("ThreadStop received ", std::this_thread::get_id(), "\n"); 176 | })); 177 | 178 | waits.emplace_back(std::async(std::launch::async, [&mngr] 179 | { 180 | std::this_thread::sleep_for(std::chrono::milliseconds(50)); 181 | log("waiting NewTask ", std::this_thread::get_id(), "\n"); 182 | mngr.wait([](cpptask::internal::EventId eventId) 183 | { 184 | return eventId == cpptask::internal::EventId::NewTaskEvent; 185 | }); 186 | mngr.notify(cpptask::internal::EventId::ThreadStopEvent); 187 | log("sent ThreadStop ", std::this_thread::get_id(), "\n"); 188 | })); 189 | 190 | for (auto& f : waits) 191 | { 192 | f.get(); 193 | } 194 | 195 | log("\n"); 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /3rdparty/gtest/include/gtest/gtest-test-part.h: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: mheule@google.com (Markus Heule) 31 | // 32 | 33 | #ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ 34 | #define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ 35 | 36 | #include 37 | #include 38 | #include "gtest/internal/gtest-internal.h" 39 | #include "gtest/internal/gtest-string.h" 40 | 41 | namespace testing { 42 | 43 | // A copyable object representing the result of a test part (i.e. an 44 | // assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()). 45 | // 46 | // Don't inherit from TestPartResult as its destructor is not virtual. 47 | class GTEST_API_ TestPartResult { 48 | public: 49 | // The possible outcomes of a test part (i.e. an assertion or an 50 | // explicit SUCCEED(), FAIL(), or ADD_FAILURE()). 51 | enum Type { 52 | kSuccess, // Succeeded. 53 | kNonFatalFailure, // Failed but the test can continue. 54 | kFatalFailure // Failed and the test should be terminated. 55 | }; 56 | 57 | // C'tor. TestPartResult does NOT have a default constructor. 58 | // Always use this constructor (with parameters) to create a 59 | // TestPartResult object. 60 | TestPartResult(Type a_type, 61 | const char* a_file_name, 62 | int a_line_number, 63 | const char* a_message) 64 | : type_(a_type), 65 | file_name_(a_file_name == NULL ? "" : a_file_name), 66 | line_number_(a_line_number), 67 | summary_(ExtractSummary(a_message)), 68 | message_(a_message) { 69 | } 70 | 71 | // Gets the outcome of the test part. 72 | Type type() const { return type_; } 73 | 74 | // Gets the name of the source file where the test part took place, or 75 | // NULL if it's unknown. 76 | const char* file_name() const { 77 | return file_name_.empty() ? NULL : file_name_.c_str(); 78 | } 79 | 80 | // Gets the line in the source file where the test part took place, 81 | // or -1 if it's unknown. 82 | int line_number() const { return line_number_; } 83 | 84 | // Gets the summary of the failure message. 85 | const char* summary() const { return summary_.c_str(); } 86 | 87 | // Gets the message associated with the test part. 88 | const char* message() const { return message_.c_str(); } 89 | 90 | // Returns true iff the test part passed. 91 | bool passed() const { return type_ == kSuccess; } 92 | 93 | // Returns true iff the test part failed. 94 | bool failed() const { return type_ != kSuccess; } 95 | 96 | // Returns true iff the test part non-fatally failed. 97 | bool nonfatally_failed() const { return type_ == kNonFatalFailure; } 98 | 99 | // Returns true iff the test part fatally failed. 100 | bool fatally_failed() const { return type_ == kFatalFailure; } 101 | 102 | private: 103 | Type type_; 104 | 105 | // Gets the summary of the failure message by omitting the stack 106 | // trace in it. 107 | static std::string ExtractSummary(const char* message); 108 | 109 | // The name of the source file where the test part took place, or 110 | // "" if the source file is unknown. 111 | std::string file_name_; 112 | // The line in the source file where the test part took place, or -1 113 | // if the line number is unknown. 114 | int line_number_; 115 | std::string summary_; // The test failure summary. 116 | std::string message_; // The test failure message. 117 | }; 118 | 119 | // Prints a TestPartResult object. 120 | std::ostream& operator<<(std::ostream& os, const TestPartResult& result); 121 | 122 | // An array of TestPartResult objects. 123 | // 124 | // Don't inherit from TestPartResultArray as its destructor is not 125 | // virtual. 126 | class GTEST_API_ TestPartResultArray { 127 | public: 128 | TestPartResultArray() {} 129 | 130 | // Appends the given TestPartResult to the array. 131 | void Append(const TestPartResult& result); 132 | 133 | // Returns the TestPartResult at the given index (0-based). 134 | const TestPartResult& GetTestPartResult(int index) const; 135 | 136 | // Returns the number of TestPartResult objects in the array. 137 | int size() const; 138 | 139 | private: 140 | std::vector array_; 141 | 142 | GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray); 143 | }; 144 | 145 | // This interface knows how to report a test part result. 146 | class TestPartResultReporterInterface { 147 | public: 148 | virtual ~TestPartResultReporterInterface() {} 149 | 150 | virtual void ReportTestPartResult(const TestPartResult& result) = 0; 151 | }; 152 | 153 | namespace internal { 154 | 155 | // This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a 156 | // statement generates new fatal failures. To do so it registers itself as the 157 | // current test part result reporter. Besides checking if fatal failures were 158 | // reported, it only delegates the reporting to the former result reporter. 159 | // The original result reporter is restored in the destructor. 160 | // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. 161 | class GTEST_API_ HasNewFatalFailureHelper 162 | : public TestPartResultReporterInterface { 163 | public: 164 | HasNewFatalFailureHelper(); 165 | virtual ~HasNewFatalFailureHelper(); 166 | virtual void ReportTestPartResult(const TestPartResult& result); 167 | bool has_new_fatal_failure() const { return has_new_fatal_failure_; } 168 | private: 169 | bool has_new_fatal_failure_; 170 | TestPartResultReporterInterface* original_reporter_; 171 | 172 | GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper); 173 | }; 174 | 175 | } // namespace internal 176 | 177 | } // namespace testing 178 | 179 | #endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ 180 | -------------------------------------------------------------------------------- /3rdparty/gtest/include/gtest/internal/gtest-string.h: -------------------------------------------------------------------------------- 1 | // Copyright 2005, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) 31 | // 32 | // The Google C++ Testing Framework (Google Test) 33 | // 34 | // This header file declares the String class and functions used internally by 35 | // Google Test. They are subject to change without notice. They should not used 36 | // by code external to Google Test. 37 | // 38 | // This header file is #included by . 39 | // It should not be #included by other files. 40 | 41 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ 42 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ 43 | 44 | #ifdef __BORLANDC__ 45 | // string.h is not guaranteed to provide strcpy on C++ Builder. 46 | # include 47 | #endif 48 | 49 | #include 50 | #include 51 | 52 | #include "gtest/internal/gtest-port.h" 53 | 54 | namespace testing { 55 | namespace internal { 56 | 57 | // String - an abstract class holding static string utilities. 58 | class GTEST_API_ String { 59 | public: 60 | // Static utility methods 61 | 62 | // Clones a 0-terminated C string, allocating memory using new. The 63 | // caller is responsible for deleting the return value using 64 | // delete[]. Returns the cloned string, or NULL if the input is 65 | // NULL. 66 | // 67 | // This is different from strdup() in string.h, which allocates 68 | // memory using malloc(). 69 | static const char* CloneCString(const char* c_str); 70 | 71 | #if GTEST_OS_WINDOWS_MOBILE 72 | // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be 73 | // able to pass strings to Win32 APIs on CE we need to convert them 74 | // to 'Unicode', UTF-16. 75 | 76 | // Creates a UTF-16 wide string from the given ANSI string, allocating 77 | // memory using new. The caller is responsible for deleting the return 78 | // value using delete[]. Returns the wide string, or NULL if the 79 | // input is NULL. 80 | // 81 | // The wide string is created using the ANSI codepage (CP_ACP) to 82 | // match the behaviour of the ANSI versions of Win32 calls and the 83 | // C runtime. 84 | static LPCWSTR AnsiToUtf16(const char* c_str); 85 | 86 | // Creates an ANSI string from the given wide string, allocating 87 | // memory using new. The caller is responsible for deleting the return 88 | // value using delete[]. Returns the ANSI string, or NULL if the 89 | // input is NULL. 90 | // 91 | // The returned string is created using the ANSI codepage (CP_ACP) to 92 | // match the behaviour of the ANSI versions of Win32 calls and the 93 | // C runtime. 94 | static const char* Utf16ToAnsi(LPCWSTR utf16_str); 95 | #endif 96 | 97 | // Compares two C strings. Returns true iff they have the same content. 98 | // 99 | // Unlike strcmp(), this function can handle NULL argument(s). A 100 | // NULL C string is considered different to any non-NULL C string, 101 | // including the empty string. 102 | static bool CStringEquals(const char* lhs, const char* rhs); 103 | 104 | // Converts a wide C string to a String using the UTF-8 encoding. 105 | // NULL will be converted to "(null)". If an error occurred during 106 | // the conversion, "(failed to convert from wide string)" is 107 | // returned. 108 | static std::string ShowWideCString(const wchar_t* wide_c_str); 109 | 110 | // Compares two wide C strings. Returns true iff they have the same 111 | // content. 112 | // 113 | // Unlike wcscmp(), this function can handle NULL argument(s). A 114 | // NULL C string is considered different to any non-NULL C string, 115 | // including the empty string. 116 | static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs); 117 | 118 | // Compares two C strings, ignoring case. Returns true iff they 119 | // have the same content. 120 | // 121 | // Unlike strcasecmp(), this function can handle NULL argument(s). 122 | // A NULL C string is considered different to any non-NULL C string, 123 | // including the empty string. 124 | static bool CaseInsensitiveCStringEquals(const char* lhs, 125 | const char* rhs); 126 | 127 | // Compares two wide C strings, ignoring case. Returns true iff they 128 | // have the same content. 129 | // 130 | // Unlike wcscasecmp(), this function can handle NULL argument(s). 131 | // A NULL C string is considered different to any non-NULL wide C string, 132 | // including the empty string. 133 | // NB: The implementations on different platforms slightly differ. 134 | // On windows, this method uses _wcsicmp which compares according to LC_CTYPE 135 | // environment variable. On GNU platform this method uses wcscasecmp 136 | // which compares according to LC_CTYPE category of the current locale. 137 | // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the 138 | // current locale. 139 | static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs, 140 | const wchar_t* rhs); 141 | 142 | // Returns true iff the given string ends with the given suffix, ignoring 143 | // case. Any string is considered to end with an empty suffix. 144 | static bool EndsWithCaseInsensitive( 145 | const std::string& str, const std::string& suffix); 146 | 147 | // Formats an int value as "%02d". 148 | static std::string FormatIntWidth2(int value); // "%02d" for width == 2 149 | 150 | // Formats an int value as "%X". 151 | static std::string FormatHexInt(int value); 152 | 153 | // Formats a byte as "%02X". 154 | static std::string FormatByte(unsigned char value); 155 | 156 | private: 157 | String(); // Not meant to be instantiated. 158 | }; // class String 159 | 160 | // Gets the content of the stringstream's buffer as an std::string. Each '\0' 161 | // character in the buffer is replaced with "\\0". 162 | GTEST_API_ std::string StringStreamToString(::std::stringstream* stream); 163 | 164 | } // namespace internal 165 | } // namespace testing 166 | 167 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ 168 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | "cpptask" is an open source library which implements load balanced task scheduler for developing parallel C++ programs. 4 | 5 | The main advantages are: 6 | 7 | 1. It was made to be **similar to native C++** `async` interfaces as much as possible. 8 | 2. You can specify **number of threads**, library will not create new ones. 9 | 3. "Work stealing" technique is used for **load balancing**. 10 | 4. You can use special type of synchronization primitives and special lock type to guarantee **workload of thread during lock** waiting operation. 11 | 5. Library implemented as **headers only** library. 12 | 13 | # Features 14 | 15 | 1. **Task management** 16 | * ***future*** class 17 | * ***async*** function 18 | 19 | These functionality copies standard C++ signatures, methods and behaviour except `shared_future` class. 20 | 21 | Usage example: 22 | 23 | ```cpp 24 | #include 25 | #include 26 | #include 27 | 28 | int main() 29 | { 30 | cpptask::initializer init(4); //initialize library with 4 threads 31 | auto f = cpptask::async(std::launch::async, []() 32 | { 33 | //do something 34 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); 35 | return 5; 36 | }); 37 | 38 | auto x = f.get(); 39 | assert(5 == x); 40 | } 41 | ``` 42 | 43 | 2. **Synchronization** 44 | * ***mutex*** class - Special synchronization primitive which allows to workload thread during waiting operation. should be used only in pair with `process_lock` type, signatures identical to `std::mutex`. 45 | 46 | Usage example: 47 | 48 | ```cpp 49 | ... 50 | cpptask::mutex guard; 51 | ... 52 | { 53 | std::unique_lock lock(guard); //totaly block thread 54 | } 55 | ... 56 | { 57 | cpptask::process_lock lock(guard); //will process other tasks during lock 58 | } 59 | ... 60 | ``` 61 | * ***event*** class - Event synchronization abstraction. 62 | 63 | Usage example: 64 | 65 | ``` 66 | cpptask::event e; 67 | ... 68 | //somewhere in thread 69 | { 70 | e.wait(); 71 | //do some work if event fired 72 | } 73 | ... 74 | //somewehere in another thread 75 | e.notify(); 76 | ... 77 | ``` 78 | 79 | * ***lockable_event*** class - Same as `cpptask::event` but should be used in pair with `process_lock` type to workload thread during waiting operation. 80 | 81 | Usage example: 82 | 83 | ```cpp 84 | ... 85 | cpptask::lockable_event e; 86 | ... 87 | //somewhere in thread 88 | { 89 | cpptask::process_lock lock(e); //will process other tasks during lock 90 | //do some work when event fired 91 | } 92 | ... 93 | //somewehere in another thread 94 | e.notify(); 95 | ... 96 | ``` 97 | * ***semaphore*** class - Counting semaphore synchronization abstraction. Object of this type can be used for example to limit threads count accessing some resource. Object can be initialized with initial counter value and maximum value for counter. When `lock` operation is called, counter value is decreased if counter value is non zero. When `unlock` operation is called, counter value is increased, but only in case if new value will be less or equal to maximum allowed. Also maximum value is negative by default, this mean that maximum value is unbounded. 98 | 99 | Usage example: 100 | 101 | ``` 102 | ... 103 | cpptask::semaphore s(3,3); //We limit access to resource only to 3 threads concurrently 104 | SharedResource res; 105 | ... 106 | //somewhere in threads 107 | { 108 | std::unique_lock lock(s); 109 | //now we can access resource 110 | process(res); 111 | } 112 | ``` 113 | 114 | * ***lockable_semaphore*** class - Same as `cpptask::semaphore` but should be used in pair with `process_lock` type to workload thread during waiting operation. 115 | 116 | Usage example: 117 | 118 | ``` 119 | ... 120 | cpptask::lockable_semaphore s(3,3); //We limit access to resource only to 3 threads concurrently 121 | SharedResource res; 122 | ... 123 | //somewhere in threads 124 | { 125 | std::process_lock lock(s); //will process other tasks during lock 126 | //now we can access resource 127 | process(res); 128 | } 129 | ``` 130 | 131 | * ***process_lock*** class - type for instantiating RAII lock on special synchronization primitives to workload thread during waiting. See `lockable_mutex`, `lockable_event` and `lockable_semaphore`. 132 | 133 | 3. **Algorithms** 134 | * ***range*** class - simple right opened range. Can be initialized with integer types or with iterators. Used internally for parallel `for_each` implementation. 135 | 136 | * ***split_range*** function - split input iterator range to number of smaller ranges sequentially. Used internally for parallel `for_each` implementation. 137 | 138 | Usage example: 139 | 140 | ``` 141 | template 142 | void function(Iterator start, Iterator end) 143 | { 144 | typedef range RangeType; 145 | typedef std::vector Ranges; 146 | Ranges ranges = split_range(start, end, 4); //split input iterator range to 4 sub ranges sequentially 147 | ... 148 | } 149 | ``` 150 | 151 | * ***split_num_range*** function - split input integers range to number of smaller ranges sequentially. Used internally for parallel `for_each` implementation. 152 | 153 | Usage example: 154 | 155 | ``` 156 | ... 157 | typedef range RangeType; 158 | typedef std::vector Ranges; 159 | Ranges ranges = split_range(1, 100, 4); //split input integer range[1,100) to 4 sub ranges sequentially 160 | ... 161 | ``` 162 | 163 | * ***for_each*** function - apply operation to each element of input right opened range. Function splits input range to number of sub ranges and proccess them in parallel. Number of sub ranges equals to number of threads used for library initialization. Input range can be specified with iterators or with integer numbers. 164 | 165 | Usage example: 166 | 167 | ``` 168 | ... 169 | cpptask::for_each(1,100,[&](int x){ heavyFunction(x); }); 170 | ... 171 | ``` 172 | 173 | * ***reduce*** function - perform reduction on input right opened range, specified with iterators. Function recursively split input range and process each sub range in parallel with others. 174 | 175 | Usage example: 176 | 177 | ``` 178 | ... 179 | int process_func(const cpptask::range::iterator>& range) 180 | { 181 | return std::accumulate(range.start, range.end, 0); 182 | } 183 | 184 | int join_func(int a, int b) 185 | { 186 | return a + b; 187 | } 188 | ... 189 | std::vector m(BIG_NUMBER_OF_ELEMENTS); 190 | ... 191 | cpptask::reduce(m.begin(), m.end(), process_func, join_func); // calculate sum in parallel 192 | ... 193 | ``` 194 | 195 | 4. **Miscellaneous** 196 | * ***initializer*** class - should be used for library initialization, use number of threads as parameter. 197 | 198 | Usage example: 199 | 200 | ``` 201 | ... 202 | cpptask::initializer init(4); //initialize library with 4 threads 203 | ... 204 | ``` 205 | 206 | * ***cpptask::exception*** class - this type of exception will be throwed in case of exceptional situation from library functions. 207 | 208 | # Supported Platforms (was tested on) 209 | 210 | * Linux (Arch) 211 | * gcc 5.1.0 (64bits) 212 | * clang 3.6.2 (64bits) 213 | * Windows 214 | * Visual Studio 2015 (64 bit) 215 | * MinGw-64 (gcc 5.1) 216 | 217 | Also you can visit [c-vision.com.ua](http://c-vision.com.ua) to learn more news about project. 218 | -------------------------------------------------------------------------------- /3rdparty/gtest/include/gtest/internal/gtest-linked_ptr.h: -------------------------------------------------------------------------------- 1 | // Copyright 2003 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Authors: Dan Egnor (egnor@google.com) 31 | // 32 | // A "smart" pointer type with reference tracking. Every pointer to a 33 | // particular object is kept on a circular linked list. When the last pointer 34 | // to an object is destroyed or reassigned, the object is deleted. 35 | // 36 | // Used properly, this deletes the object when the last reference goes away. 37 | // There are several caveats: 38 | // - Like all reference counting schemes, cycles lead to leaks. 39 | // - Each smart pointer is actually two pointers (8 bytes instead of 4). 40 | // - Every time a pointer is assigned, the entire list of pointers to that 41 | // object is traversed. This class is therefore NOT SUITABLE when there 42 | // will often be more than two or three pointers to a particular object. 43 | // - References are only tracked as long as linked_ptr<> objects are copied. 44 | // If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS 45 | // will happen (double deletion). 46 | // 47 | // A good use of this class is storing object references in STL containers. 48 | // You can safely put linked_ptr<> in a vector<>. 49 | // Other uses may not be as good. 50 | // 51 | // Note: If you use an incomplete type with linked_ptr<>, the class 52 | // *containing* linked_ptr<> must have a constructor and destructor (even 53 | // if they do nothing!). 54 | // 55 | // Bill Gibbons suggested we use something like this. 56 | // 57 | // Thread Safety: 58 | // Unlike other linked_ptr implementations, in this implementation 59 | // a linked_ptr object is thread-safe in the sense that: 60 | // - it's safe to copy linked_ptr objects concurrently, 61 | // - it's safe to copy *from* a linked_ptr and read its underlying 62 | // raw pointer (e.g. via get()) concurrently, and 63 | // - it's safe to write to two linked_ptrs that point to the same 64 | // shared object concurrently. 65 | // TODO(wan@google.com): rename this to safe_linked_ptr to avoid 66 | // confusion with normal linked_ptr. 67 | 68 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ 69 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ 70 | 71 | #include 72 | #include 73 | 74 | #include "gtest/internal/gtest-port.h" 75 | 76 | namespace testing { 77 | namespace internal { 78 | 79 | // Protects copying of all linked_ptr objects. 80 | GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex); 81 | 82 | // This is used internally by all instances of linked_ptr<>. It needs to be 83 | // a non-template class because different types of linked_ptr<> can refer to 84 | // the same object (linked_ptr(obj) vs linked_ptr(obj)). 85 | // So, it needs to be possible for different types of linked_ptr to participate 86 | // in the same circular linked list, so we need a single class type here. 87 | // 88 | // DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr. 89 | class linked_ptr_internal { 90 | public: 91 | // Create a new circle that includes only this instance. 92 | void join_new() { 93 | next_ = this; 94 | } 95 | 96 | // Many linked_ptr operations may change p.link_ for some linked_ptr 97 | // variable p in the same circle as this object. Therefore we need 98 | // to prevent two such operations from occurring concurrently. 99 | // 100 | // Note that different types of linked_ptr objects can coexist in a 101 | // circle (e.g. linked_ptr, linked_ptr, and 102 | // linked_ptr). Therefore we must use a single mutex to 103 | // protect all linked_ptr objects. This can create serious 104 | // contention in production code, but is acceptable in a testing 105 | // framework. 106 | 107 | // Join an existing circle. 108 | void join(linked_ptr_internal const* ptr) 109 | GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { 110 | MutexLock lock(&g_linked_ptr_mutex); 111 | 112 | linked_ptr_internal const* p = ptr; 113 | while (p->next_ != ptr) p = p->next_; 114 | p->next_ = this; 115 | next_ = ptr; 116 | } 117 | 118 | // Leave whatever circle we're part of. Returns true if we were the 119 | // last member of the circle. Once this is done, you can join() another. 120 | bool depart() 121 | GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { 122 | MutexLock lock(&g_linked_ptr_mutex); 123 | 124 | if (next_ == this) return true; 125 | linked_ptr_internal const* p = next_; 126 | while (p->next_ != this) p = p->next_; 127 | p->next_ = next_; 128 | return false; 129 | } 130 | 131 | private: 132 | mutable linked_ptr_internal const* next_; 133 | }; 134 | 135 | template 136 | class linked_ptr { 137 | public: 138 | typedef T element_type; 139 | 140 | // Take over ownership of a raw pointer. This should happen as soon as 141 | // possible after the object is created. 142 | explicit linked_ptr(T* ptr = NULL) { capture(ptr); } 143 | ~linked_ptr() { depart(); } 144 | 145 | // Copy an existing linked_ptr<>, adding ourselves to the list of references. 146 | template linked_ptr(linked_ptr const& ptr) { copy(&ptr); } 147 | linked_ptr(linked_ptr const& ptr) { // NOLINT 148 | assert(&ptr != this); 149 | copy(&ptr); 150 | } 151 | 152 | // Assignment releases the old value and acquires the new. 153 | template linked_ptr& operator=(linked_ptr const& ptr) { 154 | depart(); 155 | copy(&ptr); 156 | return *this; 157 | } 158 | 159 | linked_ptr& operator=(linked_ptr const& ptr) { 160 | if (&ptr != this) { 161 | depart(); 162 | copy(&ptr); 163 | } 164 | return *this; 165 | } 166 | 167 | // Smart pointer members. 168 | void reset(T* ptr = NULL) { 169 | depart(); 170 | capture(ptr); 171 | } 172 | T* get() const { return value_; } 173 | T* operator->() const { return value_; } 174 | T& operator*() const { return *value_; } 175 | 176 | bool operator==(T* p) const { return value_ == p; } 177 | bool operator!=(T* p) const { return value_ != p; } 178 | template 179 | bool operator==(linked_ptr const& ptr) const { 180 | return value_ == ptr.get(); 181 | } 182 | template 183 | bool operator!=(linked_ptr const& ptr) const { 184 | return value_ != ptr.get(); 185 | } 186 | 187 | private: 188 | template 189 | friend class linked_ptr; 190 | 191 | T* value_; 192 | linked_ptr_internal link_; 193 | 194 | void depart() { 195 | if (link_.depart()) delete value_; 196 | } 197 | 198 | void capture(T* ptr) { 199 | value_ = ptr; 200 | link_.join_new(); 201 | } 202 | 203 | template void copy(linked_ptr const* ptr) { 204 | value_ = ptr->get(); 205 | if (value_) 206 | link_.join(&ptr->link_); 207 | else 208 | link_.join_new(); 209 | } 210 | }; 211 | 212 | template inline 213 | bool operator==(T* ptr, const linked_ptr& x) { 214 | return ptr == x.get(); 215 | } 216 | 217 | template inline 218 | bool operator!=(T* ptr, const linked_ptr& x) { 219 | return ptr != x.get(); 220 | } 221 | 222 | // A function to convert T* into linked_ptr 223 | // Doing e.g. make_linked_ptr(new FooBarBaz(arg)) is a shorter notation 224 | // for linked_ptr >(new FooBarBaz(arg)) 225 | template 226 | linked_ptr make_linked_ptr(T* ptr) { 227 | return linked_ptr(ptr); 228 | } 229 | 230 | } // namespace internal 231 | } // namespace testing 232 | 233 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ 234 | -------------------------------------------------------------------------------- /3rdparty/gtest/include/gtest/gtest-message.h: -------------------------------------------------------------------------------- 1 | // Copyright 2005, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | // 32 | // The Google C++ Testing Framework (Google Test) 33 | // 34 | // This header file defines the Message class. 35 | // 36 | // IMPORTANT NOTE: Due to limitation of the C++ language, we have to 37 | // leave some internal implementation details in this header file. 38 | // They are clearly marked by comments like this: 39 | // 40 | // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. 41 | // 42 | // Such code is NOT meant to be used by a user directly, and is subject 43 | // to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user 44 | // program! 45 | 46 | #ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ 47 | #define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ 48 | 49 | #include 50 | 51 | #include "gtest/internal/gtest-port.h" 52 | 53 | // Ensures that there is at least one operator<< in the global namespace. 54 | // See Message& operator<<(...) below for why. 55 | void operator<<(const testing::internal::Secret&, int); 56 | 57 | namespace testing { 58 | 59 | // The Message class works like an ostream repeater. 60 | // 61 | // Typical usage: 62 | // 63 | // 1. You stream a bunch of values to a Message object. 64 | // It will remember the text in a stringstream. 65 | // 2. Then you stream the Message object to an ostream. 66 | // This causes the text in the Message to be streamed 67 | // to the ostream. 68 | // 69 | // For example; 70 | // 71 | // testing::Message foo; 72 | // foo << 1 << " != " << 2; 73 | // std::cout << foo; 74 | // 75 | // will print "1 != 2". 76 | // 77 | // Message is not intended to be inherited from. In particular, its 78 | // destructor is not virtual. 79 | // 80 | // Note that stringstream behaves differently in gcc and in MSVC. You 81 | // can stream a NULL char pointer to it in the former, but not in the 82 | // latter (it causes an access violation if you do). The Message 83 | // class hides this difference by treating a NULL char pointer as 84 | // "(null)". 85 | class GTEST_API_ Message { 86 | private: 87 | // The type of basic IO manipulators (endl, ends, and flush) for 88 | // narrow streams. 89 | typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&); 90 | 91 | public: 92 | // Constructs an empty Message. 93 | Message(); 94 | 95 | // Copy constructor. 96 | Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT 97 | *ss_ << msg.GetString(); 98 | } 99 | 100 | // Constructs a Message from a C-string. 101 | explicit Message(const char* str) : ss_(new ::std::stringstream) { 102 | *ss_ << str; 103 | } 104 | 105 | #if GTEST_OS_SYMBIAN 106 | // Streams a value (either a pointer or not) to this object. 107 | template 108 | inline Message& operator <<(const T& value) { 109 | StreamHelper(typename internal::is_pointer::type(), value); 110 | return *this; 111 | } 112 | #else 113 | // Streams a non-pointer value to this object. 114 | template 115 | inline Message& operator <<(const T& val) { 116 | // Some libraries overload << for STL containers. These 117 | // overloads are defined in the global namespace instead of ::std. 118 | // 119 | // C++'s symbol lookup rule (i.e. Koenig lookup) says that these 120 | // overloads are visible in either the std namespace or the global 121 | // namespace, but not other namespaces, including the testing 122 | // namespace which Google Test's Message class is in. 123 | // 124 | // To allow STL containers (and other types that has a << operator 125 | // defined in the global namespace) to be used in Google Test 126 | // assertions, testing::Message must access the custom << operator 127 | // from the global namespace. With this using declaration, 128 | // overloads of << defined in the global namespace and those 129 | // visible via Koenig lookup are both exposed in this function. 130 | using ::operator <<; 131 | *ss_ << val; 132 | return *this; 133 | } 134 | 135 | // Streams a pointer value to this object. 136 | // 137 | // This function is an overload of the previous one. When you 138 | // stream a pointer to a Message, this definition will be used as it 139 | // is more specialized. (The C++ Standard, section 140 | // [temp.func.order].) If you stream a non-pointer, then the 141 | // previous definition will be used. 142 | // 143 | // The reason for this overload is that streaming a NULL pointer to 144 | // ostream is undefined behavior. Depending on the compiler, you 145 | // may get "0", "(nil)", "(null)", or an access violation. To 146 | // ensure consistent result across compilers, we always treat NULL 147 | // as "(null)". 148 | template 149 | inline Message& operator <<(T* const& pointer) { // NOLINT 150 | if (pointer == NULL) { 151 | *ss_ << "(null)"; 152 | } else { 153 | *ss_ << pointer; 154 | } 155 | return *this; 156 | } 157 | #endif // GTEST_OS_SYMBIAN 158 | 159 | // Since the basic IO manipulators are overloaded for both narrow 160 | // and wide streams, we have to provide this specialized definition 161 | // of operator <<, even though its body is the same as the 162 | // templatized version above. Without this definition, streaming 163 | // endl or other basic IO manipulators to Message will confuse the 164 | // compiler. 165 | Message& operator <<(BasicNarrowIoManip val) { 166 | *ss_ << val; 167 | return *this; 168 | } 169 | 170 | // Instead of 1/0, we want to see true/false for bool values. 171 | Message& operator <<(bool b) { 172 | return *this << (b ? "true" : "false"); 173 | } 174 | 175 | // These two overloads allow streaming a wide C string to a Message 176 | // using the UTF-8 encoding. 177 | Message& operator <<(const wchar_t* wide_c_str); 178 | Message& operator <<(wchar_t* wide_c_str); 179 | 180 | #if GTEST_HAS_STD_WSTRING 181 | // Converts the given wide string to a narrow string using the UTF-8 182 | // encoding, and streams the result to this Message object. 183 | Message& operator <<(const ::std::wstring& wstr); 184 | #endif // GTEST_HAS_STD_WSTRING 185 | 186 | #if GTEST_HAS_GLOBAL_WSTRING 187 | // Converts the given wide string to a narrow string using the UTF-8 188 | // encoding, and streams the result to this Message object. 189 | Message& operator <<(const ::wstring& wstr); 190 | #endif // GTEST_HAS_GLOBAL_WSTRING 191 | 192 | // Gets the text streamed to this object so far as an std::string. 193 | // Each '\0' character in the buffer is replaced with "\\0". 194 | // 195 | // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. 196 | std::string GetString() const; 197 | 198 | private: 199 | 200 | #if GTEST_OS_SYMBIAN 201 | // These are needed as the Nokia Symbian Compiler cannot decide between 202 | // const T& and const T* in a function template. The Nokia compiler _can_ 203 | // decide between class template specializations for T and T*, so a 204 | // tr1::type_traits-like is_pointer works, and we can overload on that. 205 | template 206 | inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) { 207 | if (pointer == NULL) { 208 | *ss_ << "(null)"; 209 | } else { 210 | *ss_ << pointer; 211 | } 212 | } 213 | template 214 | inline void StreamHelper(internal::false_type /*is_pointer*/, 215 | const T& value) { 216 | // See the comments in Message& operator <<(const T&) above for why 217 | // we need this using statement. 218 | using ::operator <<; 219 | *ss_ << value; 220 | } 221 | #endif // GTEST_OS_SYMBIAN 222 | 223 | // We'll hold the text streamed to this object here. 224 | const internal::scoped_ptr< ::std::stringstream> ss_; 225 | 226 | // We declare (but don't implement) this to prevent the compiler 227 | // from implementing the assignment operator. 228 | void operator=(const Message&); 229 | }; 230 | 231 | // Streams a Message to an ostream. 232 | inline std::ostream& operator <<(std::ostream& os, const Message& sb) { 233 | return os << sb.GetString(); 234 | } 235 | 236 | namespace internal { 237 | 238 | // Converts a streamable value to an std::string. A NULL pointer is 239 | // converted to "(null)". When the input value is a ::string, 240 | // ::std::string, ::wstring, or ::std::wstring object, each NUL 241 | // character in it is replaced with "\\0". 242 | template 243 | std::string StreamableToString(const T& streamable) { 244 | return (Message() << streamable).GetString(); 245 | } 246 | 247 | } // namespace internal 248 | } // namespace testing 249 | 250 | #endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ 251 | -------------------------------------------------------------------------------- /3rdparty/gtest/include/gtest/internal/gtest-filepath.h: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: keith.ray@gmail.com (Keith Ray) 31 | // 32 | // Google Test filepath utilities 33 | // 34 | // This header file declares classes and functions used internally by 35 | // Google Test. They are subject to change without notice. 36 | // 37 | // This file is #included in . 38 | // Do not include this header file separately! 39 | 40 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ 41 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ 42 | 43 | #include "gtest/internal/gtest-string.h" 44 | 45 | namespace testing { 46 | namespace internal { 47 | 48 | // FilePath - a class for file and directory pathname manipulation which 49 | // handles platform-specific conventions (like the pathname separator). 50 | // Used for helper functions for naming files in a directory for xml output. 51 | // Except for Set methods, all methods are const or static, which provides an 52 | // "immutable value object" -- useful for peace of mind. 53 | // A FilePath with a value ending in a path separator ("like/this/") represents 54 | // a directory, otherwise it is assumed to represent a file. In either case, 55 | // it may or may not represent an actual file or directory in the file system. 56 | // Names are NOT checked for syntax correctness -- no checking for illegal 57 | // characters, malformed paths, etc. 58 | 59 | class GTEST_API_ FilePath { 60 | public: 61 | FilePath() : pathname_("") { } 62 | FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { } 63 | 64 | explicit FilePath(const std::string& pathname) : pathname_(pathname) { 65 | Normalize(); 66 | } 67 | 68 | FilePath& operator=(const FilePath& rhs) { 69 | Set(rhs); 70 | return *this; 71 | } 72 | 73 | void Set(const FilePath& rhs) { 74 | pathname_ = rhs.pathname_; 75 | } 76 | 77 | const std::string& string() const { return pathname_; } 78 | const char* c_str() const { return pathname_.c_str(); } 79 | 80 | // Returns the current working directory, or "" if unsuccessful. 81 | static FilePath GetCurrentDir(); 82 | 83 | // Given directory = "dir", base_name = "test", number = 0, 84 | // extension = "xml", returns "dir/test.xml". If number is greater 85 | // than zero (e.g., 12), returns "dir/test_12.xml". 86 | // On Windows platform, uses \ as the separator rather than /. 87 | static FilePath MakeFileName(const FilePath& directory, 88 | const FilePath& base_name, 89 | int number, 90 | const char* extension); 91 | 92 | // Given directory = "dir", relative_path = "test.xml", 93 | // returns "dir/test.xml". 94 | // On Windows, uses \ as the separator rather than /. 95 | static FilePath ConcatPaths(const FilePath& directory, 96 | const FilePath& relative_path); 97 | 98 | // Returns a pathname for a file that does not currently exist. The pathname 99 | // will be directory/base_name.extension or 100 | // directory/base_name_.extension if directory/base_name.extension 101 | // already exists. The number will be incremented until a pathname is found 102 | // that does not already exist. 103 | // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. 104 | // There could be a race condition if two or more processes are calling this 105 | // function at the same time -- they could both pick the same filename. 106 | static FilePath GenerateUniqueFileName(const FilePath& directory, 107 | const FilePath& base_name, 108 | const char* extension); 109 | 110 | // Returns true iff the path is "". 111 | bool IsEmpty() const { return pathname_.empty(); } 112 | 113 | // If input name has a trailing separator character, removes it and returns 114 | // the name, otherwise return the name string unmodified. 115 | // On Windows platform, uses \ as the separator, other platforms use /. 116 | FilePath RemoveTrailingPathSeparator() const; 117 | 118 | // Returns a copy of the FilePath with the directory part removed. 119 | // Example: FilePath("path/to/file").RemoveDirectoryName() returns 120 | // FilePath("file"). If there is no directory part ("just_a_file"), it returns 121 | // the FilePath unmodified. If there is no file part ("just_a_dir/") it 122 | // returns an empty FilePath (""). 123 | // On Windows platform, '\' is the path separator, otherwise it is '/'. 124 | FilePath RemoveDirectoryName() const; 125 | 126 | // RemoveFileName returns the directory path with the filename removed. 127 | // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". 128 | // If the FilePath is "a_file" or "/a_file", RemoveFileName returns 129 | // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does 130 | // not have a file, like "just/a/dir/", it returns the FilePath unmodified. 131 | // On Windows platform, '\' is the path separator, otherwise it is '/'. 132 | FilePath RemoveFileName() const; 133 | 134 | // Returns a copy of the FilePath with the case-insensitive extension removed. 135 | // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns 136 | // FilePath("dir/file"). If a case-insensitive extension is not 137 | // found, returns a copy of the original FilePath. 138 | FilePath RemoveExtension(const char* extension) const; 139 | 140 | // Creates directories so that path exists. Returns true if successful or if 141 | // the directories already exist; returns false if unable to create 142 | // directories for any reason. Will also return false if the FilePath does 143 | // not represent a directory (that is, it doesn't end with a path separator). 144 | bool CreateDirectoriesRecursively() const; 145 | 146 | // Create the directory so that path exists. Returns true if successful or 147 | // if the directory already exists; returns false if unable to create the 148 | // directory for any reason, including if the parent directory does not 149 | // exist. Not named "CreateDirectory" because that's a macro on Windows. 150 | bool CreateFolder() const; 151 | 152 | // Returns true if FilePath describes something in the file-system, 153 | // either a file, directory, or whatever, and that something exists. 154 | bool FileOrDirectoryExists() const; 155 | 156 | // Returns true if pathname describes a directory in the file-system 157 | // that exists. 158 | bool DirectoryExists() const; 159 | 160 | // Returns true if FilePath ends with a path separator, which indicates that 161 | // it is intended to represent a directory. Returns false otherwise. 162 | // This does NOT check that a directory (or file) actually exists. 163 | bool IsDirectory() const; 164 | 165 | // Returns true if pathname describes a root directory. (Windows has one 166 | // root directory per disk drive.) 167 | bool IsRootDirectory() const; 168 | 169 | // Returns true if pathname describes an absolute path. 170 | bool IsAbsolutePath() const; 171 | 172 | private: 173 | // Replaces multiple consecutive separators with a single separator. 174 | // For example, "bar///foo" becomes "bar/foo". Does not eliminate other 175 | // redundancies that might be in a pathname involving "." or "..". 176 | // 177 | // A pathname with multiple consecutive separators may occur either through 178 | // user error or as a result of some scripts or APIs that generate a pathname 179 | // with a trailing separator. On other platforms the same API or script 180 | // may NOT generate a pathname with a trailing "/". Then elsewhere that 181 | // pathname may have another "/" and pathname components added to it, 182 | // without checking for the separator already being there. 183 | // The script language and operating system may allow paths like "foo//bar" 184 | // but some of the functions in FilePath will not handle that correctly. In 185 | // particular, RemoveTrailingPathSeparator() only removes one separator, and 186 | // it is called in CreateDirectoriesRecursively() assuming that it will change 187 | // a pathname from directory syntax (trailing separator) to filename syntax. 188 | // 189 | // On Windows this method also replaces the alternate path separator '/' with 190 | // the primary path separator '\\', so that for example "bar\\/\\foo" becomes 191 | // "bar\\foo". 192 | 193 | void Normalize(); 194 | 195 | // Returns a pointer to the last occurence of a valid path separator in 196 | // the FilePath. On Windows, for example, both '/' and '\' are valid path 197 | // separators. Returns NULL if no path separator was found. 198 | const char* FindLastPathSeparator() const; 199 | 200 | std::string pathname_; 201 | }; // class FilePath 202 | 203 | } // namespace internal 204 | } // namespace testing 205 | 206 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ 207 | -------------------------------------------------------------------------------- /3rdparty/gtest/include/gtest/internal/gtest-type-util.h.pump: -------------------------------------------------------------------------------- 1 | $$ -*- mode: c++; -*- 2 | $var n = 50 $$ Maximum length of type lists we want to support. 3 | // Copyright 2008 Google Inc. 4 | // All Rights Reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are 8 | // met: 9 | // 10 | // * Redistributions of source code must retain the above copyright 11 | // notice, this list of conditions and the following disclaimer. 12 | // * Redistributions in binary form must reproduce the above 13 | // copyright notice, this list of conditions and the following disclaimer 14 | // in the documentation and/or other materials provided with the 15 | // distribution. 16 | // * Neither the name of Google Inc. nor the names of its 17 | // contributors may be used to endorse or promote products derived from 18 | // this software without specific prior written permission. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | // 32 | // Author: wan@google.com (Zhanyong Wan) 33 | 34 | // Type utilities needed for implementing typed and type-parameterized 35 | // tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! 36 | // 37 | // Currently we support at most $n types in a list, and at most $n 38 | // type-parameterized tests in one type-parameterized test case. 39 | // Please contact googletestframework@googlegroups.com if you need 40 | // more. 41 | 42 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ 43 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ 44 | 45 | #include "gtest/internal/gtest-port.h" 46 | 47 | // #ifdef __GNUC__ is too general here. It is possible to use gcc without using 48 | // libstdc++ (which is where cxxabi.h comes from). 49 | # if GTEST_HAS_CXXABI_H_ 50 | # include 51 | # elif defined(__HP_aCC) 52 | # include 53 | # endif // GTEST_HASH_CXXABI_H_ 54 | 55 | namespace testing { 56 | namespace internal { 57 | 58 | // GetTypeName() returns a human-readable name of type T. 59 | // NB: This function is also used in Google Mock, so don't move it inside of 60 | // the typed-test-only section below. 61 | template 62 | std::string GetTypeName() { 63 | # if GTEST_HAS_RTTI 64 | 65 | const char* const name = typeid(T).name(); 66 | # if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) 67 | int status = 0; 68 | // gcc's implementation of typeid(T).name() mangles the type name, 69 | // so we have to demangle it. 70 | # if GTEST_HAS_CXXABI_H_ 71 | using abi::__cxa_demangle; 72 | # endif // GTEST_HAS_CXXABI_H_ 73 | char* const readable_name = __cxa_demangle(name, 0, 0, &status); 74 | const std::string name_str(status == 0 ? readable_name : name); 75 | free(readable_name); 76 | return name_str; 77 | # else 78 | return name; 79 | # endif // GTEST_HAS_CXXABI_H_ || __HP_aCC 80 | 81 | # else 82 | 83 | return ""; 84 | 85 | # endif // GTEST_HAS_RTTI 86 | } 87 | 88 | #if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P 89 | 90 | // AssertyTypeEq::type is defined iff T1 and T2 are the same 91 | // type. This can be used as a compile-time assertion to ensure that 92 | // two types are equal. 93 | 94 | template 95 | struct AssertTypeEq; 96 | 97 | template 98 | struct AssertTypeEq { 99 | typedef bool type; 100 | }; 101 | 102 | // A unique type used as the default value for the arguments of class 103 | // template Types. This allows us to simulate variadic templates 104 | // (e.g. Types, Type, and etc), which C++ doesn't 105 | // support directly. 106 | struct None {}; 107 | 108 | // The following family of struct and struct templates are used to 109 | // represent type lists. In particular, TypesN 110 | // represents a type list with N types (T1, T2, ..., and TN) in it. 111 | // Except for Types0, every struct in the family has two member types: 112 | // Head for the first type in the list, and Tail for the rest of the 113 | // list. 114 | 115 | // The empty type list. 116 | struct Types0 {}; 117 | 118 | // Type lists of length 1, 2, 3, and so on. 119 | 120 | template 121 | struct Types1 { 122 | typedef T1 Head; 123 | typedef Types0 Tail; 124 | }; 125 | 126 | $range i 2..n 127 | 128 | $for i [[ 129 | $range j 1..i 130 | $range k 2..i 131 | template <$for j, [[typename T$j]]> 132 | struct Types$i { 133 | typedef T1 Head; 134 | typedef Types$(i-1)<$for k, [[T$k]]> Tail; 135 | }; 136 | 137 | 138 | ]] 139 | 140 | } // namespace internal 141 | 142 | // We don't want to require the users to write TypesN<...> directly, 143 | // as that would require them to count the length. Types<...> is much 144 | // easier to write, but generates horrible messages when there is a 145 | // compiler error, as gcc insists on printing out each template 146 | // argument, even if it has the default value (this means Types 147 | // will appear as Types in the compiler 148 | // errors). 149 | // 150 | // Our solution is to combine the best part of the two approaches: a 151 | // user would write Types, and Google Test will translate 152 | // that to TypesN internally to make error messages 153 | // readable. The translation is done by the 'type' member of the 154 | // Types template. 155 | 156 | $range i 1..n 157 | template <$for i, [[typename T$i = internal::None]]> 158 | struct Types { 159 | typedef internal::Types$n<$for i, [[T$i]]> type; 160 | }; 161 | 162 | template <> 163 | struct Types<$for i, [[internal::None]]> { 164 | typedef internal::Types0 type; 165 | }; 166 | 167 | $range i 1..n-1 168 | $for i [[ 169 | $range j 1..i 170 | $range k i+1..n 171 | template <$for j, [[typename T$j]]> 172 | struct Types<$for j, [[T$j]]$for k[[, internal::None]]> { 173 | typedef internal::Types$i<$for j, [[T$j]]> type; 174 | }; 175 | 176 | ]] 177 | 178 | namespace internal { 179 | 180 | # define GTEST_TEMPLATE_ template class 181 | 182 | // The template "selector" struct TemplateSel is used to 183 | // represent Tmpl, which must be a class template with one type 184 | // parameter, as a type. TemplateSel::Bind::type is defined 185 | // as the type Tmpl. This allows us to actually instantiate the 186 | // template "selected" by TemplateSel. 187 | // 188 | // This trick is necessary for simulating typedef for class templates, 189 | // which C++ doesn't support directly. 190 | template 191 | struct TemplateSel { 192 | template 193 | struct Bind { 194 | typedef Tmpl type; 195 | }; 196 | }; 197 | 198 | # define GTEST_BIND_(TmplSel, T) \ 199 | TmplSel::template Bind::type 200 | 201 | // A unique struct template used as the default value for the 202 | // arguments of class template Templates. This allows us to simulate 203 | // variadic templates (e.g. Templates, Templates, 204 | // and etc), which C++ doesn't support directly. 205 | template 206 | struct NoneT {}; 207 | 208 | // The following family of struct and struct templates are used to 209 | // represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except 211 | // for Templates0, every struct in the family has two member types: 212 | // Head for the selector of the first template in the list, and Tail 213 | // for the rest of the list. 214 | 215 | // The empty template list. 216 | struct Templates0 {}; 217 | 218 | // Template lists of length 1, 2, 3, and so on. 219 | 220 | template 221 | struct Templates1 { 222 | typedef TemplateSel Head; 223 | typedef Templates0 Tail; 224 | }; 225 | 226 | $range i 2..n 227 | 228 | $for i [[ 229 | $range j 1..i 230 | $range k 2..i 231 | template <$for j, [[GTEST_TEMPLATE_ T$j]]> 232 | struct Templates$i { 233 | typedef TemplateSel Head; 234 | typedef Templates$(i-1)<$for k, [[T$k]]> Tail; 235 | }; 236 | 237 | 238 | ]] 239 | 240 | // We don't want to require the users to write TemplatesN<...> directly, 241 | // as that would require them to count the length. Templates<...> is much 242 | // easier to write, but generates horrible messages when there is a 243 | // compiler error, as gcc insists on printing out each template 244 | // argument, even if it has the default value (this means Templates 245 | // will appear as Templates in the compiler 246 | // errors). 247 | // 248 | // Our solution is to combine the best part of the two approaches: a 249 | // user would write Templates, and Google Test will translate 250 | // that to TemplatesN internally to make error messages 251 | // readable. The translation is done by the 'type' member of the 252 | // Templates template. 253 | 254 | $range i 1..n 255 | template <$for i, [[GTEST_TEMPLATE_ T$i = NoneT]]> 256 | struct Templates { 257 | typedef Templates$n<$for i, [[T$i]]> type; 258 | }; 259 | 260 | template <> 261 | struct Templates<$for i, [[NoneT]]> { 262 | typedef Templates0 type; 263 | }; 264 | 265 | $range i 1..n-1 266 | $for i [[ 267 | $range j 1..i 268 | $range k i+1..n 269 | template <$for j, [[GTEST_TEMPLATE_ T$j]]> 270 | struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> { 271 | typedef Templates$i<$for j, [[T$j]]> type; 272 | }; 273 | 274 | ]] 275 | 276 | // The TypeList template makes it possible to use either a single type 277 | // or a Types<...> list in TYPED_TEST_CASE() and 278 | // INSTANTIATE_TYPED_TEST_CASE_P(). 279 | 280 | template 281 | struct TypeList { 282 | typedef Types1 type; 283 | }; 284 | 285 | 286 | $range i 1..n 287 | template <$for i, [[typename T$i]]> 288 | struct TypeList > { 289 | typedef typename Types<$for i, [[T$i]]>::type type; 290 | }; 291 | 292 | #endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P 293 | 294 | } // namespace internal 295 | } // namespace testing 296 | 297 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ 298 | -------------------------------------------------------------------------------- /3rdparty/gtest/include/gtest/internal/gtest-param-util-generated.h.pump: -------------------------------------------------------------------------------- 1 | $$ -*- mode: c++; -*- 2 | $var n = 50 $$ Maximum length of Values arguments we want to support. 3 | $var maxtuple = 10 $$ Maximum number of Combine arguments we want to support. 4 | // Copyright 2008 Google Inc. 5 | // All Rights Reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are 9 | // met: 10 | // 11 | // * Redistributions of source code must retain the above copyright 12 | // notice, this list of conditions and the following disclaimer. 13 | // * Redistributions in binary form must reproduce the above 14 | // copyright notice, this list of conditions and the following disclaimer 15 | // in the documentation and/or other materials provided with the 16 | // distribution. 17 | // * Neither the name of Google Inc. nor the names of its 18 | // contributors may be used to endorse or promote products derived from 19 | // this software without specific prior written permission. 20 | // 21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | // 33 | // Author: vladl@google.com (Vlad Losev) 34 | 35 | // Type and function utilities for implementing parameterized tests. 36 | // This file is generated by a SCRIPT. DO NOT EDIT BY HAND! 37 | // 38 | // Currently Google Test supports at most $n arguments in Values, 39 | // and at most $maxtuple arguments in Combine. Please contact 40 | // googletestframework@googlegroups.com if you need more. 41 | // Please note that the number of arguments to Combine is limited 42 | // by the maximum arity of the implementation of tr1::tuple which is 43 | // currently set at $maxtuple. 44 | 45 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ 46 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ 47 | 48 | // scripts/fuse_gtest.py depends on gtest's own header being #included 49 | // *unconditionally*. Therefore these #includes cannot be moved 50 | // inside #if GTEST_HAS_PARAM_TEST. 51 | #include "gtest/internal/gtest-param-util.h" 52 | #include "gtest/internal/gtest-port.h" 53 | 54 | #if GTEST_HAS_PARAM_TEST 55 | 56 | namespace testing { 57 | 58 | // Forward declarations of ValuesIn(), which is implemented in 59 | // include/gtest/gtest-param-test.h. 60 | template 61 | internal::ParamGenerator< 62 | typename ::testing::internal::IteratorTraits::value_type> 63 | ValuesIn(ForwardIterator begin, ForwardIterator end); 64 | 65 | template 66 | internal::ParamGenerator ValuesIn(const T (&array)[N]); 67 | 68 | template 69 | internal::ParamGenerator ValuesIn( 70 | const Container& container); 71 | 72 | namespace internal { 73 | 74 | // Used in the Values() function to provide polymorphic capabilities. 75 | template 76 | class ValueArray1 { 77 | public: 78 | explicit ValueArray1(T1 v1) : v1_(v1) {} 79 | 80 | template 81 | operator ParamGenerator() const { return ValuesIn(&v1_, &v1_ + 1); } 82 | 83 | private: 84 | // No implementation - assignment is unsupported. 85 | void operator=(const ValueArray1& other); 86 | 87 | const T1 v1_; 88 | }; 89 | 90 | $range i 2..n 91 | $for i [[ 92 | $range j 1..i 93 | 94 | template <$for j, [[typename T$j]]> 95 | class ValueArray$i { 96 | public: 97 | ValueArray$i($for j, [[T$j v$j]]) : $for j, [[v$(j)_(v$j)]] {} 98 | 99 | template 100 | operator ParamGenerator() const { 101 | const T array[] = {$for j, [[static_cast(v$(j)_)]]}; 102 | return ValuesIn(array); 103 | } 104 | 105 | private: 106 | // No implementation - assignment is unsupported. 107 | void operator=(const ValueArray$i& other); 108 | 109 | $for j [[ 110 | 111 | const T$j v$(j)_; 112 | ]] 113 | 114 | }; 115 | 116 | ]] 117 | 118 | # if GTEST_HAS_COMBINE 119 | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. 120 | // 121 | // Generates values from the Cartesian product of values produced 122 | // by the argument generators. 123 | // 124 | $range i 2..maxtuple 125 | $for i [[ 126 | $range j 1..i 127 | $range k 2..i 128 | 129 | template <$for j, [[typename T$j]]> 130 | class CartesianProductGenerator$i 131 | : public ParamGeneratorInterface< ::std::tr1::tuple<$for j, [[T$j]]> > { 132 | public: 133 | typedef ::std::tr1::tuple<$for j, [[T$j]]> ParamType; 134 | 135 | CartesianProductGenerator$i($for j, [[const ParamGenerator& g$j]]) 136 | : $for j, [[g$(j)_(g$j)]] {} 137 | virtual ~CartesianProductGenerator$i() {} 138 | 139 | virtual ParamIteratorInterface* Begin() const { 140 | return new Iterator(this, $for j, [[g$(j)_, g$(j)_.begin()]]); 141 | } 142 | virtual ParamIteratorInterface* End() const { 143 | return new Iterator(this, $for j, [[g$(j)_, g$(j)_.end()]]); 144 | } 145 | 146 | private: 147 | class Iterator : public ParamIteratorInterface { 148 | public: 149 | Iterator(const ParamGeneratorInterface* base, $for j, [[ 150 | 151 | const ParamGenerator& g$j, 152 | const typename ParamGenerator::iterator& current$(j)]]) 153 | : base_(base), 154 | $for j, [[ 155 | 156 | begin$(j)_(g$j.begin()), end$(j)_(g$j.end()), current$(j)_(current$j) 157 | ]] { 158 | ComputeCurrentValue(); 159 | } 160 | virtual ~Iterator() {} 161 | 162 | virtual const ParamGeneratorInterface* BaseGenerator() const { 163 | return base_; 164 | } 165 | // Advance should not be called on beyond-of-range iterators 166 | // so no component iterators must be beyond end of range, either. 167 | virtual void Advance() { 168 | assert(!AtEnd()); 169 | ++current$(i)_; 170 | 171 | $for k [[ 172 | if (current$(i+2-k)_ == end$(i+2-k)_) { 173 | current$(i+2-k)_ = begin$(i+2-k)_; 174 | ++current$(i+2-k-1)_; 175 | } 176 | 177 | ]] 178 | ComputeCurrentValue(); 179 | } 180 | virtual ParamIteratorInterface* Clone() const { 181 | return new Iterator(*this); 182 | } 183 | virtual const ParamType* Current() const { return ¤t_value_; } 184 | virtual bool Equals(const ParamIteratorInterface& other) const { 185 | // Having the same base generator guarantees that the other 186 | // iterator is of the same type and we can downcast. 187 | GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) 188 | << "The program attempted to compare iterators " 189 | << "from different generators." << std::endl; 190 | const Iterator* typed_other = 191 | CheckedDowncastToActualType(&other); 192 | // We must report iterators equal if they both point beyond their 193 | // respective ranges. That can happen in a variety of fashions, 194 | // so we have to consult AtEnd(). 195 | return (AtEnd() && typed_other->AtEnd()) || 196 | ($for j && [[ 197 | 198 | current$(j)_ == typed_other->current$(j)_ 199 | ]]); 200 | } 201 | 202 | private: 203 | Iterator(const Iterator& other) 204 | : base_(other.base_), $for j, [[ 205 | 206 | begin$(j)_(other.begin$(j)_), 207 | end$(j)_(other.end$(j)_), 208 | current$(j)_(other.current$(j)_) 209 | ]] { 210 | ComputeCurrentValue(); 211 | } 212 | 213 | void ComputeCurrentValue() { 214 | if (!AtEnd()) 215 | current_value_ = ParamType($for j, [[*current$(j)_]]); 216 | } 217 | bool AtEnd() const { 218 | // We must report iterator past the end of the range when either of the 219 | // component iterators has reached the end of its range. 220 | return 221 | $for j || [[ 222 | 223 | current$(j)_ == end$(j)_ 224 | ]]; 225 | } 226 | 227 | // No implementation - assignment is unsupported. 228 | void operator=(const Iterator& other); 229 | 230 | const ParamGeneratorInterface* const base_; 231 | // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. 232 | // current[i]_ is the actual traversing iterator. 233 | $for j [[ 234 | 235 | const typename ParamGenerator::iterator begin$(j)_; 236 | const typename ParamGenerator::iterator end$(j)_; 237 | typename ParamGenerator::iterator current$(j)_; 238 | ]] 239 | 240 | ParamType current_value_; 241 | }; // class CartesianProductGenerator$i::Iterator 242 | 243 | // No implementation - assignment is unsupported. 244 | void operator=(const CartesianProductGenerator$i& other); 245 | 246 | 247 | $for j [[ 248 | const ParamGenerator g$(j)_; 249 | 250 | ]] 251 | }; // class CartesianProductGenerator$i 252 | 253 | 254 | ]] 255 | 256 | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. 257 | // 258 | // Helper classes providing Combine() with polymorphic features. They allow 259 | // casting CartesianProductGeneratorN to ParamGenerator if T is 260 | // convertible to U. 261 | // 262 | $range i 2..maxtuple 263 | $for i [[ 264 | $range j 1..i 265 | 266 | template <$for j, [[class Generator$j]]> 267 | class CartesianProductHolder$i { 268 | public: 269 | CartesianProductHolder$i($for j, [[const Generator$j& g$j]]) 270 | : $for j, [[g$(j)_(g$j)]] {} 271 | template <$for j, [[typename T$j]]> 272 | operator ParamGenerator< ::std::tr1::tuple<$for j, [[T$j]]> >() const { 273 | return ParamGenerator< ::std::tr1::tuple<$for j, [[T$j]]> >( 274 | new CartesianProductGenerator$i<$for j, [[T$j]]>( 275 | $for j,[[ 276 | 277 | static_cast >(g$(j)_) 278 | ]])); 279 | } 280 | 281 | private: 282 | // No implementation - assignment is unsupported. 283 | void operator=(const CartesianProductHolder$i& other); 284 | 285 | 286 | $for j [[ 287 | const Generator$j g$(j)_; 288 | 289 | ]] 290 | }; // class CartesianProductHolder$i 291 | 292 | ]] 293 | 294 | # endif // GTEST_HAS_COMBINE 295 | 296 | } // namespace internal 297 | } // namespace testing 298 | 299 | #endif // GTEST_HAS_PARAM_TEST 300 | 301 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ 302 | -------------------------------------------------------------------------------- /3rdparty/gtest/include/gtest/internal/gtest-tuple.h.pump: -------------------------------------------------------------------------------- 1 | $$ -*- mode: c++; -*- 2 | $var n = 10 $$ Maximum number of tuple fields we want to support. 3 | $$ This meta comment fixes auto-indentation in Emacs. }} 4 | // Copyright 2009 Google Inc. 5 | // All Rights Reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are 9 | // met: 10 | // 11 | // * Redistributions of source code must retain the above copyright 12 | // notice, this list of conditions and the following disclaimer. 13 | // * Redistributions in binary form must reproduce the above 14 | // copyright notice, this list of conditions and the following disclaimer 15 | // in the documentation and/or other materials provided with the 16 | // distribution. 17 | // * Neither the name of Google Inc. nor the names of its 18 | // contributors may be used to endorse or promote products derived from 19 | // this software without specific prior written permission. 20 | // 21 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | // 33 | // Author: wan@google.com (Zhanyong Wan) 34 | 35 | // Implements a subset of TR1 tuple needed by Google Test and Google Mock. 36 | 37 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ 38 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ 39 | 40 | #include // For ::std::pair. 41 | 42 | // The compiler used in Symbian has a bug that prevents us from declaring the 43 | // tuple template as a friend (it complains that tuple is redefined). This 44 | // hack bypasses the bug by declaring the members that should otherwise be 45 | // private as public. 46 | // Sun Studio versions < 12 also have the above bug. 47 | #if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) 48 | # define GTEST_DECLARE_TUPLE_AS_FRIEND_ public: 49 | #else 50 | # define GTEST_DECLARE_TUPLE_AS_FRIEND_ \ 51 | template friend class tuple; \ 52 | private: 53 | #endif 54 | 55 | 56 | $range i 0..n-1 57 | $range j 0..n 58 | $range k 1..n 59 | // GTEST_n_TUPLE_(T) is the type of an n-tuple. 60 | #define GTEST_0_TUPLE_(T) tuple<> 61 | 62 | $for k [[ 63 | $range m 0..k-1 64 | $range m2 k..n-1 65 | #define GTEST_$(k)_TUPLE_(T) tuple<$for m, [[T##$m]]$for m2 [[, void]]> 66 | 67 | ]] 68 | 69 | // GTEST_n_TYPENAMES_(T) declares a list of n typenames. 70 | 71 | $for j [[ 72 | $range m 0..j-1 73 | #define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]] 74 | 75 | 76 | ]] 77 | 78 | // In theory, defining stuff in the ::std namespace is undefined 79 | // behavior. We can do this as we are playing the role of a standard 80 | // library vendor. 81 | namespace std { 82 | namespace tr1 { 83 | 84 | template <$for i, [[typename T$i = void]]> 85 | class tuple; 86 | 87 | // Anything in namespace gtest_internal is Google Test's INTERNAL 88 | // IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code. 89 | namespace gtest_internal { 90 | 91 | // ByRef::type is T if T is a reference; otherwise it's const T&. 92 | template 93 | struct ByRef { typedef const T& type; }; // NOLINT 94 | template 95 | struct ByRef { typedef T& type; }; // NOLINT 96 | 97 | // A handy wrapper for ByRef. 98 | #define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef::type 99 | 100 | // AddRef::type is T if T is a reference; otherwise it's T&. This 101 | // is the same as tr1::add_reference::type. 102 | template 103 | struct AddRef { typedef T& type; }; // NOLINT 104 | template 105 | struct AddRef { typedef T& type; }; // NOLINT 106 | 107 | // A handy wrapper for AddRef. 108 | #define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef::type 109 | 110 | // A helper for implementing get(). 111 | template class Get; 112 | 113 | // A helper for implementing tuple_element. kIndexValid is true 114 | // iff k < the number of fields in tuple type T. 115 | template 116 | struct TupleElement; 117 | 118 | 119 | $for i [[ 120 | template 121 | struct TupleElement { 122 | typedef T$i type; 123 | }; 124 | 125 | 126 | ]] 127 | } // namespace gtest_internal 128 | 129 | template <> 130 | class tuple<> { 131 | public: 132 | tuple() {} 133 | tuple(const tuple& /* t */) {} 134 | tuple& operator=(const tuple& /* t */) { return *this; } 135 | }; 136 | 137 | 138 | $for k [[ 139 | $range m 0..k-1 140 | template 141 | class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] { 142 | public: 143 | template friend class gtest_internal::Get; 144 | 145 | tuple() : $for m, [[f$(m)_()]] {} 146 | 147 | explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]] 148 | $for m, [[f$(m)_(f$m)]] {} 149 | 150 | tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {} 151 | 152 | template 153 | tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {} 154 | 155 | $if k == 2 [[ 156 | template 157 | tuple(const ::std::pair& p) : f0_(p.first), f1_(p.second) {} 158 | 159 | ]] 160 | 161 | tuple& operator=(const tuple& t) { return CopyFrom(t); } 162 | 163 | template 164 | tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) { 165 | return CopyFrom(t); 166 | } 167 | 168 | $if k == 2 [[ 169 | template 170 | tuple& operator=(const ::std::pair& p) { 171 | f0_ = p.first; 172 | f1_ = p.second; 173 | return *this; 174 | } 175 | 176 | ]] 177 | 178 | GTEST_DECLARE_TUPLE_AS_FRIEND_ 179 | 180 | template 181 | tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) { 182 | 183 | $for m [[ 184 | f$(m)_ = t.f$(m)_; 185 | 186 | ]] 187 | return *this; 188 | } 189 | 190 | 191 | $for m [[ 192 | T$m f$(m)_; 193 | 194 | ]] 195 | }; 196 | 197 | 198 | ]] 199 | // 6.1.3.2 Tuple creation functions. 200 | 201 | // Known limitations: we don't support passing an 202 | // std::tr1::reference_wrapper to make_tuple(). And we don't 203 | // implement tie(). 204 | 205 | inline tuple<> make_tuple() { return tuple<>(); } 206 | 207 | $for k [[ 208 | $range m 0..k-1 209 | 210 | template 211 | inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) { 212 | return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]); 213 | } 214 | 215 | ]] 216 | 217 | // 6.1.3.3 Tuple helper classes. 218 | 219 | template struct tuple_size; 220 | 221 | 222 | $for j [[ 223 | template 224 | struct tuple_size { 225 | static const int value = $j; 226 | }; 227 | 228 | 229 | ]] 230 | template 231 | struct tuple_element { 232 | typedef typename gtest_internal::TupleElement< 233 | k < (tuple_size::value), k, Tuple>::type type; 234 | }; 235 | 236 | #define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element::type 237 | 238 | // 6.1.3.4 Element access. 239 | 240 | namespace gtest_internal { 241 | 242 | 243 | $for i [[ 244 | template <> 245 | class Get<$i> { 246 | public: 247 | template 248 | static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple)) 249 | Field(Tuple& t) { return t.f$(i)_; } // NOLINT 250 | 251 | template 252 | static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple)) 253 | ConstField(const Tuple& t) { return t.f$(i)_; } 254 | }; 255 | 256 | 257 | ]] 258 | } // namespace gtest_internal 259 | 260 | template 261 | GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T))) 262 | get(GTEST_$(n)_TUPLE_(T)& t) { 263 | return gtest_internal::Get::Field(t); 264 | } 265 | 266 | template 267 | GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T))) 268 | get(const GTEST_$(n)_TUPLE_(T)& t) { 269 | return gtest_internal::Get::ConstField(t); 270 | } 271 | 272 | // 6.1.3.5 Relational operators 273 | 274 | // We only implement == and !=, as we don't have a need for the rest yet. 275 | 276 | namespace gtest_internal { 277 | 278 | // SameSizeTuplePrefixComparator::Eq(t1, t2) returns true if the 279 | // first k fields of t1 equals the first k fields of t2. 280 | // SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if 281 | // k1 != k2. 282 | template 283 | struct SameSizeTuplePrefixComparator; 284 | 285 | template <> 286 | struct SameSizeTuplePrefixComparator<0, 0> { 287 | template 288 | static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { 289 | return true; 290 | } 291 | }; 292 | 293 | template 294 | struct SameSizeTuplePrefixComparator { 295 | template 296 | static bool Eq(const Tuple1& t1, const Tuple2& t2) { 297 | return SameSizeTuplePrefixComparator::Eq(t1, t2) && 298 | ::std::tr1::get(t1) == ::std::tr1::get(t2); 299 | } 300 | }; 301 | 302 | } // namespace gtest_internal 303 | 304 | template 305 | inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t, 306 | const GTEST_$(n)_TUPLE_(U)& u) { 307 | return gtest_internal::SameSizeTuplePrefixComparator< 308 | tuple_size::value, 309 | tuple_size::value>::Eq(t, u); 310 | } 311 | 312 | template 313 | inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t, 314 | const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); } 315 | 316 | // 6.1.4 Pairs. 317 | // Unimplemented. 318 | 319 | } // namespace tr1 320 | } // namespace std 321 | 322 | 323 | $for j [[ 324 | #undef GTEST_$(j)_TUPLE_ 325 | 326 | ]] 327 | 328 | 329 | $for j [[ 330 | #undef GTEST_$(j)_TYPENAMES_ 331 | 332 | ]] 333 | 334 | #undef GTEST_DECLARE_TUPLE_AS_FRIEND_ 335 | #undef GTEST_BY_REF_ 336 | #undef GTEST_ADD_REF_ 337 | #undef GTEST_TUPLE_ELEMENT_ 338 | 339 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ 340 | -------------------------------------------------------------------------------- /3rdparty/gtest/include/gtest/gtest-spi.h: -------------------------------------------------------------------------------- 1 | // Copyright 2007, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | // 32 | // Utilities for testing Google Test itself and code that uses Google Test 33 | // (e.g. frameworks built on top of Google Test). 34 | 35 | #ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_ 36 | #define GTEST_INCLUDE_GTEST_GTEST_SPI_H_ 37 | 38 | #include "gtest/gtest.h" 39 | 40 | namespace testing { 41 | 42 | // This helper class can be used to mock out Google Test failure reporting 43 | // so that we can test Google Test or code that builds on Google Test. 44 | // 45 | // An object of this class appends a TestPartResult object to the 46 | // TestPartResultArray object given in the constructor whenever a Google Test 47 | // failure is reported. It can either intercept only failures that are 48 | // generated in the same thread that created this object or it can intercept 49 | // all generated failures. The scope of this mock object can be controlled with 50 | // the second argument to the two arguments constructor. 51 | class GTEST_API_ ScopedFakeTestPartResultReporter 52 | : public TestPartResultReporterInterface { 53 | public: 54 | // The two possible mocking modes of this object. 55 | enum InterceptMode { 56 | INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures. 57 | INTERCEPT_ALL_THREADS // Intercepts all failures. 58 | }; 59 | 60 | // The c'tor sets this object as the test part result reporter used 61 | // by Google Test. The 'result' parameter specifies where to report the 62 | // results. This reporter will only catch failures generated in the current 63 | // thread. DEPRECATED 64 | explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result); 65 | 66 | // Same as above, but you can choose the interception scope of this object. 67 | ScopedFakeTestPartResultReporter(InterceptMode intercept_mode, 68 | TestPartResultArray* result); 69 | 70 | // The d'tor restores the previous test part result reporter. 71 | virtual ~ScopedFakeTestPartResultReporter(); 72 | 73 | // Appends the TestPartResult object to the TestPartResultArray 74 | // received in the constructor. 75 | // 76 | // This method is from the TestPartResultReporterInterface 77 | // interface. 78 | virtual void ReportTestPartResult(const TestPartResult& result); 79 | private: 80 | void Init(); 81 | 82 | const InterceptMode intercept_mode_; 83 | TestPartResultReporterInterface* old_reporter_; 84 | TestPartResultArray* const result_; 85 | 86 | GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter); 87 | }; 88 | 89 | namespace internal { 90 | 91 | // A helper class for implementing EXPECT_FATAL_FAILURE() and 92 | // EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given 93 | // TestPartResultArray contains exactly one failure that has the given 94 | // type and contains the given substring. If that's not the case, a 95 | // non-fatal failure will be generated. 96 | class GTEST_API_ SingleFailureChecker { 97 | public: 98 | // The constructor remembers the arguments. 99 | SingleFailureChecker(const TestPartResultArray* results, 100 | TestPartResult::Type type, 101 | const string& substr); 102 | ~SingleFailureChecker(); 103 | private: 104 | const TestPartResultArray* const results_; 105 | const TestPartResult::Type type_; 106 | const string substr_; 107 | 108 | GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker); 109 | }; 110 | 111 | } // namespace internal 112 | 113 | } // namespace testing 114 | 115 | // A set of macros for testing Google Test assertions or code that's expected 116 | // to generate Google Test fatal failures. It verifies that the given 117 | // statement will cause exactly one fatal Google Test failure with 'substr' 118 | // being part of the failure message. 119 | // 120 | // There are two different versions of this macro. EXPECT_FATAL_FAILURE only 121 | // affects and considers failures generated in the current thread and 122 | // EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. 123 | // 124 | // The verification of the assertion is done correctly even when the statement 125 | // throws an exception or aborts the current function. 126 | // 127 | // Known restrictions: 128 | // - 'statement' cannot reference local non-static variables or 129 | // non-static members of the current object. 130 | // - 'statement' cannot return a value. 131 | // - You cannot stream a failure message to this macro. 132 | // 133 | // Note that even though the implementations of the following two 134 | // macros are much alike, we cannot refactor them to use a common 135 | // helper macro, due to some peculiarity in how the preprocessor 136 | // works. The AcceptsMacroThatExpandsToUnprotectedComma test in 137 | // gtest_unittest.cc will fail to compile if we do that. 138 | #define EXPECT_FATAL_FAILURE(statement, substr) \ 139 | do { \ 140 | class GTestExpectFatalFailureHelper {\ 141 | public:\ 142 | static void Execute() { statement; }\ 143 | };\ 144 | ::testing::TestPartResultArray gtest_failures;\ 145 | ::testing::internal::SingleFailureChecker gtest_checker(\ 146 | >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ 147 | {\ 148 | ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ 149 | ::testing::ScopedFakeTestPartResultReporter:: \ 150 | INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ 151 | GTestExpectFatalFailureHelper::Execute();\ 152 | }\ 153 | } while (::testing::internal::AlwaysFalse()) 154 | 155 | #define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ 156 | do { \ 157 | class GTestExpectFatalFailureHelper {\ 158 | public:\ 159 | static void Execute() { statement; }\ 160 | };\ 161 | ::testing::TestPartResultArray gtest_failures;\ 162 | ::testing::internal::SingleFailureChecker gtest_checker(\ 163 | >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ 164 | {\ 165 | ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ 166 | ::testing::ScopedFakeTestPartResultReporter:: \ 167 | INTERCEPT_ALL_THREADS, >est_failures);\ 168 | GTestExpectFatalFailureHelper::Execute();\ 169 | }\ 170 | } while (::testing::internal::AlwaysFalse()) 171 | 172 | // A macro for testing Google Test assertions or code that's expected to 173 | // generate Google Test non-fatal failures. It asserts that the given 174 | // statement will cause exactly one non-fatal Google Test failure with 'substr' 175 | // being part of the failure message. 176 | // 177 | // There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only 178 | // affects and considers failures generated in the current thread and 179 | // EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. 180 | // 181 | // 'statement' is allowed to reference local variables and members of 182 | // the current object. 183 | // 184 | // The verification of the assertion is done correctly even when the statement 185 | // throws an exception or aborts the current function. 186 | // 187 | // Known restrictions: 188 | // - You cannot stream a failure message to this macro. 189 | // 190 | // Note that even though the implementations of the following two 191 | // macros are much alike, we cannot refactor them to use a common 192 | // helper macro, due to some peculiarity in how the preprocessor 193 | // works. If we do that, the code won't compile when the user gives 194 | // EXPECT_NONFATAL_FAILURE() a statement that contains a macro that 195 | // expands to code containing an unprotected comma. The 196 | // AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc 197 | // catches that. 198 | // 199 | // For the same reason, we have to write 200 | // if (::testing::internal::AlwaysTrue()) { statement; } 201 | // instead of 202 | // GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) 203 | // to avoid an MSVC warning on unreachable code. 204 | #define EXPECT_NONFATAL_FAILURE(statement, substr) \ 205 | do {\ 206 | ::testing::TestPartResultArray gtest_failures;\ 207 | ::testing::internal::SingleFailureChecker gtest_checker(\ 208 | >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ 209 | (substr));\ 210 | {\ 211 | ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ 212 | ::testing::ScopedFakeTestPartResultReporter:: \ 213 | INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ 214 | if (::testing::internal::AlwaysTrue()) { statement; }\ 215 | }\ 216 | } while (::testing::internal::AlwaysFalse()) 217 | 218 | #define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ 219 | do {\ 220 | ::testing::TestPartResultArray gtest_failures;\ 221 | ::testing::internal::SingleFailureChecker gtest_checker(\ 222 | >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ 223 | (substr));\ 224 | {\ 225 | ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ 226 | ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \ 227 | >est_failures);\ 228 | if (::testing::internal::AlwaysTrue()) { statement; }\ 229 | }\ 230 | } while (::testing::internal::AlwaysFalse()) 231 | 232 | #endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_ 233 | --------------------------------------------------------------------------------