├── .gitignore ├── 3rdparty └── googletest │ ├── .gitignore │ ├── README.md │ ├── core.mk │ ├── inc │ └── gtest │ │ ├── gtest-death-test.h │ │ ├── gtest-message.h │ │ ├── gtest-param-test.h │ │ ├── gtest-param-test.h.pump │ │ ├── gtest-printers.h │ │ ├── gtest-spi.h │ │ ├── gtest-test-part.h │ │ ├── gtest-typed-test.h │ │ ├── gtest.h │ │ ├── gtest_pred_impl.h │ │ ├── gtest_prod.h │ │ └── internal │ │ ├── custom │ │ ├── gtest-port.h │ │ ├── gtest-printers.h │ │ └── gtest.h │ │ ├── gtest-death-test-internal.h │ │ ├── gtest-filepath.h │ │ ├── gtest-internal.h │ │ ├── gtest-linked_ptr.h │ │ ├── gtest-param-util-generated.h │ │ ├── gtest-param-util-generated.h.pump │ │ ├── gtest-param-util.h │ │ ├── gtest-port-arch.h │ │ ├── gtest-port.h │ │ ├── gtest-string.h │ │ ├── gtest-tuple.h │ │ ├── gtest-tuple.h.pump │ │ ├── gtest-type-util.h │ │ └── gtest-type-util.h.pump │ ├── makefile │ ├── misc │ ├── CHANGES │ ├── CONTRIBUTORS │ └── LICENSE │ └── src │ ├── CustomTestPrinter.cpp │ ├── gtest-death-test.cc │ ├── gtest-filepath.cc │ ├── gtest-internal-inl.h │ ├── gtest-port.cc │ ├── gtest-printers.cc │ ├── gtest-test-part.cc │ ├── gtest-typed-test.cc │ └── gtest.cc ├── core.mk ├── inc └── BSignals │ ├── ExecutorScheme.h │ ├── Signal.hpp │ └── details │ ├── AsynchronousSlot.hpp │ ├── BasicTimer.h │ ├── ContiguousMPMCQueue.hpp │ ├── DeferredSlot.hpp │ ├── MPSCQueue.hpp │ ├── Semaphore.h │ ├── SharedMutex.h │ ├── SignalImpl.hpp │ ├── Slot.hpp │ ├── StrandSlot.hpp │ ├── SynchronousSlot.hpp │ ├── ThreadPooledSlot.hpp │ ├── Wheel.hpp │ └── WheeledThreadPool.h ├── license ├── makefile ├── readme.md ├── src └── details │ ├── BasicTimer.cpp │ ├── Semaphore.cpp │ ├── SharedMutex.cpp │ └── WheeledThreadPool.cpp └── test ├── FunctionTimeRegular.hpp ├── SafeQueue.hpp ├── SignalTest.cpp ├── SignalTest.h ├── SignalTest_Parametrized.cpp └── SignalTest_Parametrized.h /.gitignore: -------------------------------------------------------------------------------- 1 | /gen/ 2 | /nbproject/ 3 | -------------------------------------------------------------------------------- /3rdparty/googletest/.gitignore: -------------------------------------------------------------------------------- 1 | /gen/ 2 | /nbproject/ 3 | -------------------------------------------------------------------------------- /3rdparty/googletest/README.md: -------------------------------------------------------------------------------- 1 | ### Googletest Variant ### 2 | 3 | This is a lightweight variant of the google test library with 4 | - unit tests stripped out 5 | - a custom makefile 6 | - a custom printer class 7 | 8 | License file can be found in the misc directory 9 | 10 | Original googletest code: https://github.com/google/googletest 11 | -------------------------------------------------------------------------------- /3rdparty/googletest/inc/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/googletest/inc/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 | -------------------------------------------------------------------------------- /3rdparty/googletest/inc/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/googletest/inc/gtest/gtest-typed-test.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: wan@google.com (Zhanyong Wan) 31 | 32 | #ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ 33 | #define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ 34 | 35 | // This header implements typed tests and type-parameterized tests. 36 | 37 | // Typed (aka type-driven) tests repeat the same test for types in a 38 | // list. You must know which types you want to test with when writing 39 | // typed tests. Here's how you do it: 40 | 41 | #if 0 42 | 43 | // First, define a fixture class template. It should be parameterized 44 | // by a type. Remember to derive it from testing::Test. 45 | template 46 | class FooTest : public testing::Test { 47 | public: 48 | ... 49 | typedef std::list List; 50 | static T shared_; 51 | T value_; 52 | }; 53 | 54 | // Next, associate a list of types with the test case, which will be 55 | // repeated for each type in the list. The typedef is necessary for 56 | // the macro to parse correctly. 57 | typedef testing::Types MyTypes; 58 | TYPED_TEST_CASE(FooTest, MyTypes); 59 | 60 | // If the type list contains only one type, you can write that type 61 | // directly without Types<...>: 62 | // TYPED_TEST_CASE(FooTest, int); 63 | 64 | // Then, use TYPED_TEST() instead of TEST_F() to define as many typed 65 | // tests for this test case as you want. 66 | TYPED_TEST(FooTest, DoesBlah) { 67 | // Inside a test, refer to TypeParam to get the type parameter. 68 | // Since we are inside a derived class template, C++ requires use to 69 | // visit the members of FooTest via 'this'. 70 | TypeParam n = this->value_; 71 | 72 | // To visit static members of the fixture, add the TestFixture:: 73 | // prefix. 74 | n += TestFixture::shared_; 75 | 76 | // To refer to typedefs in the fixture, add the "typename 77 | // TestFixture::" prefix. 78 | typename TestFixture::List values; 79 | values.push_back(n); 80 | ... 81 | } 82 | 83 | TYPED_TEST(FooTest, HasPropertyA) { ... } 84 | 85 | #endif // 0 86 | 87 | // Type-parameterized tests are abstract test patterns parameterized 88 | // by a type. Compared with typed tests, type-parameterized tests 89 | // allow you to define the test pattern without knowing what the type 90 | // parameters are. The defined pattern can be instantiated with 91 | // different types any number of times, in any number of translation 92 | // units. 93 | // 94 | // If you are designing an interface or concept, you can define a 95 | // suite of type-parameterized tests to verify properties that any 96 | // valid implementation of the interface/concept should have. Then, 97 | // each implementation can easily instantiate the test suite to verify 98 | // that it conforms to the requirements, without having to write 99 | // similar tests repeatedly. Here's an example: 100 | 101 | #if 0 102 | 103 | // First, define a fixture class template. It should be parameterized 104 | // by a type. Remember to derive it from testing::Test. 105 | template 106 | class FooTest : public testing::Test { 107 | ... 108 | }; 109 | 110 | // Next, declare that you will define a type-parameterized test case 111 | // (the _P suffix is for "parameterized" or "pattern", whichever you 112 | // prefer): 113 | TYPED_TEST_CASE_P(FooTest); 114 | 115 | // Then, use TYPED_TEST_P() to define as many type-parameterized tests 116 | // for this type-parameterized test case as you want. 117 | TYPED_TEST_P(FooTest, DoesBlah) { 118 | // Inside a test, refer to TypeParam to get the type parameter. 119 | TypeParam n = 0; 120 | ... 121 | } 122 | 123 | TYPED_TEST_P(FooTest, HasPropertyA) { ... } 124 | 125 | // Now the tricky part: you need to register all test patterns before 126 | // you can instantiate them. The first argument of the macro is the 127 | // test case name; the rest are the names of the tests in this test 128 | // case. 129 | REGISTER_TYPED_TEST_CASE_P(FooTest, 130 | DoesBlah, HasPropertyA); 131 | 132 | // Finally, you are free to instantiate the pattern with the types you 133 | // want. If you put the above code in a header file, you can #include 134 | // it in multiple C++ source files and instantiate it multiple times. 135 | // 136 | // To distinguish different instances of the pattern, the first 137 | // argument to the INSTANTIATE_* macro is a prefix that will be added 138 | // to the actual test case name. Remember to pick unique prefixes for 139 | // different instances. 140 | typedef testing::Types MyTypes; 141 | INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); 142 | 143 | // If the type list contains only one type, you can write that type 144 | // directly without Types<...>: 145 | // INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int); 146 | 147 | #endif // 0 148 | 149 | #include "gtest/internal/gtest-port.h" 150 | #include "gtest/internal/gtest-type-util.h" 151 | 152 | // Implements typed tests. 153 | 154 | #if GTEST_HAS_TYPED_TEST 155 | 156 | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. 157 | // 158 | // Expands to the name of the typedef for the type parameters of the 159 | // given test case. 160 | # define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_ 161 | 162 | // The 'Types' template argument below must have spaces around it 163 | // since some compilers may choke on '>>' when passing a template 164 | // instance (e.g. Types) 165 | # define TYPED_TEST_CASE(CaseName, Types) \ 166 | typedef ::testing::internal::TypeList< Types >::type \ 167 | GTEST_TYPE_PARAMS_(CaseName) 168 | 169 | # define TYPED_TEST(CaseName, TestName) \ 170 | template \ 171 | class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ 172 | : public CaseName { \ 173 | private: \ 174 | typedef CaseName TestFixture; \ 175 | typedef gtest_TypeParam_ TypeParam; \ 176 | virtual void TestBody(); \ 177 | }; \ 178 | bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \ 179 | ::testing::internal::TypeParameterizedTest< \ 180 | CaseName, \ 181 | ::testing::internal::TemplateSel< \ 182 | GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \ 183 | GTEST_TYPE_PARAMS_(CaseName)>::Register(\ 184 | "", ::testing::internal::CodeLocation(__FILE__, __LINE__), \ 185 | #CaseName, #TestName, 0); \ 186 | template \ 187 | void GTEST_TEST_CLASS_NAME_(CaseName, TestName)::TestBody() 188 | 189 | #endif // GTEST_HAS_TYPED_TEST 190 | 191 | // Implements type-parameterized tests. 192 | 193 | #if GTEST_HAS_TYPED_TEST_P 194 | 195 | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. 196 | // 197 | // Expands to the namespace name that the type-parameterized tests for 198 | // the given type-parameterized test case are defined in. The exact 199 | // name of the namespace is subject to change without notice. 200 | # define GTEST_CASE_NAMESPACE_(TestCaseName) \ 201 | gtest_case_##TestCaseName##_ 202 | 203 | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. 204 | // 205 | // Expands to the name of the variable used to remember the names of 206 | // the defined tests in the given test case. 207 | # define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \ 208 | gtest_typed_test_case_p_state_##TestCaseName##_ 209 | 210 | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY. 211 | // 212 | // Expands to the name of the variable used to remember the names of 213 | // the registered tests in the given test case. 214 | # define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \ 215 | gtest_registered_test_names_##TestCaseName##_ 216 | 217 | // The variables defined in the type-parameterized test macros are 218 | // static as typically these macros are used in a .h file that can be 219 | // #included in multiple translation units linked together. 220 | # define TYPED_TEST_CASE_P(CaseName) \ 221 | static ::testing::internal::TypedTestCasePState \ 222 | GTEST_TYPED_TEST_CASE_P_STATE_(CaseName) 223 | 224 | # define TYPED_TEST_P(CaseName, TestName) \ 225 | namespace GTEST_CASE_NAMESPACE_(CaseName) { \ 226 | template \ 227 | class TestName : public CaseName { \ 228 | private: \ 229 | typedef CaseName TestFixture; \ 230 | typedef gtest_TypeParam_ TypeParam; \ 231 | virtual void TestBody(); \ 232 | }; \ 233 | static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \ 234 | GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\ 235 | __FILE__, __LINE__, #CaseName, #TestName); \ 236 | } \ 237 | template \ 238 | void GTEST_CASE_NAMESPACE_(CaseName)::TestName::TestBody() 239 | 240 | # define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \ 241 | namespace GTEST_CASE_NAMESPACE_(CaseName) { \ 242 | typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \ 243 | } \ 244 | static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \ 245 | GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\ 246 | __FILE__, __LINE__, #__VA_ARGS__) 247 | 248 | // The 'Types' template argument below must have spaces around it 249 | // since some compilers may choke on '>>' when passing a template 250 | // instance (e.g. Types) 251 | # define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \ 252 | bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \ 253 | ::testing::internal::TypeParameterizedTestCase::type>::Register(\ 256 | #Prefix, \ 257 | ::testing::internal::CodeLocation(__FILE__, __LINE__), \ 258 | >EST_TYPED_TEST_CASE_P_STATE_(CaseName), \ 259 | #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName)) 260 | 261 | #endif // GTEST_HAS_TYPED_TEST_P 262 | 263 | #endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ 264 | -------------------------------------------------------------------------------- /3rdparty/googletest/inc/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 | -------------------------------------------------------------------------------- /3rdparty/googletest/inc/gtest/internal/custom/gtest-port.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015, 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 | // Injection point for custom user configurations. 31 | // The following macros can be defined: 32 | // 33 | // Flag related macros: 34 | // GTEST_FLAG(flag_name) 35 | // GTEST_USE_OWN_FLAGFILE_FLAG_ - Define to 0 when the system provides its 36 | // own flagfile flag parsing. 37 | // GTEST_DECLARE_bool_(name) 38 | // GTEST_DECLARE_int32_(name) 39 | // GTEST_DECLARE_string_(name) 40 | // GTEST_DEFINE_bool_(name, default_val, doc) 41 | // GTEST_DEFINE_int32_(name, default_val, doc) 42 | // GTEST_DEFINE_string_(name, default_val, doc) 43 | // 44 | // Test filtering: 45 | // GTEST_TEST_FILTER_ENV_VAR_ - The name of an environment variable that 46 | // will be used if --GTEST_FLAG(test_filter) 47 | // is not provided. 48 | // 49 | // Logging: 50 | // GTEST_LOG_(severity) 51 | // GTEST_CHECK_(condition) 52 | // Functions LogToStderr() and FlushInfoLog() have to be provided too. 53 | // 54 | // Threading: 55 | // GTEST_HAS_NOTIFICATION_ - Enabled if Notification is already provided. 56 | // GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ - Enabled if Mutex and ThreadLocal are 57 | // already provided. 58 | // Must also provide GTEST_DECLARE_STATIC_MUTEX_(mutex) and 59 | // GTEST_DEFINE_STATIC_MUTEX_(mutex) 60 | // 61 | // GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks) 62 | // GTEST_LOCK_EXCLUDED_(locks) 63 | // 64 | // ** Custom implementation starts here ** 65 | 66 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ 67 | #define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ 68 | 69 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ 70 | -------------------------------------------------------------------------------- /3rdparty/googletest/inc/gtest/internal/custom/gtest-printers.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015, 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 | // This file provides an injection point for custom printers in a local 31 | // installation of gTest. 32 | // It will be included from gtest-printers.h and the overrides in this file 33 | // will be visible to everyone. 34 | // See documentation at gtest/gtest-printers.h for details on how to define a 35 | // custom printer. 36 | // 37 | // ** Custom implementation starts here ** 38 | 39 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ 40 | #define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ 41 | 42 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ 43 | -------------------------------------------------------------------------------- /3rdparty/googletest/inc/gtest/internal/custom/gtest.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015, 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 | // Injection point for custom user configurations. 31 | // The following macros can be defined: 32 | // 33 | // GTEST_OS_STACK_TRACE_GETTER_ - The name of an implementation of 34 | // OsStackTraceGetterInterface. 35 | // 36 | // ** Custom implementation starts here ** 37 | 38 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ 39 | #define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ 40 | 41 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ 42 | -------------------------------------------------------------------------------- /3rdparty/googletest/inc/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/googletest/inc/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) { 114 | assert(p->next_ != this && 115 | "Trying to join() a linked ring we are already in. " 116 | "Is GMock thread safety enabled?"); 117 | p = p->next_; 118 | } 119 | p->next_ = this; 120 | next_ = ptr; 121 | } 122 | 123 | // Leave whatever circle we're part of. Returns true if we were the 124 | // last member of the circle. Once this is done, you can join() another. 125 | bool depart() 126 | GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { 127 | MutexLock lock(&g_linked_ptr_mutex); 128 | 129 | if (next_ == this) return true; 130 | linked_ptr_internal const* p = next_; 131 | while (p->next_ != this) { 132 | assert(p->next_ != next_ && 133 | "Trying to depart() a linked ring we are not in. " 134 | "Is GMock thread safety enabled?"); 135 | p = p->next_; 136 | } 137 | p->next_ = next_; 138 | return false; 139 | } 140 | 141 | private: 142 | mutable linked_ptr_internal const* next_; 143 | }; 144 | 145 | template 146 | class linked_ptr { 147 | public: 148 | typedef T element_type; 149 | 150 | // Take over ownership of a raw pointer. This should happen as soon as 151 | // possible after the object is created. 152 | explicit linked_ptr(T* ptr = NULL) { capture(ptr); } 153 | ~linked_ptr() { depart(); } 154 | 155 | // Copy an existing linked_ptr<>, adding ourselves to the list of references. 156 | template linked_ptr(linked_ptr const& ptr) { copy(&ptr); } 157 | linked_ptr(linked_ptr const& ptr) { // NOLINT 158 | assert(&ptr != this); 159 | copy(&ptr); 160 | } 161 | 162 | // Assignment releases the old value and acquires the new. 163 | template linked_ptr& operator=(linked_ptr const& ptr) { 164 | depart(); 165 | copy(&ptr); 166 | return *this; 167 | } 168 | 169 | linked_ptr& operator=(linked_ptr const& ptr) { 170 | if (&ptr != this) { 171 | depart(); 172 | copy(&ptr); 173 | } 174 | return *this; 175 | } 176 | 177 | // Smart pointer members. 178 | void reset(T* ptr = NULL) { 179 | depart(); 180 | capture(ptr); 181 | } 182 | T* get() const { return value_; } 183 | T* operator->() const { return value_; } 184 | T& operator*() const { return *value_; } 185 | 186 | bool operator==(T* p) const { return value_ == p; } 187 | bool operator!=(T* p) const { return value_ != p; } 188 | template 189 | bool operator==(linked_ptr const& ptr) const { 190 | return value_ == ptr.get(); 191 | } 192 | template 193 | bool operator!=(linked_ptr const& ptr) const { 194 | return value_ != ptr.get(); 195 | } 196 | 197 | private: 198 | template 199 | friend class linked_ptr; 200 | 201 | T* value_; 202 | linked_ptr_internal link_; 203 | 204 | void depart() { 205 | if (link_.depart()) delete value_; 206 | } 207 | 208 | void capture(T* ptr) { 209 | value_ = ptr; 210 | link_.join_new(); 211 | } 212 | 213 | template void copy(linked_ptr const* ptr) { 214 | value_ = ptr->get(); 215 | if (value_) 216 | link_.join(&ptr->link_); 217 | else 218 | link_.join_new(); 219 | } 220 | }; 221 | 222 | template inline 223 | bool operator==(T* ptr, const linked_ptr& x) { 224 | return ptr == x.get(); 225 | } 226 | 227 | template inline 228 | bool operator!=(T* ptr, const linked_ptr& x) { 229 | return ptr != x.get(); 230 | } 231 | 232 | // A function to convert T* into linked_ptr 233 | // Doing e.g. make_linked_ptr(new FooBarBaz(arg)) is a shorter notation 234 | // for linked_ptr >(new FooBarBaz(arg)) 235 | template 236 | linked_ptr make_linked_ptr(T* ptr) { 237 | return linked_ptr(ptr); 238 | } 239 | 240 | } // namespace internal 241 | } // namespace testing 242 | 243 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ 244 | -------------------------------------------------------------------------------- /3rdparty/googletest/inc/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 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 | $range i 1..n 76 | $for i [[ 77 | $range j 1..i 78 | 79 | template <$for j, [[typename T$j]]> 80 | class ValueArray$i { 81 | public: 82 | $if i==1 [[explicit ]]ValueArray$i($for j, [[T$j v$j]]) : $for j, [[v$(j)_(v$j)]] {} 83 | 84 | template 85 | operator ParamGenerator() const { 86 | const T array[] = {$for j, [[static_cast(v$(j)_)]]}; 87 | return ValuesIn(array); 88 | } 89 | 90 | private: 91 | // No implementation - assignment is unsupported. 92 | void operator=(const ValueArray$i& other); 93 | 94 | $for j [[ 95 | 96 | const T$j v$(j)_; 97 | ]] 98 | 99 | }; 100 | 101 | ]] 102 | 103 | # if GTEST_HAS_COMBINE 104 | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. 105 | // 106 | // Generates values from the Cartesian product of values produced 107 | // by the argument generators. 108 | // 109 | $range i 2..maxtuple 110 | $for i [[ 111 | $range j 1..i 112 | $range k 2..i 113 | 114 | template <$for j, [[typename T$j]]> 115 | class CartesianProductGenerator$i 116 | : public ParamGeneratorInterface< ::testing::tuple<$for j, [[T$j]]> > { 117 | public: 118 | typedef ::testing::tuple<$for j, [[T$j]]> ParamType; 119 | 120 | CartesianProductGenerator$i($for j, [[const ParamGenerator& g$j]]) 121 | : $for j, [[g$(j)_(g$j)]] {} 122 | virtual ~CartesianProductGenerator$i() {} 123 | 124 | virtual ParamIteratorInterface* Begin() const { 125 | return new Iterator(this, $for j, [[g$(j)_, g$(j)_.begin()]]); 126 | } 127 | virtual ParamIteratorInterface* End() const { 128 | return new Iterator(this, $for j, [[g$(j)_, g$(j)_.end()]]); 129 | } 130 | 131 | private: 132 | class Iterator : public ParamIteratorInterface { 133 | public: 134 | Iterator(const ParamGeneratorInterface* base, $for j, [[ 135 | 136 | const ParamGenerator& g$j, 137 | const typename ParamGenerator::iterator& current$(j)]]) 138 | : base_(base), 139 | $for j, [[ 140 | 141 | begin$(j)_(g$j.begin()), end$(j)_(g$j.end()), current$(j)_(current$j) 142 | ]] { 143 | ComputeCurrentValue(); 144 | } 145 | virtual ~Iterator() {} 146 | 147 | virtual const ParamGeneratorInterface* BaseGenerator() const { 148 | return base_; 149 | } 150 | // Advance should not be called on beyond-of-range iterators 151 | // so no component iterators must be beyond end of range, either. 152 | virtual void Advance() { 153 | assert(!AtEnd()); 154 | ++current$(i)_; 155 | 156 | $for k [[ 157 | if (current$(i+2-k)_ == end$(i+2-k)_) { 158 | current$(i+2-k)_ = begin$(i+2-k)_; 159 | ++current$(i+2-k-1)_; 160 | } 161 | 162 | ]] 163 | ComputeCurrentValue(); 164 | } 165 | virtual ParamIteratorInterface* Clone() const { 166 | return new Iterator(*this); 167 | } 168 | virtual const ParamType* Current() const { return ¤t_value_; } 169 | virtual bool Equals(const ParamIteratorInterface& other) const { 170 | // Having the same base generator guarantees that the other 171 | // iterator is of the same type and we can downcast. 172 | GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) 173 | << "The program attempted to compare iterators " 174 | << "from different generators." << std::endl; 175 | const Iterator* typed_other = 176 | CheckedDowncastToActualType(&other); 177 | // We must report iterators equal if they both point beyond their 178 | // respective ranges. That can happen in a variety of fashions, 179 | // so we have to consult AtEnd(). 180 | return (AtEnd() && typed_other->AtEnd()) || 181 | ($for j && [[ 182 | 183 | current$(j)_ == typed_other->current$(j)_ 184 | ]]); 185 | } 186 | 187 | private: 188 | Iterator(const Iterator& other) 189 | : base_(other.base_), $for j, [[ 190 | 191 | begin$(j)_(other.begin$(j)_), 192 | end$(j)_(other.end$(j)_), 193 | current$(j)_(other.current$(j)_) 194 | ]] { 195 | ComputeCurrentValue(); 196 | } 197 | 198 | void ComputeCurrentValue() { 199 | if (!AtEnd()) 200 | current_value_ = ParamType($for j, [[*current$(j)_]]); 201 | } 202 | bool AtEnd() const { 203 | // We must report iterator past the end of the range when either of the 204 | // component iterators has reached the end of its range. 205 | return 206 | $for j || [[ 207 | 208 | current$(j)_ == end$(j)_ 209 | ]]; 210 | } 211 | 212 | // No implementation - assignment is unsupported. 213 | void operator=(const Iterator& other); 214 | 215 | const ParamGeneratorInterface* const base_; 216 | // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. 217 | // current[i]_ is the actual traversing iterator. 218 | $for j [[ 219 | 220 | const typename ParamGenerator::iterator begin$(j)_; 221 | const typename ParamGenerator::iterator end$(j)_; 222 | typename ParamGenerator::iterator current$(j)_; 223 | ]] 224 | 225 | ParamType current_value_; 226 | }; // class CartesianProductGenerator$i::Iterator 227 | 228 | // No implementation - assignment is unsupported. 229 | void operator=(const CartesianProductGenerator$i& other); 230 | 231 | 232 | $for j [[ 233 | const ParamGenerator g$(j)_; 234 | 235 | ]] 236 | }; // class CartesianProductGenerator$i 237 | 238 | 239 | ]] 240 | 241 | // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. 242 | // 243 | // Helper classes providing Combine() with polymorphic features. They allow 244 | // casting CartesianProductGeneratorN to ParamGenerator if T is 245 | // convertible to U. 246 | // 247 | $range i 2..maxtuple 248 | $for i [[ 249 | $range j 1..i 250 | 251 | template <$for j, [[class Generator$j]]> 252 | class CartesianProductHolder$i { 253 | public: 254 | CartesianProductHolder$i($for j, [[const Generator$j& g$j]]) 255 | : $for j, [[g$(j)_(g$j)]] {} 256 | template <$for j, [[typename T$j]]> 257 | operator ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >() const { 258 | return ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >( 259 | new CartesianProductGenerator$i<$for j, [[T$j]]>( 260 | $for j,[[ 261 | 262 | static_cast >(g$(j)_) 263 | ]])); 264 | } 265 | 266 | private: 267 | // No implementation - assignment is unsupported. 268 | void operator=(const CartesianProductHolder$i& other); 269 | 270 | 271 | $for j [[ 272 | const Generator$j g$(j)_; 273 | 274 | ]] 275 | }; // class CartesianProductHolder$i 276 | 277 | ]] 278 | 279 | # endif // GTEST_HAS_COMBINE 280 | 281 | } // namespace internal 282 | } // namespace testing 283 | 284 | #endif // GTEST_HAS_PARAM_TEST 285 | 286 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ 287 | -------------------------------------------------------------------------------- /3rdparty/googletest/inc/gtest/internal/gtest-port-arch.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015, 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 | // The Google C++ Testing Framework (Google Test) 31 | // 32 | // This header file defines the GTEST_OS_* macro. 33 | // It is separate from gtest-port.h so that custom/gtest-port.h can include it. 34 | 35 | #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ 36 | #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ 37 | 38 | // Determines the platform on which Google Test is compiled. 39 | #ifdef __CYGWIN__ 40 | # define GTEST_OS_CYGWIN 1 41 | #elif defined __SYMBIAN32__ 42 | # define GTEST_OS_SYMBIAN 1 43 | #elif defined _WIN32 44 | # define GTEST_OS_WINDOWS 1 45 | # ifdef _WIN32_WCE 46 | # define GTEST_OS_WINDOWS_MOBILE 1 47 | # elif defined(__MINGW__) || defined(__MINGW32__) 48 | # define GTEST_OS_WINDOWS_MINGW 1 49 | # elif defined(WINAPI_FAMILY) 50 | # include 51 | # if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) 52 | # define GTEST_OS_WINDOWS_DESKTOP 1 53 | # elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) 54 | # define GTEST_OS_WINDOWS_PHONE 1 55 | # elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) 56 | # define GTEST_OS_WINDOWS_RT 1 57 | # else 58 | // WINAPI_FAMILY defined but no known partition matched. 59 | // Default to desktop. 60 | # define GTEST_OS_WINDOWS_DESKTOP 1 61 | # endif 62 | # else 63 | # define GTEST_OS_WINDOWS_DESKTOP 1 64 | # endif // _WIN32_WCE 65 | #elif defined __APPLE__ 66 | # define GTEST_OS_MAC 1 67 | # if TARGET_OS_IPHONE 68 | # define GTEST_OS_IOS 1 69 | # endif 70 | #elif defined __FreeBSD__ 71 | # define GTEST_OS_FREEBSD 1 72 | #elif defined __linux__ 73 | # define GTEST_OS_LINUX 1 74 | # if defined __ANDROID__ 75 | # define GTEST_OS_LINUX_ANDROID 1 76 | # endif 77 | #elif defined __MVS__ 78 | # define GTEST_OS_ZOS 1 79 | #elif defined(__sun) && defined(__SVR4) 80 | # define GTEST_OS_SOLARIS 1 81 | #elif defined(_AIX) 82 | # define GTEST_OS_AIX 1 83 | #elif defined(__hpux) 84 | # define GTEST_OS_HPUX 1 85 | #elif defined __native_client__ 86 | # define GTEST_OS_NACL 1 87 | #elif defined __OpenBSD__ 88 | # define GTEST_OS_OPENBSD 1 89 | #elif defined __QNX__ 90 | # define GTEST_OS_QNX 1 91 | #endif // __CYGWIN__ 92 | 93 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ 94 | -------------------------------------------------------------------------------- /3rdparty/googletest/inc/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 | -------------------------------------------------------------------------------- /3rdparty/googletest/inc/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 | // Visual Studio 2010, 2012, and 2013 define symbols in std::tr1 that conflict 56 | // with our own definitions. Therefore using our own tuple does not work on 57 | // those compilers. 58 | #if defined(_MSC_VER) && _MSC_VER >= 1600 /* 1600 is Visual Studio 2010 */ 59 | # error "gtest's tuple doesn't compile on Visual Studio 2010 or later. \ 60 | GTEST_USE_OWN_TR1_TUPLE must be set to 0 on those compilers." 61 | #endif 62 | 63 | 64 | $range i 0..n-1 65 | $range j 0..n 66 | $range k 1..n 67 | // GTEST_n_TUPLE_(T) is the type of an n-tuple. 68 | #define GTEST_0_TUPLE_(T) tuple<> 69 | 70 | $for k [[ 71 | $range m 0..k-1 72 | $range m2 k..n-1 73 | #define GTEST_$(k)_TUPLE_(T) tuple<$for m, [[T##$m]]$for m2 [[, void]]> 74 | 75 | ]] 76 | 77 | // GTEST_n_TYPENAMES_(T) declares a list of n typenames. 78 | 79 | $for j [[ 80 | $range m 0..j-1 81 | #define GTEST_$(j)_TYPENAMES_(T) $for m, [[typename T##$m]] 82 | 83 | 84 | ]] 85 | 86 | // In theory, defining stuff in the ::std namespace is undefined 87 | // behavior. We can do this as we are playing the role of a standard 88 | // library vendor. 89 | namespace std { 90 | namespace tr1 { 91 | 92 | template <$for i, [[typename T$i = void]]> 93 | class tuple; 94 | 95 | // Anything in namespace gtest_internal is Google Test's INTERNAL 96 | // IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code. 97 | namespace gtest_internal { 98 | 99 | // ByRef::type is T if T is a reference; otherwise it's const T&. 100 | template 101 | struct ByRef { typedef const T& type; }; // NOLINT 102 | template 103 | struct ByRef { typedef T& type; }; // NOLINT 104 | 105 | // A handy wrapper for ByRef. 106 | #define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef::type 107 | 108 | // AddRef::type is T if T is a reference; otherwise it's T&. This 109 | // is the same as tr1::add_reference::type. 110 | template 111 | struct AddRef { typedef T& type; }; // NOLINT 112 | template 113 | struct AddRef { typedef T& type; }; // NOLINT 114 | 115 | // A handy wrapper for AddRef. 116 | #define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef::type 117 | 118 | // A helper for implementing get(). 119 | template class Get; 120 | 121 | // A helper for implementing tuple_element. kIndexValid is true 122 | // iff k < the number of fields in tuple type T. 123 | template 124 | struct TupleElement; 125 | 126 | 127 | $for i [[ 128 | template 129 | struct TupleElement { 130 | typedef T$i type; 131 | }; 132 | 133 | 134 | ]] 135 | } // namespace gtest_internal 136 | 137 | template <> 138 | class tuple<> { 139 | public: 140 | tuple() {} 141 | tuple(const tuple& /* t */) {} 142 | tuple& operator=(const tuple& /* t */) { return *this; } 143 | }; 144 | 145 | 146 | $for k [[ 147 | $range m 0..k-1 148 | template 149 | class $if k < n [[GTEST_$(k)_TUPLE_(T)]] $else [[tuple]] { 150 | public: 151 | template friend class gtest_internal::Get; 152 | 153 | tuple() : $for m, [[f$(m)_()]] {} 154 | 155 | explicit tuple($for m, [[GTEST_BY_REF_(T$m) f$m]]) : [[]] 156 | $for m, [[f$(m)_(f$m)]] {} 157 | 158 | tuple(const tuple& t) : $for m, [[f$(m)_(t.f$(m)_)]] {} 159 | 160 | template 161 | tuple(const GTEST_$(k)_TUPLE_(U)& t) : $for m, [[f$(m)_(t.f$(m)_)]] {} 162 | 163 | $if k == 2 [[ 164 | template 165 | tuple(const ::std::pair& p) : f0_(p.first), f1_(p.second) {} 166 | 167 | ]] 168 | 169 | tuple& operator=(const tuple& t) { return CopyFrom(t); } 170 | 171 | template 172 | tuple& operator=(const GTEST_$(k)_TUPLE_(U)& t) { 173 | return CopyFrom(t); 174 | } 175 | 176 | $if k == 2 [[ 177 | template 178 | tuple& operator=(const ::std::pair& p) { 179 | f0_ = p.first; 180 | f1_ = p.second; 181 | return *this; 182 | } 183 | 184 | ]] 185 | 186 | GTEST_DECLARE_TUPLE_AS_FRIEND_ 187 | 188 | template 189 | tuple& CopyFrom(const GTEST_$(k)_TUPLE_(U)& t) { 190 | 191 | $for m [[ 192 | f$(m)_ = t.f$(m)_; 193 | 194 | ]] 195 | return *this; 196 | } 197 | 198 | 199 | $for m [[ 200 | T$m f$(m)_; 201 | 202 | ]] 203 | }; 204 | 205 | 206 | ]] 207 | // 6.1.3.2 Tuple creation functions. 208 | 209 | // Known limitations: we don't support passing an 210 | // std::tr1::reference_wrapper to make_tuple(). And we don't 211 | // implement tie(). 212 | 213 | inline tuple<> make_tuple() { return tuple<>(); } 214 | 215 | $for k [[ 216 | $range m 0..k-1 217 | 218 | template 219 | inline GTEST_$(k)_TUPLE_(T) make_tuple($for m, [[const T$m& f$m]]) { 220 | return GTEST_$(k)_TUPLE_(T)($for m, [[f$m]]); 221 | } 222 | 223 | ]] 224 | 225 | // 6.1.3.3 Tuple helper classes. 226 | 227 | template struct tuple_size; 228 | 229 | 230 | $for j [[ 231 | template 232 | struct tuple_size { 233 | static const int value = $j; 234 | }; 235 | 236 | 237 | ]] 238 | template 239 | struct tuple_element { 240 | typedef typename gtest_internal::TupleElement< 241 | k < (tuple_size::value), k, Tuple>::type type; 242 | }; 243 | 244 | #define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element::type 245 | 246 | // 6.1.3.4 Element access. 247 | 248 | namespace gtest_internal { 249 | 250 | 251 | $for i [[ 252 | template <> 253 | class Get<$i> { 254 | public: 255 | template 256 | static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple)) 257 | Field(Tuple& t) { return t.f$(i)_; } // NOLINT 258 | 259 | template 260 | static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_($i, Tuple)) 261 | ConstField(const Tuple& t) { return t.f$(i)_; } 262 | }; 263 | 264 | 265 | ]] 266 | } // namespace gtest_internal 267 | 268 | template 269 | GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T))) 270 | get(GTEST_$(n)_TUPLE_(T)& t) { 271 | return gtest_internal::Get::Field(t); 272 | } 273 | 274 | template 275 | GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_$(n)_TUPLE_(T))) 276 | get(const GTEST_$(n)_TUPLE_(T)& t) { 277 | return gtest_internal::Get::ConstField(t); 278 | } 279 | 280 | // 6.1.3.5 Relational operators 281 | 282 | // We only implement == and !=, as we don't have a need for the rest yet. 283 | 284 | namespace gtest_internal { 285 | 286 | // SameSizeTuplePrefixComparator::Eq(t1, t2) returns true if the 287 | // first k fields of t1 equals the first k fields of t2. 288 | // SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if 289 | // k1 != k2. 290 | template 291 | struct SameSizeTuplePrefixComparator; 292 | 293 | template <> 294 | struct SameSizeTuplePrefixComparator<0, 0> { 295 | template 296 | static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { 297 | return true; 298 | } 299 | }; 300 | 301 | template 302 | struct SameSizeTuplePrefixComparator { 303 | template 304 | static bool Eq(const Tuple1& t1, const Tuple2& t2) { 305 | return SameSizeTuplePrefixComparator::Eq(t1, t2) && 306 | ::std::tr1::get(t1) == ::std::tr1::get(t2); 307 | } 308 | }; 309 | 310 | } // namespace gtest_internal 311 | 312 | template 313 | inline bool operator==(const GTEST_$(n)_TUPLE_(T)& t, 314 | const GTEST_$(n)_TUPLE_(U)& u) { 315 | return gtest_internal::SameSizeTuplePrefixComparator< 316 | tuple_size::value, 317 | tuple_size::value>::Eq(t, u); 318 | } 319 | 320 | template 321 | inline bool operator!=(const GTEST_$(n)_TUPLE_(T)& t, 322 | const GTEST_$(n)_TUPLE_(U)& u) { return !(t == u); } 323 | 324 | // 6.1.4 Pairs. 325 | // Unimplemented. 326 | 327 | } // namespace tr1 328 | } // namespace std 329 | 330 | 331 | $for j [[ 332 | #undef GTEST_$(j)_TUPLE_ 333 | 334 | ]] 335 | 336 | 337 | $for j [[ 338 | #undef GTEST_$(j)_TYPENAMES_ 339 | 340 | ]] 341 | 342 | #undef GTEST_DECLARE_TUPLE_AS_FRIEND_ 343 | #undef GTEST_BY_REF_ 344 | #undef GTEST_ADD_REF_ 345 | #undef GTEST_TUPLE_ELEMENT_ 346 | 347 | #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ 348 | -------------------------------------------------------------------------------- /3rdparty/googletest/inc/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/googletest/makefile: -------------------------------------------------------------------------------- 1 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 2 | #||BUILD FLAGS||# 3 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 4 | 5 | #Generates moc files from headers for QT applications 6 | BUILD_MOCS = 0 7 | 8 | #Generates dynamic (shared object) and static (archive) from non-main objects 9 | BUILD_LIB = 1 10 | 11 | #Generates binary from all objects 12 | BUILD_BIN = 0 13 | 14 | #Generates test application 15 | BUILD_TESTS = 0 16 | 17 | #Runs pre-build scripts 18 | RUN_PREBUILD = 0 19 | 20 | #Runs post-build scripts 21 | RUN_POSTBUILD = 0 22 | 23 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 24 | #||EXTERNALS||# 25 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 26 | 27 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 28 | #||BUILD CONFIG||# 29 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 30 | 31 | ###################### 32 | ## Compiler Options ## 33 | ###################### 34 | #Compiler 35 | CC = g++ 36 | 37 | #Compiler options 38 | OPTS = -Wall -fPIC 39 | RELEASE_OPTS = -O2 -O3 40 | DEBUG_OPTS = -g 41 | 42 | #Static library archiver 43 | LG = ar 44 | 45 | #Static archiver options 46 | LGOPTS = -r 47 | 48 | #Project source file extensions 49 | SRCTYPES = cpp cc c 50 | 51 | #Project header file extensions 52 | HTYPES = h hpp 53 | 54 | ########################### 55 | ## Project Configuration ## 56 | ########################### 57 | 58 | PROJECT = gtest 59 | 60 | #Define Flags 61 | DEFINE = LINUX 62 | 63 | #Pre-Build Scripts 64 | PREBUILD = 65 | 66 | #Post-Build Scripts 67 | POSTBUILD = 68 | 69 | ############################ 70 | # Directory Configuration ## 71 | ############################ 72 | 73 | # Project Directories 74 | SRCDIR = src 75 | INCDIR = inc 76 | TESTDIR = 77 | 78 | #Generated Directories 79 | GENDIR = gen 80 | 81 | #################################### 82 | # External Dependencies and Paths ## 83 | #################################### 84 | 85 | # External Include Directories 86 | EXTINC = src 87 | 88 | # External/System Libraries 89 | LIBDIRS = 90 | LIBS = pthread 91 | 92 | #Additional Source files to compile 93 | ADDSRC = 94 | 95 | # External Links 96 | LINKS = 97 | 98 | #Additional files/folders to clean 99 | CLEANFILES = 100 | 101 | ########################### 102 | # Unit Test Dependencies ## 103 | ########################### 104 | 105 | #Unit testing library 106 | TESTLIB = 107 | 108 | #Unit testing library include path 109 | TESTINC = 110 | 111 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 112 | #||ADDITIONAL OPTIONS||# 113 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 114 | 115 | # debug = builds with debug options by default (can be manually specified by invoking the debug target) 116 | # release = builds with release options by default (can be manually specified by invoking the release target) 117 | BUILD_TYPE = debug 118 | 119 | # 0 = Include only INCDIR 120 | # 1 = Recursively include all directories in INCDIR 121 | RECURSIVELY_INCLUDE_LOCAL = 0 122 | 123 | # 0 = Include only directories listed in EXTINC 124 | # 1 = Recursively include all directories for each directory specified in extinc 125 | RECURSIVELY_INCLUDE_EXTERNAL = 0 126 | 127 | # 0 = Don't include main object file in generated libraries 128 | # 1 = Include main object file in generated libraries 129 | MAIN_OBJECT_IN_LIBRARIES = 1 130 | 131 | # 0 = The project contains no main method (i.e. exclusively a library) 132 | # 1 = The project contains at least one main method 133 | PROJECT_CONTAINS_MAIN = 1 134 | 135 | # If they exist, sources with main methods can be explicitly specified here. 136 | # This saves compilation time, as the makefile will no longer need to 137 | # search the object files for the main symbol 138 | EXPLICIT_MAIN_SOURCE = CustomTestPrinter.cpp 139 | 140 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 141 | #||BUILD SCRIPT||# 142 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 143 | include core.mk 144 | -------------------------------------------------------------------------------- /3rdparty/googletest/misc/CHANGES: -------------------------------------------------------------------------------- 1 | Changes for 1.7.0: 2 | 3 | * New feature: death tests are supported on OpenBSD and in iOS 4 | simulator now. 5 | * New feature: Google Test now implements a protocol to allow 6 | a test runner to detect that a test program has exited 7 | prematurely and report it as a failure (before it would be 8 | falsely reported as a success if the exit code is 0). 9 | * New feature: Test::RecordProperty() can now be used outside of the 10 | lifespan of a test method, in which case it will be attributed to 11 | the current test case or the test program in the XML report. 12 | * New feature (potentially breaking): --gtest_list_tests now prints 13 | the type parameters and value parameters for each test. 14 | * Improvement: char pointers and char arrays are now escaped properly 15 | in failure messages. 16 | * Improvement: failure summary in XML reports now includes file and 17 | line information. 18 | * Improvement: the XML element now has a timestamp attribute. 19 | * Improvement: When --gtest_filter is specified, XML report now doesn't 20 | contain information about tests that are filtered out. 21 | * Fixed the bug where long --gtest_filter flag values are truncated in 22 | death tests. 23 | * Potentially breaking change: RUN_ALL_TESTS() is now implemented as a 24 | function instead of a macro in order to work better with Clang. 25 | * Compatibility fixes with C++ 11 and various platforms. 26 | * Bug/warning fixes. 27 | 28 | Changes for 1.6.0: 29 | 30 | * New feature: ADD_FAILURE_AT() for reporting a test failure at the 31 | given source location -- useful for writing testing utilities. 32 | * New feature: the universal value printer is moved from Google Mock 33 | to Google Test. 34 | * New feature: type parameters and value parameters are reported in 35 | the XML report now. 36 | * A gtest_disable_pthreads CMake option. 37 | * Colored output works in GNU Screen sessions now. 38 | * Parameters of value-parameterized tests are now printed in the 39 | textual output. 40 | * Failures from ad hoc test assertions run before RUN_ALL_TESTS() are 41 | now correctly reported. 42 | * Arguments of ASSERT_XY and EXPECT_XY no longer need to support << to 43 | ostream. 44 | * More complete handling of exceptions. 45 | * GTEST_ASSERT_XY can be used instead of ASSERT_XY in case the latter 46 | name is already used by another library. 47 | * --gtest_catch_exceptions is now true by default, allowing a test 48 | program to continue after an exception is thrown. 49 | * Value-parameterized test fixtures can now derive from Test and 50 | WithParamInterface separately, easing conversion of legacy tests. 51 | * Death test messages are clearly marked to make them more 52 | distinguishable from other messages. 53 | * Compatibility fixes for Android, Google Native Client, MinGW, HP UX, 54 | PowerPC, Lucid autotools, libCStd, Sun C++, Borland C++ Builder (Code Gear), 55 | IBM XL C++ (Visual Age C++), and C++0x. 56 | * Bug fixes and implementation clean-ups. 57 | * Potentially incompatible changes: disables the harmful 'make install' 58 | command in autotools. 59 | 60 | Changes for 1.5.0: 61 | 62 | * New feature: assertions can be safely called in multiple threads 63 | where the pthreads library is available. 64 | * New feature: predicates used inside EXPECT_TRUE() and friends 65 | can now generate custom failure messages. 66 | * New feature: Google Test can now be compiled as a DLL. 67 | * New feature: fused source files are included. 68 | * New feature: prints help when encountering unrecognized Google Test flags. 69 | * Experimental feature: CMake build script (requires CMake 2.6.4+). 70 | * Experimental feature: the Pump script for meta programming. 71 | * double values streamed to an assertion are printed with enough precision 72 | to differentiate any two different values. 73 | * Google Test now works on Solaris and AIX. 74 | * Build and test script improvements. 75 | * Bug fixes and implementation clean-ups. 76 | 77 | Potentially breaking changes: 78 | 79 | * Stopped supporting VC++ 7.1 with exceptions disabled. 80 | * Dropped support for 'make install'. 81 | 82 | Changes for 1.4.0: 83 | 84 | * New feature: the event listener API 85 | * New feature: test shuffling 86 | * New feature: the XML report format is closer to junitreport and can 87 | be parsed by Hudson now. 88 | * New feature: when a test runs under Visual Studio, its failures are 89 | integrated in the IDE. 90 | * New feature: /MD(d) versions of VC++ projects. 91 | * New feature: elapsed time for the tests is printed by default. 92 | * New feature: comes with a TR1 tuple implementation such that Boost 93 | is no longer needed for Combine(). 94 | * New feature: EXPECT_DEATH_IF_SUPPORTED macro and friends. 95 | * New feature: the Xcode project can now produce static gtest 96 | libraries in addition to a framework. 97 | * Compatibility fixes for Solaris, Cygwin, minGW, Windows Mobile, 98 | Symbian, gcc, and C++Builder. 99 | * Bug fixes and implementation clean-ups. 100 | 101 | Changes for 1.3.0: 102 | 103 | * New feature: death tests on Windows, Cygwin, and Mac. 104 | * New feature: ability to use Google Test assertions in other testing 105 | frameworks. 106 | * New feature: ability to run disabled test via 107 | --gtest_also_run_disabled_tests. 108 | * New feature: the --help flag for printing the usage. 109 | * New feature: access to Google Test flag values in user code. 110 | * New feature: a script that packs Google Test into one .h and one 111 | .cc file for easy deployment. 112 | * New feature: support for distributing test functions to multiple 113 | machines (requires support from the test runner). 114 | * Bug fixes and implementation clean-ups. 115 | 116 | Changes for 1.2.1: 117 | 118 | * Compatibility fixes for Linux IA-64 and IBM z/OS. 119 | * Added support for using Boost and other TR1 implementations. 120 | * Changes to the build scripts to support upcoming release of Google C++ 121 | Mocking Framework. 122 | * Added Makefile to the distribution package. 123 | * Improved build instructions in README. 124 | 125 | Changes for 1.2.0: 126 | 127 | * New feature: value-parameterized tests. 128 | * New feature: the ASSERT/EXPECT_(NON)FATAL_FAILURE(_ON_ALL_THREADS) 129 | macros. 130 | * Changed the XML report format to match JUnit/Ant's. 131 | * Added tests to the Xcode project. 132 | * Added scons/SConscript for building with SCons. 133 | * Added src/gtest-all.cc for building Google Test from a single file. 134 | * Fixed compatibility with Solaris and z/OS. 135 | * Enabled running Python tests on systems with python 2.3 installed, 136 | e.g. Mac OS X 10.4. 137 | * Bug fixes. 138 | 139 | Changes for 1.1.0: 140 | 141 | * New feature: type-parameterized tests. 142 | * New feature: exception assertions. 143 | * New feature: printing elapsed time of tests. 144 | * Improved the robustness of death tests. 145 | * Added an Xcode project and samples. 146 | * Adjusted the output format on Windows to be understandable by Visual Studio. 147 | * Minor bug fixes. 148 | 149 | Changes for 1.0.1: 150 | 151 | * Added project files for Visual Studio 7.1. 152 | * Fixed issues with compiling on Mac OS X. 153 | * Fixed issues with compiling on Cygwin. 154 | 155 | Changes for 1.0.0: 156 | 157 | * Initial Open Source release of Google Test 158 | -------------------------------------------------------------------------------- /3rdparty/googletest/misc/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This file contains a list of people who've made non-trivial 2 | # contribution to the Google C++ Testing Framework project. People 3 | # who commit code to the project are encouraged to add their names 4 | # here. Please keep the list sorted by first names. 5 | 6 | Ajay Joshi 7 | Balázs Dán 8 | Bharat Mediratta 9 | Chandler Carruth 10 | Chris Prince 11 | Chris Taylor 12 | Dan Egnor 13 | Eric Roman 14 | Hady Zalek 15 | Jeffrey Yasskin 16 | Jói Sigurðsson 17 | Keir Mierle 18 | Keith Ray 19 | Kenton Varda 20 | Manuel Klimek 21 | Markus Heule 22 | Mika Raento 23 | Miklós Fazekas 24 | Pasi Valminen 25 | Patrick Hanna 26 | Patrick Riley 27 | Peter Kaminski 28 | Preston Jackson 29 | Rainer Klaffenboeck 30 | Russ Cox 31 | Russ Rufer 32 | Sean Mcafee 33 | Sigurður Ásgeirsson 34 | Tracy Bialik 35 | Vadim Berman 36 | Vlad Losev 37 | Zhanyong Wan 38 | -------------------------------------------------------------------------------- /3rdparty/googletest/misc/LICENSE: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /3rdparty/googletest/src/CustomTestPrinter.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include 3 | 4 | using std::cout; 5 | using std::endl; 6 | using namespace testing; 7 | 8 | static const char kUniversalFilter[] = "*"; 9 | static const char kTypeParamLabel[] = "TypeParam"; 10 | static const char kValueParamLabel[] = "GetParam()"; 11 | 12 | #define PRINT_SEPARATOR printf("-----------------------------------------------------------------------------------\n"); 13 | #define PRINT_MAIN_SEPARATOR printf("|---------------------------------------------------------------------------------|\n"); 14 | #define PRINT_UNDERSEPARATOR printf("|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|\n"); 15 | #define PRINT_EXTENDER printf("- "); 16 | #define PRINT_ALT_EXTENDER printf("~| "); 17 | #define PRINT_LONG_EXTENDER printf(" "); 18 | #define PRINT_FAILSTART_MARKER printf("|#!#!#! TEST_FAILURE >>>>>>> TEST_FAILURE <<<<<<< TEST_FAILURE #!#!#!|\n"); 19 | #define PRINT_FAILEND_MARKER printf(" ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ \n"); 20 | 21 | class CustomTestPrinter : public EmptyTestEventListener { 22 | // Fired before each iteration of tests starts. 23 | 24 | void OnTestIterationStart(const UnitTest& unit_test, int iteration) { 25 | if (GTEST_FLAG(repeat) != 1) { 26 | printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1); 27 | } 28 | const char* const filter = GTEST_FLAG(filter).c_str(); 29 | 30 | // Prints the filter if it's not *. This reminds the user that some 31 | // tests may be skipped. 32 | if (strcmp(filter, kUniversalFilter) != 0) { 33 | printf("Note: %s filter = %s\n", GTEST_NAME_, filter); 34 | } 35 | 36 | if (GTEST_FLAG(shuffle)) { 37 | printf("Note: Randomizing tests' orders with a seed of %d .\n", unit_test.random_seed()); 38 | } 39 | 40 | PRINT_SEPARATOR; 41 | PRINT_EXTENDER; 42 | printf("Running %d test%s from %d test case%s.\n", 43 | unit_test.test_to_run_count(), unit_test.test_to_run_count() == 1 ? "" : "s", 44 | unit_test.test_case_to_run_count(), unit_test.test_case_to_run_count() == 1 ? "" : "s"); 45 | PRINT_SEPARATOR; 46 | fflush(stdout); 47 | } 48 | 49 | void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) { 50 | //PRINT_EXTENDER; 51 | //printf("Global test environment set-up.\n"); 52 | fflush(stdout); 53 | } 54 | 55 | void OnTestCaseStart(const TestCase& test_case) { 56 | PRINT_ALT_EXTENDER; 57 | printf("Test Case: %s", test_case.name()); 58 | if (test_case.type_param() == NULL) { 59 | printf("\n"); 60 | } else { 61 | printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param()); 62 | } 63 | PRINT_ALT_EXTENDER; 64 | printf("Tests: \n"); 65 | for (int i=0; iname()); 70 | 71 | } 72 | /*printf("%d %s from %s", test_case.test_to_run_count(), test_case.test_to_run_count() == 1 ? "test" : "tests", test_case.name()); 73 | if (test_case.type_param() == NULL) { 74 | printf("\n"); 75 | } else { 76 | printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param()); 77 | }*/ 78 | PRINT_SEPARATOR; 79 | fflush(stdout); 80 | } 81 | 82 | void OnTestStart(const TestInfo& test_info) { 83 | PRINT_LONG_EXTENDER; 84 | printf("Test %s.%s RUNNING", test_info.test_case_name(), test_info.name()); 85 | printf("\n"); 86 | PRINT_SEPARATOR; 87 | fflush(stdout); 88 | } 89 | 90 | // Called after an assertion failure. 91 | 92 | void OnTestPartResult( 93 | const TestPartResult& result) { 94 | // If the test part succeeded, we don't need to do anything. 95 | if (result.type() == TestPartResult::kSuccess) 96 | return; 97 | PRINT_FAILSTART_MARKER; 98 | printf("Failure in %s:%d\n%s\n", 99 | result.file_name(), 100 | result.line_number(), 101 | result.summary()); 102 | PRINT_FAILEND_MARKER; 103 | fflush(stdout); 104 | } 105 | 106 | void PrintFullTestCommentIfPresent(const TestInfo& test_info) { 107 | const char* const type_param = test_info.type_param(); 108 | const char* const value_param = test_info.value_param(); 109 | 110 | if (type_param != NULL || value_param != NULL) { 111 | printf(", where "); 112 | if (type_param != NULL) { 113 | printf("%s = %s", kTypeParamLabel, type_param); 114 | if (value_param != NULL) 115 | printf(" and "); 116 | } 117 | if (value_param != NULL) { 118 | printf("%s = %s", kValueParamLabel, value_param); 119 | } 120 | } 121 | } 122 | 123 | void OnTestEnd(const TestInfo& test_info) { 124 | PRINT_SEPARATOR; 125 | PRINT_LONG_EXTENDER; 126 | printf("Test %s.%s %s", test_info.test_case_name(), test_info.name(), test_info.result()->Passed() ? "PASSED" : "FAILED"); 127 | 128 | if (test_info.result()->Failed()) 129 | PrintFullTestCommentIfPresent(test_info); 130 | 131 | if (GTEST_FLAG(print_time)) { 132 | printf(" (%ld ms)\n", (long)test_info.result()->elapsed_time()); 133 | } else { 134 | printf("\n"); 135 | } 136 | PRINT_SEPARATOR; 137 | fflush(stdout); 138 | } 139 | 140 | void OnTestCaseEnd(const TestCase& test_case) { 141 | if (!GTEST_FLAG(print_time)) return; 142 | PRINT_ALT_EXTENDER; 143 | printf("%d %s from %s (%ld ms total)\n", 144 | test_case.test_to_run_count(), test_case.test_to_run_count() == 1 ? "test" : "tests", test_case.name(), (long)test_case.elapsed_time()); 145 | PRINT_SEPARATOR; 146 | fflush(stdout); 147 | } 148 | 149 | void OnEnvironmentsTearDownStart( 150 | const UnitTest& /*unit_test*/) { 151 | //PRINT_EXTENDER; 152 | //printf("Global test environment tear-down\n"); 153 | fflush(stdout); 154 | } 155 | 156 | // Internal helper for printing the list of failed tests. 157 | 158 | void PrintFailedTests(const UnitTest& unit_test) { 159 | const int failed_test_count = unit_test.failed_test_count(); 160 | if (failed_test_count == 0) { 161 | return; 162 | } 163 | PRINT_SEPARATOR; 164 | printf("Failed tests: \n"); 165 | for (int i = 0; i < unit_test.total_test_case_count(); ++i) { 166 | const TestCase& test_case = *unit_test.GetTestCase(i); 167 | if (!test_case.should_run() || (test_case.failed_test_count() == 0)) { 168 | continue; 169 | } 170 | 171 | for (int j = 0; j < test_case.total_test_count(); ++j) { 172 | const TestInfo& test_info = *test_case.GetTestInfo(j); 173 | if (!test_info.should_run() || test_info.result()->Passed()) { 174 | continue; 175 | } 176 | PRINT_EXTENDER; 177 | printf("%s.%s", test_case.name(), test_info.name()); 178 | PrintFullTestCommentIfPresent(test_info); 179 | printf("\n"); 180 | } 181 | } 182 | PRINT_SEPARATOR; 183 | } 184 | 185 | void OnTestIterationEnd(const UnitTest& unit_test, int /*iteration*/) { 186 | PRINT_EXTENDER; 187 | printf("%d %s from %d %s ran", 188 | unit_test.test_to_run_count(), unit_test.test_to_run_count() == 1 ? "test" : "tests", 189 | unit_test.test_case_to_run_count(), unit_test.test_case_to_run_count() == 1 ? "test case" : "test cases"); 190 | 191 | if (GTEST_FLAG(print_time)) { 192 | printf(" (%s ms total)", 193 | internal::StreamableToString(unit_test.elapsed_time()).c_str()); 194 | } 195 | printf("\n"); 196 | PRINT_EXTENDER; 197 | printf("%d %s PASSED.\n", unit_test.successful_test_count(), unit_test.successful_test_count() == 1 ? "test" : "tests"); 198 | 199 | int num_failures = unit_test.failed_test_count(); 200 | if (!unit_test.Passed()) { 201 | const int failed_test_count = unit_test.failed_test_count(); 202 | PRINT_EXTENDER; 203 | printf("%d %s FAILED.\n", failed_test_count, failed_test_count == 1 ? "test" : "tests"); 204 | PrintFailedTests(unit_test); 205 | } 206 | 207 | int num_disabled = unit_test.reportable_disabled_test_count(); 208 | if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) { 209 | if (!num_failures) { 210 | printf("\n"); // Add a spacer if no FAILURE banner is displayed. 211 | } 212 | printf( 213 | " YOU HAVE %d DISABLED %s\n\n", 214 | num_disabled, 215 | num_disabled == 1 ? "TEST" : "TESTS"); 216 | } 217 | // Ensure that Google Test output is printed before, e.g., heapchecker output. 218 | fflush(stdout); 219 | } 220 | 221 | }; 222 | 223 | int main(int argc, char **argv) { 224 | InitGoogleTest(&argc, argv); 225 | UnitTest& unit_test = *UnitTest::GetInstance(); 226 | TestEventListeners& listeners = unit_test.listeners(); 227 | 228 | // Removes the default console output listener from the list so it will 229 | // not receive events from Google Test and won't print any output. Since 230 | // this operation transfers ownership of the listener to the caller we 231 | // have to delete it as well. 232 | delete listeners.Release(listeners.default_result_printer()); 233 | 234 | // Adds the custom output listener to the list. It will now receive 235 | // events from Google Test and print the alternative output. We don't 236 | // have to worry about deleting it since Google Test assumes ownership 237 | // over it after adding it to the list. 238 | listeners.Append(new CustomTestPrinter); 239 | int ret_val = RUN_ALL_TESTS(); 240 | return ret_val; 241 | } -------------------------------------------------------------------------------- /3rdparty/googletest/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 exists to 39 | // prevent the accidental inclusion of gtest-internal-inl.h in the 40 | // user's code. 41 | #define GTEST_IMPLEMENTATION_ 1 42 | #include "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 | -------------------------------------------------------------------------------- /3rdparty/googletest/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 | static std::vector SplitIntoTestNames(const char* src) { 49 | std::vector name_vec; 50 | src = SkipSpaces(src); 51 | for (; src != NULL; src = SkipComma(src)) { 52 | name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src))); 53 | } 54 | return name_vec; 55 | } 56 | 57 | // Verifies that registered_tests match the test names in 58 | // registered_tests_; returns registered_tests if successful, or 59 | // aborts the program otherwise. 60 | const char* TypedTestCasePState::VerifyRegisteredTestNames( 61 | const char* file, int line, const char* registered_tests) { 62 | typedef RegisteredTestsMap::const_iterator RegisteredTestIter; 63 | registered_ = true; 64 | 65 | std::vector name_vec = SplitIntoTestNames(registered_tests); 66 | 67 | Message errors; 68 | 69 | std::set tests; 70 | for (std::vector::const_iterator name_it = name_vec.begin(); 71 | name_it != name_vec.end(); ++name_it) { 72 | const std::string& name = *name_it; 73 | if (tests.count(name) != 0) { 74 | errors << "Test " << name << " is listed more than once.\n"; 75 | continue; 76 | } 77 | 78 | bool found = false; 79 | for (RegisteredTestIter it = registered_tests_.begin(); 80 | it != registered_tests_.end(); 81 | ++it) { 82 | if (name == it->first) { 83 | found = true; 84 | break; 85 | } 86 | } 87 | 88 | if (found) { 89 | tests.insert(name); 90 | } else { 91 | errors << "No test named " << name 92 | << " can be found in this test case.\n"; 93 | } 94 | } 95 | 96 | for (RegisteredTestIter it = registered_tests_.begin(); 97 | it != registered_tests_.end(); 98 | ++it) { 99 | if (tests.count(it->first) == 0) { 100 | errors << "You forgot to list test " << it->first << ".\n"; 101 | } 102 | } 103 | 104 | const std::string& errors_str = errors.GetString(); 105 | if (errors_str != "") { 106 | fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), 107 | errors_str.c_str()); 108 | fflush(stderr); 109 | posix::Abort(); 110 | } 111 | 112 | return registered_tests; 113 | } 114 | 115 | #endif // GTEST_HAS_TYPED_TEST_P 116 | 117 | } // namespace internal 118 | } // namespace testing 119 | -------------------------------------------------------------------------------- /inc/BSignals/ExecutorScheme.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: ExecutorScheme.h 3 | * Author: Barath Kannan 4 | * 5 | * Created on 8 August 2016, 9:25 PM 6 | */ 7 | 8 | #ifndef BSIGNALS_EXECUTORSCHEME_H 9 | #define BSIGNALS_EXECUTORSCHEME_H 10 | 11 | namespace BSignals{ 12 | 13 | //These executors determine how message emission to a slot occurs 14 | // SYNCHRONOUS: 15 | // Emission occurs synchronously. 16 | // When emit returns, all connected slots have been invoked and returned. 17 | // This method is preferred when connected functions have short execution 18 | // time, quick emission is required, and/or when it is necessary to know 19 | // that the function has returned before proceeding. 20 | 21 | // ASYNCHRONOUS: 22 | // Emission occurs asynchronously. A detached thread is spawned on emission. 23 | // When emit returns, the thread has been spawned. The thread automatically 24 | // destructs when the connected function returns. 25 | // This method is recommended when connected functions have long execution 26 | // time and are independent. 27 | 28 | // STRAND: 29 | // Emission occurs asynchronously. 30 | // On connection a dedicated thread (per slot) is spawned to wait for new messages. 31 | // Emitted parameters are bound to the mapped function and enqueued on the 32 | // waiting thread. These messages are then processed synchronously in the 33 | // spawned thread. 34 | // This method is recommended when connected functions have longer execution 35 | // time, the overhead of creating/destroying a thread for each slot would be 36 | // unperformant, and/or connected functions need to be processed in order 37 | // of arrival (FIFO). 38 | 39 | // THREAD POOLED: 40 | // Emission occurs asynchronously. 41 | // On connection, if it is the first thread pooled function by any signal, 42 | // the thread pool is initialized with 8 threads, all listening for queued 43 | // emissions. The number of threads in the pool is not currently run-time 44 | // configurable but may be in the future. 45 | // Emitted parameters are bound to the mapped function and enqueued on the 46 | // one of the waiting threads. These messages are then processed when the 47 | // relevant queue is consumed by the mapped thread pool. 48 | // This method is recommended when connected functions have longer execution 49 | // time, the overhead of creating/destroying a thread for each slot would be 50 | // unperformant, the overhead of a waiting thread for each slot is 51 | // unnecessary, and/or connected functions do NOT need to be processed in 52 | // order of arrival. 53 | 54 | // DEFERRED_SYNCHRONOUS: 55 | // Emissions are queued up to be manually invoked through the invokeDeferred function 56 | // 57 | 58 | enum class ExecutorScheme { 59 | SYNCHRONOUS, 60 | DEFERRED_SYNCHRONOUS, 61 | ASYNCHRONOUS, 62 | STRAND, 63 | THREAD_POOLED 64 | }; 65 | 66 | } 67 | 68 | #endif /* BSIGNALS_EXECUTORSCHEME_H */ 69 | 70 | -------------------------------------------------------------------------------- /inc/BSignals/Signal.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Signal.hpp 3 | * Author: Barath Kannan 4 | * 5 | * Created on 14 June 2016, 9:12 PM 6 | */ 7 | 8 | #ifndef BSIGNALS_SIGNAL_HPP 9 | #define BSIGNALS_SIGNAL_HPP 10 | 11 | #include "BSignals/ExecutorScheme.h" 12 | #include "BSignals/details/SignalImpl.hpp" 13 | 14 | namespace BSignals { 15 | 16 | template 17 | class Signal { 18 | public: 19 | Signal() = default; 20 | 21 | Signal(bool enforceThreadSafety) 22 | : signalImpl(enforceThreadSafety) {} 23 | 24 | ~Signal() {} 25 | 26 | template 27 | int connectMemberSlot(ExecutorScheme scheme, F&& function, C&& instance) { 28 | return signalImpl.connectMemberSlot(scheme, std::forward(function), std::forward(instance)); 29 | } 30 | 31 | int connectSlot(ExecutorScheme scheme, std::function slot) { 32 | return signalImpl.connectSlot(scheme, slot); 33 | } 34 | 35 | void disconnectSlot(int id) { 36 | signalImpl.disconnectSlot(id); 37 | } 38 | 39 | void disconnectAllSlots() { 40 | signalImpl.disconnectAllSlots(); 41 | } 42 | 43 | void emitSignal(const Args& ... p) { 44 | signalImpl.emitSignal(p...); 45 | } 46 | 47 | void invokeDeferred() { 48 | signalImpl.invokeDeferred(); 49 | } 50 | 51 | void operator()(const Args& ... p) { 52 | signalImpl(p...); 53 | } 54 | 55 | private: 56 | BSignals::details::SignalImpl signalImpl; 57 | Signal(const Signal& that) = delete; 58 | void operator=(const Signal&) = delete; 59 | }; 60 | 61 | } /* namespace BSignals */ 62 | 63 | #endif /* BSIGNALS_SIGNAL_HPP */ -------------------------------------------------------------------------------- /inc/BSignals/details/AsynchronousSlot.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * File: AsynchronousSlot.hpp 3 | * Author: Barath Kannan 4 | * 5 | * Created on 24 August 2016, 11:06 PM 6 | */ 7 | 8 | #ifndef BSIGNALS_ASYNCHRONOUSSLOT_HPP 9 | #define BSIGNALS_ASYNCHRONOUSSLOT_HPP 10 | 11 | #include 12 | #include "BSignals/details/Slot.hpp" 13 | #include "BSignals/details/Semaphore.h" 14 | 15 | namespace BSignals{ namespace details{ 16 | 17 | template 18 | class AsynchronousSlot : public Slot{ 19 | public: 20 | AsynchronousSlot(std::function f, std::function validityCheck = nullptr) 21 | : Slot(f), checkIfValid(validityCheck){} 22 | 23 | ~AsynchronousSlot(){ 24 | sem.acquireAll(); 25 | } 26 | 27 | void execute(const Args& ... args){ 28 | sem.acquire(); 29 | std::thread slotThread([this, args...](){ 30 | if (!checkIfValid || checkIfValid()){ 31 | this->slotFunction(args...); 32 | } 33 | sem.release(); 34 | }); 35 | slotThread.detach(); 36 | } 37 | 38 | private: 39 | std::function checkIfValid; 40 | Semaphore sem{1024}; 41 | }; 42 | 43 | }} 44 | 45 | #endif /* BSIGNALS_ASYNCHRONOUSSLOT_HPP */ 46 | 47 | -------------------------------------------------------------------------------- /inc/BSignals/details/BasicTimer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: BasicTimer.h 3 | * Author: Barath Kannan 4 | * 5 | * Created on April 21, 2016, 12:09 PM 6 | */ 7 | 8 | #ifndef BSIGNALS_BASICTIMER_H 9 | #define BSIGNALS_BASICTIMER_H 10 | 11 | #include 12 | 13 | namespace BSignals{ namespace details{ 14 | class BasicTimer{ 15 | public: 16 | BasicTimer(); 17 | bool start(); 18 | bool stop(); 19 | 20 | bool isRunning(); 21 | double getElapsedSeconds(); 22 | double getElapsedMilliseconds(); 23 | double getElapsedMicroseconds(); 24 | double getElapsedNanoseconds(); 25 | 26 | std::chrono::duration getElapsedDuration(); 27 | 28 | protected: 29 | std::chrono::time_point begin, end; 30 | bool running; 31 | }; 32 | }} 33 | #endif /* BSIGNALS_BASICTIMER_H */ 34 | -------------------------------------------------------------------------------- /inc/BSignals/details/ContiguousMPMCQueue.hpp: -------------------------------------------------------------------------------- 1 | // This is free and unencumbered software released into the public domain. 2 | 3 | // Anyone is free to copy, modify, publish, use, compile, sell, or 4 | // distribute this software, either in source code form or as a compiled 5 | // binary, for any purpose, commercial or non-commercial, and by any 6 | // means. 7 | 8 | // In jurisdictions that recognize copyright laws, the author or authors 9 | // of this software dedicate any and all copyright interest in the 10 | // software to the public domain. We make this dedication for the benefit 11 | // of the public at large and to the detriment of our heirs and 12 | // successors. We intend this dedication to be an overt act of 13 | // relinquishment in perpetuity of all present and future rights to this 14 | // software under copyright law. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | // OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | // For more information, please refer to 25 | 26 | // Implementation of Dmitry Vyukov's MPMC algorithm 27 | // http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue 28 | /* 29 | * File: ContiguousMPMCQueue.hpp 30 | * Author: Barath Kannan 31 | * This is an adaptation of https://github.com/mstump/queues/blob/master/include/mpmc-bounded-queue.hpp 32 | * Created on 20 June 2016, 1:01 AM 33 | */ 34 | 35 | #ifndef BSIGNALS_CONTIGUOUSMPMCQUEUE_HPP 36 | #define BSIGNALS_CONTIGUOUSMPMCQUEUE_HPP 37 | 38 | #include 39 | #include 40 | 41 | namespace BSignals{ namespace details{ 42 | template 43 | class ContiguousMPMCQueue 44 | { 45 | public: 46 | 47 | ContiguousMPMCQueue(){ 48 | static_assert((N != 0) && ((N & (~N + 1)) == N), "size of MPMC queue must be power of 2"); 49 | for (size_t i=0; iseq.load(std::memory_order_acquire); 59 | intptr_t dif = (intptr_t) node_seq - (intptr_t) head_seq; 60 | 61 | if (dif == 0){ 62 | if (_head_seq.compare_exchange_weak(head_seq, head_seq + 1, std::memory_order_relaxed)) { 63 | node->data = data; 64 | node->seq.store(head_seq + 1, std::memory_order_release); 65 | return true; 66 | } 67 | } 68 | else if (dif < 0){ 69 | return false; 70 | } 71 | else{ 72 | head_seq = _head_seq.load(std::memory_order_relaxed); 73 | } 74 | } 75 | } 76 | 77 | bool dequeue(T& data){ 78 | size_t tail_seq = _tail_seq.load(std::memory_order_relaxed); 79 | while(true){ 80 | node_t* node = &_buffer[tail_seq & (N-1)]; 81 | size_t node_seq = node->seq.load(std::memory_order_acquire); 82 | intptr_t dif = (intptr_t) node_seq - (intptr_t)(tail_seq + 1); 83 | if (dif == 0) { 84 | if (_tail_seq.compare_exchange_weak(tail_seq, tail_seq + 1, std::memory_order_relaxed)) { 85 | data = node->data; 86 | node->seq.store(tail_seq + N, std::memory_order_release); 87 | return true; 88 | } 89 | } 90 | else if (dif < 0){ 91 | return false; 92 | } 93 | else{ 94 | tail_seq = _tail_seq.load(std::memory_order_relaxed); 95 | } 96 | } 97 | } 98 | 99 | private: 100 | 101 | struct node_t{ 102 | T data; 103 | std::atomic seq; 104 | }; 105 | 106 | std::array _buffer; 107 | char pad0[64]; 108 | std::atomic _head_seq{0}; 109 | char pad1[64]; 110 | std::atomic _tail_seq{0}; 111 | 112 | ContiguousMPMCQueue(const ContiguousMPMCQueue&) {} 113 | void operator=(const ContiguousMPMCQueue&) {} 114 | }; 115 | }} 116 | #endif -------------------------------------------------------------------------------- /inc/BSignals/details/DeferredSlot.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * File: DeferredSlot.hpp 3 | * Author: Barath Kannan 4 | * 5 | * Created on 24 August 2016, 11:37 PM 6 | */ 7 | 8 | #ifndef BSIGNALS_DEFERREDSLOT_HPP 9 | #define BSIGNALS_DEFERREDSLOT_HPP 10 | 11 | #include "BSignals/details/Slot.hpp" 12 | #include "BSignals/details/MPSCQueue.hpp" 13 | 14 | namespace BSignals{ namespace details{ 15 | 16 | template 17 | class DeferredSlot : public Slot{ 18 | public: 19 | DeferredSlot(std::function f, std::shared_ptr, uint32_t>>> dq, uint32_t slotId) 20 | : Slot(f), deferredQueue(dq), id(slotId){} 21 | 22 | void execute(const Args& ... args){ 23 | deferredQueue->enqueue({[this, args...](){this->slotFunction(args...);}, id}); 24 | } 25 | 26 | ExecutorScheme getScheme() const{ 27 | return ExecutorScheme::DEFERRED_SYNCHRONOUS; 28 | } 29 | 30 | private: 31 | std::shared_ptr, uint32_t>>> deferredQueue{nullptr}; 32 | const uint32_t id; 33 | }; 34 | }} 35 | 36 | #endif /* BSIGNALS_DEFERREDSLOT_HPP */ 37 | 38 | -------------------------------------------------------------------------------- /inc/BSignals/details/MPSCQueue.hpp: -------------------------------------------------------------------------------- 1 | // This is free and unencumbered software released into the public domain. 2 | 3 | // Anyone is free to copy, modify, publish, use, compile, sell, or 4 | // distribute this software, either in source code form or as a compiled 5 | // binary, for any purpose, commercial or non-commercial, and by any 6 | // means. 7 | 8 | // In jurisdictions that recognize copyright laws, the author or authors 9 | // of this software dedicate any and all copyright interest in the 10 | // software to the public domain. We make this dedication for the benefit 11 | // of the public at large and to the detriment of our heirs and 12 | // successors. We intend this dedication to be an overt act of 13 | // relinquishment in perpetuity of all present and future rights to this 14 | // software under copyright law. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | // OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | // For more information, please refer to 25 | 26 | // C++ implementation of Dmitry Vyukov's non-intrusive lock free unbounded MPSC queue 27 | // http://www.1024cores.net/home/lock-free-algorithms/queues/non-intrusive-mpsc-node-based-queue 28 | /* 29 | * File: MPSCQueue.hpp 30 | * Author: Barath Kannan 31 | * This is an adaptation of https://github.com/mstump/queues/blob/master/include/mpsc-queue.hpp 32 | * The queue has been modified such that it can also be used as a blocking queue 33 | * Aligned storage was removed, was causing segmentation faults and didn't improve performance 34 | * Created on 14 June 2016, 1:14 AM 35 | */ 36 | 37 | 38 | #ifndef BSIGNALS_MPSCQUEUE_HPP 39 | #define BSIGNALS_MPSCQUEUE_HPP 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include "BSignals/details/ContiguousMPMCQueue.hpp" 48 | 49 | namespace BSignals{ namespace details{ 50 | 51 | template 52 | class MPSCQueue{ 53 | public: 54 | 55 | MPSCQueue(){} 56 | 57 | ~MPSCQueue(){ 58 | T output; 59 | while(this->dequeue(output)); 60 | listNode* front = _head.load(std::memory_order_relaxed); 61 | delete front; 62 | } 63 | 64 | void enqueue(const T& input){ 65 | if (fastEnqueue(input)) return; 66 | slowEnqueue(input); 67 | } 68 | 69 | //only try to enqueue to the cache 70 | bool fastEnqueue(const T& input){ 71 | if (_cache.enqueue(input)){ 72 | if (waitingReader.load(std::memory_order_acquire)) _cv.notify_one(); 73 | return true; 74 | } 75 | return false; 76 | } 77 | 78 | bool dequeue(T& output){ 79 | return (fastDequeue(output) || slowDequeue(output)); 80 | } 81 | 82 | //only try to dequeue from the cache 83 | bool fastDequeue(T &output){ 84 | return _cache.dequeue(output); 85 | } 86 | 87 | //transfer as many items as possible to the cache 88 | void transferMaxToCache(){ 89 | T output; 90 | while (slowDequeue(output)){ 91 | if (!fastEnqueue(output)){ 92 | slowEnqueue(output); 93 | break; 94 | } 95 | } 96 | } 97 | 98 | void blockingDequeue(T& output){ 99 | std::unique_lock lock(_mutex); 100 | waitingReader.store(true, std::memory_order_release); 101 | while (!dequeue(output)){ 102 | _cv.wait(lock); 103 | } 104 | waitingReader.store(false, std::memory_order_release); 105 | } 106 | 107 | private: 108 | inline bool slowDequeue(T &output){ 109 | listNode* tail = _tail.load(std::memory_order_relaxed); 110 | listNode* next = tail->next.load(std::memory_order_acquire); 111 | if (next == nullptr) return false; 112 | 113 | output = next->data; 114 | _tail.store(next, std::memory_order_release); 115 | delete tail; 116 | return true; 117 | } 118 | 119 | inline void slowEnqueue(const T& input){ 120 | listNode* node = new listNode(); 121 | node->data = input; 122 | listNode* prev_head = _head.exchange(node, std::memory_order_acq_rel); 123 | prev_head->next.store(node, std::memory_order_release); 124 | 125 | if (waitingReader.load(std::memory_order_acquire)) _cv.notify_one(); 126 | } 127 | 128 | struct listNode{ 129 | T data; 130 | std::atomic next{nullptr}; 131 | }; 132 | 133 | ContiguousMPMCQueue _cache; 134 | std::atomic _head{new listNode}; 135 | std::atomic _tail{_head.load(std::memory_order_relaxed)}; 136 | std::mutex _mutex; 137 | std::condition_variable _cv; 138 | std::atomic waitingReader{false}; 139 | 140 | MPSCQueue(const MPSCQueue&) {} 141 | void operator=(const MPSCQueue&) {} 142 | }; 143 | }} 144 | 145 | #endif 146 | -------------------------------------------------------------------------------- /inc/BSignals/details/Semaphore.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Semaphore.h 3 | * Author: Barath Kannan 4 | * 5 | * Created on 30 May 2016, 6:49 PM 6 | */ 7 | 8 | #ifndef BSIGNALS_SEMAPHORE_H 9 | #define BSIGNALS_SEMAPHORE_H 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace BSignals{ namespace details{ 16 | class Semaphore{ 17 | public: 18 | Semaphore(uint32_t size); 19 | ~Semaphore(); 20 | 21 | void acquire(); 22 | void acquireAll(); 23 | void release(); 24 | 25 | private: 26 | std::mutex semMutex; 27 | std::condition_variable semCV; 28 | std::atomic semCounter; 29 | const uint32_t initial; 30 | }; 31 | }} 32 | #endif /* BSIGNALS_SEMAPHORE_H */ 33 | 34 | -------------------------------------------------------------------------------- /inc/BSignals/details/SharedMutex.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: SharedMutex.h 3 | * Author: Barath Kannan 4 | * 5 | * Created on 23 August 2016, 6:42 AM 6 | */ 7 | 8 | #ifndef SHAREDMUTEX_H 9 | #define SHAREDMUTEX_H 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace BSignals{ namespace details{ 16 | 17 | class SharedMutex{ 18 | public: 19 | SharedMutex() = default; 20 | SharedMutex(const SharedMutex& that) = delete; 21 | void operator=(const SharedMutex&) = delete; 22 | 23 | void lock(); 24 | void lock_shared(); 25 | void unlock(); 26 | void unlock_shared(); 27 | 28 | private: 29 | std::mutex m_mutex; 30 | std::condition_variable m_condVar; 31 | std::atomic m_readers{0}; 32 | std::atomic m_writers{0}; 33 | std::atomic m_writer{false}; 34 | }; 35 | 36 | }} 37 | 38 | #endif /* SHAREDMUTEX_H */ 39 | 40 | -------------------------------------------------------------------------------- /inc/BSignals/details/SignalImpl.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * File: SignalImpl.hpp 3 | * Author: Barath Kannan 4 | * Signal/Slots C++11 implementation 5 | * Created on May 10, 2016, 5:57 PM 6 | */ 7 | 8 | #ifndef BSIGNALS_SIGNALIMPL_HPP 9 | #define BSIGNALS_SIGNALIMPL_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "BSignals/ExecutorScheme.h" 22 | #include "BSignals/details/MPSCQueue.hpp" 23 | #include "BSignals/details/WheeledThreadPool.h" 24 | #include "BSignals/details/Semaphore.h" 25 | #include "BSignals/details/SharedMutex.h" 26 | #include "BSignals/details/Slot.hpp" 27 | #include "BSignals/details/StrandSlot.hpp" 28 | #include "BSignals/details/ThreadPooledSlot.hpp" 29 | #include "BSignals/details/AsynchronousSlot.hpp" 30 | #include "BSignals/details/DeferredSlot.hpp" 31 | #include "BSignals/details/SynchronousSlot.hpp" 32 | 33 | namespace BSignals{ namespace details{ 34 | 35 | template 36 | class SignalImpl { 37 | public: 38 | SignalImpl() = default; 39 | 40 | SignalImpl(bool enforceThreadSafety) 41 | : enableEmissionGuard{enforceThreadSafety} {} 42 | 43 | ~SignalImpl(){ 44 | disconnectAllSlots(); 45 | } 46 | 47 | template 48 | int connectMemberSlot(BSignals::ExecutorScheme scheme, F&& function, C&& instance){ 49 | //type check assertions 50 | static_assert(std::is_member_function_pointer::value, "function is not a member function"); 51 | static_assert(std::is_object>::value, "instance is not a class object"); 52 | 53 | //Construct a bound function from the function pointer and object 54 | auto boundFunc = objectBind(function, instance); 55 | return connectSlot(scheme, boundFunc); 56 | } 57 | 58 | int connectSlot(BSignals::ExecutorScheme scheme, std::function slot){ 59 | uint32_t id = currentId.fetch_add(1); 60 | if (enableEmissionGuard){ 61 | std::lock_guard lock(connectBufferLock); 62 | connectBuffer.emplace(id, ConnectDescriptor{scheme, slot}); 63 | connectBufferDirty = true; 64 | return id; 65 | } 66 | else{ 67 | return connectSlotFunction(id, scheme, slot); 68 | } 69 | } 70 | 71 | void disconnectSlot(int id){ 72 | if (enableEmissionGuard){ 73 | slotLock.lock_shared(); 74 | auto it = slots.find(id); 75 | if (it == slots.end()) return; 76 | it->second->markForDeath(); 77 | slotLock.unlock_shared(); 78 | } 79 | else{ 80 | disconnectSlotFunction(id); 81 | } 82 | } 83 | 84 | void disconnectAllSlots(){ 85 | slotLock.lock(); 86 | slots.clear(); 87 | slotLock.unlock(); 88 | } 89 | 90 | void emitSignal(const Args& ... p){ 91 | enableEmissionGuard ? emitSignalThreadSafe(p...) : emitSignalUnsafe(p...); 92 | } 93 | 94 | void invokeDeferred(){ 95 | slotLock.lock_shared(); 96 | std::pair, uint32_t> deferredInvocation; 97 | if (!deferredQueue) return; 98 | while (deferredQueue->dequeue(deferredInvocation)){ 99 | if (!enableEmissionGuard || getIsStillConnectedFromExecutor(deferredInvocation.second)){ 100 | deferredInvocation.first(); 101 | } 102 | } 103 | slotLock.unlock_shared(); 104 | } 105 | 106 | void operator()(const Args &... p){ 107 | emitSignal(p...); 108 | } 109 | 110 | private: 111 | SignalImpl(const SignalImpl& that) = delete; 112 | void operator=(const SignalImpl&) = delete; 113 | 114 | inline void disconnectSlotFunction(uint32_t id){ 115 | slotLock.lock(); 116 | auto it = slots.find(id); 117 | if (it == slots.end()) return; 118 | slots.erase(it); 119 | slotLock.unlock(); 120 | } 121 | 122 | int connectSlotFunction(uint32_t id, BSignals::ExecutorScheme scheme, std::function slot){ 123 | std::unique_ptr> slotInstance{nullptr}; 124 | switch(scheme){ 125 | case(BSignals::ExecutorScheme::STRAND): 126 | slotInstance = std::make_unique>(slot); 127 | break; 128 | case(BSignals::ExecutorScheme::THREAD_POOLED): 129 | if (enableEmissionGuard) slotInstance = std::make_unique>(slot, [this, id](){return getIsStillConnectedFromExecutor(id);}); 130 | else slotInstance = std::make_unique>(slot); 131 | break; 132 | case(BSignals::ExecutorScheme::ASYNCHRONOUS): 133 | if (enableEmissionGuard) slotInstance = std::make_unique>(slot, [this, id](){return getIsStillConnectedFromExecutor(id);}); 134 | else slotInstance = std::make_unique>(slot); 135 | break; 136 | case(BSignals::ExecutorScheme::DEFERRED_SYNCHRONOUS): 137 | initializeDeferredQueue(); 138 | slotInstance = std::make_unique>(slot, deferredQueue, id); 139 | break; 140 | case(BSignals::ExecutorScheme::SYNCHRONOUS): 141 | slotInstance = std::make_unique>(slot); 142 | break; 143 | } 144 | slotLock.lock(); 145 | slots.emplace_hint(slots.end(), std::piecewise_construct, std::make_tuple(id), 146 | std::make_tuple(std::move(slotInstance))); 147 | slotLock.unlock(); 148 | return (int)id; 149 | } 150 | 151 | inline void initializeDeferredQueue(){ 152 | if (!deferredQueue) deferredQueue = std::shared_ptr, uint32_t>>>(new MPSCQueue, uint32_t>>); 153 | } 154 | 155 | inline void emitSignalUnsafe(const Args& ... p){ 156 | for (auto const &kvpair : slots){ 157 | kvpair.second->execute(p...); 158 | } 159 | } 160 | 161 | inline bool getIsStillConnectedFromExecutor(uint32_t id) const{ 162 | slotLock.lock_shared(); 163 | auto it = slots.find(id); 164 | bool retVal = (it != slots.end() && it->second->isAlive()); 165 | slotLock.unlock_shared(); 166 | return retVal; 167 | } 168 | 169 | inline void emitSignalThreadSafe(const Args& ... p){ 170 | while (connectBufferDirty.load(std::memory_order_acquire)){ 171 | connectBufferLock.lock(); 172 | if (!connectBufferDirty.load(std::memory_order_acquire)){ 173 | connectBufferLock.unlock(); 174 | break; 175 | } 176 | for (auto const &kvpair : connectBuffer){ 177 | connectSlotFunction(kvpair.first, kvpair.second.scheme, kvpair.second.slot); 178 | } 179 | connectBuffer.clear(); 180 | connectBufferDirty.store(false, std::memory_order_release); 181 | connectBufferLock.unlock(); 182 | slotLock.lock(); 183 | for (auto it = slots.begin(); it!= slots.end();){ 184 | if (!it->second->isAlive()){ 185 | it = slots.erase(it); 186 | } 187 | else{ 188 | ++it; 189 | } 190 | } 191 | slotLock.unlock(); 192 | } 193 | slotLock.lock_shared(); 194 | for (auto const &kvpair : slots){ 195 | if (kvpair.second->isAlive()){ 196 | kvpair.second->execute(p...); 197 | } 198 | } 199 | slotLock.unlock_shared(); 200 | } 201 | 202 | //Reference to instance 203 | template 204 | std::function objectBind(F&& function, I&& instance) const { 205 | return[=, &instance](Args... args){ 206 | (instance.*function)(args...); 207 | }; 208 | } 209 | 210 | //Pointer to instance 211 | template 212 | std::function objectBind(F&& function, I* instance) const { 213 | return objectBind(function, *instance); 214 | } 215 | 216 | //Atomically incremented slotId 217 | std::atomic currentId {0}; 218 | 219 | //EmissionGuard determines if it is necessary to guard emission with a shared mutex 220 | //This is only required if connection/disconnection could be interleaved with emission 221 | const bool enableEmissionGuard {false}; 222 | 223 | //Deferred invocation queue 224 | //Use unique pointer so that full MPSC queue overhead is only required if there is a deferred slot 225 | std::shared_ptr, uint32_t>>> deferredQueue{nullptr}; 226 | 227 | struct ConnectDescriptor{ 228 | ExecutorScheme scheme; 229 | std::function slot; 230 | }; 231 | 232 | mutable SharedMutex slotLock; 233 | std::map> > slots; 234 | 235 | mutable std::mutex connectBufferLock; 236 | std::atomic connectBufferDirty{false}; 237 | std::map connectBuffer; 238 | }; 239 | 240 | }} 241 | 242 | #endif /* BSIGNALS_SIGNALIMPL_HPP */ 243 | -------------------------------------------------------------------------------- /inc/BSignals/details/Slot.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Slot.hpp 3 | * Author: Barath Kannan 4 | * 5 | * Created on 24 August 2016, 8:07 PM 6 | */ 7 | 8 | #ifndef BSIGNALS_SLOT_HPP 9 | #define BSIGNALS_SLOT_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | #include "BSignals/ExecutorScheme.h" 15 | 16 | namespace BSignals{ namespace details{ 17 | 18 | template 19 | class Slot{ 20 | public: 21 | Slot(std::function f) : slotFunction(f){}; 22 | virtual ~Slot(){}; 23 | virtual void execute(const Args& ... args) = 0; 24 | 25 | bool isAlive() const{ 26 | return (alive.load(std::memory_order_acquire)); 27 | } 28 | 29 | void markForDeath(){ 30 | alive.store(false, std::memory_order_release); 31 | } 32 | 33 | protected: 34 | template 35 | void callFuncWithTuple(const std::tuple& tuple, std::index_sequence) { 36 | slotFunction(std::get(tuple)...); 37 | } 38 | 39 | std::function slotFunction; 40 | std::atomic alive{true}; 41 | }; 42 | 43 | }} 44 | 45 | #endif /* BSIGNALS_SLOT_HPP */ 46 | 47 | -------------------------------------------------------------------------------- /inc/BSignals/details/StrandSlot.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * File: StrandSlot.hpp 3 | * Author: Barath Kannan 4 | * 5 | * Created on 24 August 2016, 8:17 PM 6 | */ 7 | 8 | #ifndef BSIGNALS_STRANDSLOT_HPP 9 | #define BSIGNALS_STRANDSLOT_HPP 10 | 11 | #include 12 | #include 13 | #include "BSignals/details/Slot.hpp" 14 | #include "BSignals/details/WheeledThreadPool.h" 15 | #include "BSignals/details/MPSCQueue.hpp" 16 | 17 | namespace BSignals{ namespace details{ 18 | 19 | template 20 | class StrandSlot : public Slot{ 21 | public: 22 | StrandSlot(std::function f) : Slot(f){ 23 | strandThread = std::thread(&StrandSlot::queueListener, this); 24 | } 25 | 26 | ~StrandSlot(){ 27 | stop = true; 28 | strandQueue.enqueue(std::tuple{}); 29 | strandThread.join(); 30 | } 31 | 32 | void execute(const Args& ... args){ 33 | strandQueue.enqueue(std::tuple(args...)); 34 | } 35 | 36 | private: 37 | void queueListener(){ 38 | std::tuple tuple{}; 39 | auto maxWait = WheeledThreadPool::getMaxWait(); 40 | std::chrono::duration waitTime = std::chrono::nanoseconds(1); 41 | while (!stop){ 42 | if (strandQueue.dequeue(tuple)){ 43 | if (!stop) this->callFuncWithTuple(tuple, std::index_sequence_for()); 44 | waitTime = std::chrono::nanoseconds(1); 45 | } 46 | else{ 47 | std::this_thread::sleep_for(waitTime); 48 | waitTime*=2; 49 | } 50 | if (waitTime > maxWait){ 51 | strandQueue.blockingDequeue(tuple); 52 | if (!stop) this->callFuncWithTuple(tuple, std::index_sequence_for()); 53 | waitTime = std::chrono::nanoseconds(1); 54 | } 55 | } 56 | } 57 | 58 | MPSCQueue> strandQueue; 59 | std::thread strandThread; 60 | bool stop{false}; 61 | }; 62 | 63 | }} 64 | 65 | #endif /* BSIGNALS_STRANDSLOT_HPP */ 66 | 67 | -------------------------------------------------------------------------------- /inc/BSignals/details/SynchronousSlot.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * File: SynchronousSlot.hpp 3 | * Author: Barath Kannan 4 | * 5 | * Created on 24 August 2016, 9:22 PM 6 | */ 7 | 8 | #ifndef BSIGNALS_SYNCHRONOUSSLOT_HPP 9 | #define BSIGNALS_SYNCHRONOUSSLOT_HPP 10 | 11 | #include "BSignals/details/Slot.hpp" 12 | 13 | namespace BSignals{ namespace details{ 14 | 15 | template 16 | class SynchronousSlot : public Slot{ 17 | public: 18 | SynchronousSlot(std::function f) : Slot(f){} 19 | 20 | void execute(const Args& ... args){ 21 | this->slotFunction(args...); 22 | } 23 | 24 | }; 25 | 26 | }} 27 | #endif /* BSIGNALS_SYNCHRONOUSSLOT_HPP */ 28 | 29 | -------------------------------------------------------------------------------- /inc/BSignals/details/ThreadPooledSlot.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * File: ThreadPooledSlot.hpp 3 | * Author: Barath Kannan 4 | * 5 | * Created on 24 August 2016, 10:20 PM 6 | */ 7 | 8 | #ifndef BSIGNALS_THREADPOOLEDSLOT_HPP 9 | #define BSIGNALS_THREADPOOLEDSLOT_HPP 10 | 11 | #include "BSignals/details/Slot.hpp" 12 | #include "BSignals/details/WheeledThreadPool.h" 13 | 14 | namespace BSignals{ namespace details{ 15 | 16 | template 17 | class ThreadPooledSlot : public Slot{ 18 | public: 19 | ThreadPooledSlot(std::function f, std::function validityCheck = nullptr) 20 | : Slot(f), checkIfValid(validityCheck){ 21 | WheeledThreadPool::startup(); 22 | } 23 | 24 | void execute(const Args& ... args){ 25 | WheeledThreadPool::run([this, args...](){ 26 | if (!checkIfValid || checkIfValid()){ 27 | this->slotFunction(args...); 28 | } 29 | }); 30 | } 31 | 32 | private: 33 | std::function checkIfValid; 34 | }; 35 | 36 | }} 37 | 38 | #endif /* BSIGNALS_THREADPOOLEDSLOT_HPP */ 39 | 40 | -------------------------------------------------------------------------------- /inc/BSignals/details/Wheel.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * File: Wheel.hpp 3 | * Author: Barath Kannan 4 | * 5 | * Created on 13 June 2016, 12:50 AM 6 | */ 7 | 8 | #ifndef BSIGNALS_WHEEL_HPP 9 | #define BSIGNALS_WHEEL_HPP 10 | 11 | #include 12 | 13 | namespace BSignals{ namespace details{ 14 | 15 | //T must be default constructable 16 | template 17 | class Wheel{ 18 | public: 19 | 20 | T& getSpoke() noexcept{ 21 | return wheelymajig[fetchWrapIncrement()]; 22 | } 23 | 24 | T& getSpokeRandom() noexcept{ 25 | return wheelymajig[std::rand()%N]; 26 | } 27 | 28 | T& getSpoke(uint32_t index) noexcept{ 29 | return wheelymajig[index]; 30 | } 31 | 32 | uint32_t getIndex() noexcept{ 33 | return fetchWrapIncrement(); 34 | } 35 | 36 | const uint32_t size() noexcept{ 37 | return N; 38 | } 39 | 40 | private: 41 | inline uint32_t fetchWrapIncrement() noexcept{ 42 | uint32_t oldValue = currentElement.load(); 43 | while (!currentElement.compare_exchange_weak(oldValue, (oldValue+1 == N) ? 0 : oldValue+1)); 44 | return oldValue; 45 | } 46 | char padding0[64]; 47 | std::atomic currentElement{0}; 48 | char padding1[64]; 49 | std::array wheelymajig; 50 | char padding2[64]; 51 | }; 52 | }} 53 | 54 | #endif /* BSIGNALS_WHEEL_HPP */ 55 | 56 | -------------------------------------------------------------------------------- /inc/BSignals/details/WheeledThreadPool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: WheeledThreadPool.h 3 | * Author: Barath Kannan 4 | * 5 | * Created on 13 June 2016, 3:36 PM 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "BSignals/details/Wheel.hpp" 15 | #include "BSignals/details/MPSCQueue.hpp" 16 | 17 | #ifndef BSIGNALS_WHEELEDTHREADPOOL_H 18 | #define BSIGNALS_WHEELEDTHREADPOOL_H 19 | 20 | namespace BSignals{ namespace details{ 21 | 22 | class WheeledThreadPool { 23 | public: 24 | 25 | template 26 | static void run(const std::function &task, const Args &... p) noexcept{ 27 | run([task, p...](){task(p...);}); 28 | } 29 | 30 | static void run(const std::function task) noexcept; 31 | 32 | //only invoke start up if a thread pooled slot has been connected 33 | static void startup(); 34 | 35 | static std::chrono::duration getMaxWait(); 36 | private: 37 | static void queueListener(uint32_t index); 38 | static class _init { 39 | public: 40 | _init(); 41 | ~_init(); 42 | } _initializer; 43 | 44 | static const uint32_t nThreads{32}; 45 | static std::chrono::duration maxWait; 46 | static std::mutex tpLock; 47 | static bool isStarted; 48 | static Wheel, 256>, BSignals::details::WheeledThreadPool::nThreads> threadPooledFunctions; 49 | static std::vector queueMonitors; 50 | }; 51 | }} 52 | 53 | #endif /* BSIGNALS_WHEELEDTHREADPOOL_H */ -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Barath Kannan 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included 12 | in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 2 | #||BUILD FLAGS||# 3 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 4 | 5 | #Generates moc files from headers for QT applications 6 | BUILD_MOCS = 0 7 | 8 | #Generates dynamic (shared object) and static (archive) from non-main objects 9 | BUILD_LIB = 1 10 | 11 | #Generates binary from all objects 12 | BUILD_BIN = 0 13 | 14 | #Generates test application 15 | BUILD_TESTS = 1 16 | 17 | #Runs pre-build scripts 18 | RUN_PREBUILD = 1 19 | 20 | #Runs post-build scripts 21 | RUN_POSTBUILD = 0 22 | 23 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 24 | #||EXTERNALS||# 25 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 26 | GOOGLETEST_INC = 3rdparty/googletest/inc 27 | GOOGLETEST_LIB = 3rdparty/googletest/gen/debug/lib/static/libgtest.a 28 | 29 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 30 | #||BUILD CONFIG||# 31 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 32 | 33 | ###################### 34 | ## Compiler Options ## 35 | ###################### 36 | 37 | #Compiler 38 | CC = g++ 39 | 40 | #Compiler options 41 | OPTS = -Wall -std=c++14 -fPIC 42 | RELEASE_OPTS = -O3 43 | DEBUG_OPTS = -g 44 | 45 | #Static library archiver 46 | LG = ar 47 | 48 | #Static archiver options 49 | LGOPTS = -r 50 | 51 | #Project source file extensions 52 | SRCTYPES = cpp cc c 53 | 54 | #Project header file extensions 55 | HTYPES = h hpp 56 | 57 | ########################### 58 | ## Project Configuration ## 59 | ########################### 60 | 61 | PROJECT = BSignals 62 | VERSION = 2.0.0-alpha.1 63 | 64 | #Define Flags 65 | DEFINE = LINUX 66 | 67 | #Pre-Build Scripts 68 | PREBUILD = +$(MAKE) -C 3rdparty/googletest 69 | 70 | #Post-Build Scripts 71 | POSTBUILD = 72 | 73 | ############################ 74 | # Directory Configuration ## 75 | ############################ 76 | 77 | # Project Directories 78 | SRCDIR = src 79 | INCDIR = inc 80 | TESTDIR = test 81 | 82 | #Generated Directories 83 | GENDIR = gen 84 | 85 | #################################### 86 | # External Dependencies and Paths ## 87 | #################################### 88 | 89 | # External Include Directories 90 | EXTINC = 91 | 92 | # External/System Libraries 93 | LIBDIRS = 94 | LIBS = pthread 95 | 96 | #Additional Source files to compile 97 | ADDSRC = 98 | 99 | # External Links 100 | LINKS = 101 | 102 | #Additional files/folders to clean 103 | CLEANFILES = 104 | 105 | ########################### 106 | # Unit Test Dependencies ## 107 | ########################### 108 | 109 | #Unit testing library 110 | TESTLIB = $(GOOGLETEST_LIB) 111 | 112 | #Unit testing library include path 113 | TESTINC = $(GOOGLETEST_INC) 114 | 115 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 116 | #||ADDITIONAL OPTIONS||# 117 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 118 | 119 | # debug - builds with debug options by default (can be manually specified by invoking the debug target) 120 | # release - builds with release options by default (can be manually specified by invoking the release target) 121 | BUILD_TYPE = release 122 | 123 | # 0 = Include only INCDIR 124 | # 1 = Recursively include all directories in INCDIR 125 | RECURSIVELY_INCLUDE_LOCAL = 0 126 | 127 | # 0 = Include only directories listed in EXTINC 128 | # 1 = Recursively include all directories for each directory specified in extinc 129 | RECURSIVELY_INCLUDE_EXTERNAL = 0 130 | 131 | # 0 = Don't include main object file in generated libraries 132 | # 1 = Include main object file in generated libraries 133 | MAIN_OBJECT_IN_LIBRARIES = 0 134 | 135 | # 0 = The project contains no main method (i.e. exclusively a library) 136 | # 1 = The project contains at least one main method 137 | PROJECT_CONTAINS_MAIN = 0 138 | 139 | # If they exist, sources with main methods can be explicitly specified here. 140 | # This saves compilation time, as the makefile will no longer need to 141 | # search the object files for the main symbol 142 | EXPLICIT_MAIN_SOURCE = 143 | 144 | # 0 = Binary names are generated from the project name and the main source file name(s) 145 | # 1 = Binary names are generated from the project name only (only valid when there is 1 main source) 146 | # 2 = Binary source names are generated from the main source file name(s) only 147 | BINARY_NAMING_CONVENTION = 0 148 | 149 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 150 | #||BUILD SCRIPT||# 151 | #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 152 | include core.mk 153 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # BSignals 2 | 3 | NOTE: This library is deprecated and unmaintained. 4 | It will eventually be replaced by: https://github.com/Barath-Kannan/exo 5 | 6 | This is a signals and slots library for C++14. 7 | 8 | The intention is to provide a fast thread safe signals/slots mechanism which is easy to use and has no external dependencies. The main differentiating factor between this signals/slots library and others is that it provides the means to specify the type of executor used. 9 | 10 | ##Table of Contents 11 | - [BSignals](#bsignals) 12 | - [Table of Contents](#table-of-contents) 13 | - [Features](#features) 14 | - [Building and Linking](#building-and-linking) 15 | - [Usage](#usage) 16 | - [Simple Usage Example](#simple-usage-example) 17 | - [Include](#include) 18 | - [Construct](#construct) 19 | - [Connect](#connect) 20 | - [Emit](#emit) 21 | - [Disconnect](#disconnect) 22 | - [Executors](#executors) 23 | - [Synchronous](#synchronous) 24 | - [Deferred Synchronous](#deferred-synchronous) 25 | - [Asynchronous](#asynchronous) 26 | - [Strand](#strand) 27 | - [Thread Pooled](#thread-pooled) 28 | - [To Do](#to-do) 29 | - [Limitations](#limitations) 30 | 31 | ##Features 32 | - Simple signals and slots mechanism 33 | - Specifiable executor (synchronous, synchronous deferred, asynchronous, strand, thread pooled) 34 | - Constructor specifiable thread safety 35 | - Thread safety only required for interleaved emission/connection/disconnection 36 | 37 | ##Building and Linking 38 | To build the default release build, type 39 | ``` 40 | make 41 | ``` 42 | in the base directory. 43 | To build the debug build, type 44 | ``` 45 | make debug 46 | ``` 47 | in the base directory. 48 | Currently only makefile based build is supported - other build systems may be added 49 | in the future. 50 | For dynamic linking, a shared object is generated in 51 | ``` 52 | {BASE_DIRECTORY}/gen/release/lib/dynamic 53 | ``` 54 | For static linking, an archive is generated in 55 | ``` 56 | {BASE_DIRECTORY}/gen/release/lib/static 57 | ``` 58 | The gtest binary is generated in 59 | ``` 60 | {BASE_DIRECTORY}/gen/release/test 61 | ``` 62 | ##Usage 63 | 64 | Below is a summary of how to use the Signal class. 65 | 66 | For more examples, see SignalTest.cpp in the test directory. 67 | 68 | ####Simple Usage Example 69 | ``` 70 | #include 71 | #include 72 | 73 | int main(int argc, char *argv[]){ 74 | BSignals::Signal testSignal; 75 | int id = testSignal.connectSlot(BSignals::ExecutorScheme::SYNCHRONOUS, 76 | [](int x, int y){ 77 | std::cout << x << " + " << y << " = " << x + y << std::endl; 78 | }); 79 | testSignal.emitSignal(1, 2); 80 | testSignal.disconnectSlot(id); 81 | return 0; 82 | } 83 | ``` 84 | ####Include 85 | ``` 86 | #include 87 | ``` 88 | ####Construct 89 | ``` 90 | //Default constructor 91 | BSignals::Signal signalA; // T1..TN are the types required by emission 92 | ``` 93 | - Full thread safety is disabled by default for performance reasons 94 | - Interleaved emissions are always thread safe 95 | - Interleaved connects/disconnects are always thread safe 96 | - Interleaved connect/disconnect with emissions are not thread safe 97 | 98 | If you cannot make guarantees that the emission and connection/disconnection will 99 | not be interleaved, or you wish to connect/disconnect a slot or slots from within a 100 | slot function, enable thread safety using the constructor: 101 | ``` 102 | BSignals::Signal signalB(true); 103 | ``` 104 | ####Connect 105 | Connected functions must have a return type of void and a signature matching that 106 | of the signal object - i.e. given a Signal object: 107 | ``` 108 | BSignals::Signal signalInt; 109 | ``` 110 | Connected slots must must have the signature: 111 | ``` 112 | void functionName(int a, int b); 113 | ``` 114 | To connect a function, an executor is specified as the first argument, and the 115 | function name as the second. 116 | ``` 117 | //id can be used later for disconnection 118 | int id = signal.connectSlot(BSignals::ExecutorScheme::SYNCHRONOUS, functionName); 119 | ``` 120 | Alternative executor schemes can also be specified (see Executor section below 121 | for more details). 122 | ``` 123 | signal.connectSlot(BSignals::ExecutorScheme::DEFERRED_SYNCHRONOUS, functionName); 124 | signal.connectSlot(BSignals::ExecutorScheme::ASYNCHRONOUS, functionName); 125 | signal.connectSlot(BSignals::ExecutorScheme::STRAND, functionName); 126 | signal.connectSlot(BSignals::ExecutorScheme::THREAD_POOLED, functionName); 127 | ``` 128 | To connect a member function, an executor is specified as the first argument, 129 | the member function name as the second, and the instance reference/pointer as the third. 130 | ``` 131 | Foo foo; 132 | 133 | //connect by pointer 134 | int id1 = signal.connectMemberSlot(BSignals::ExecutorScheme::SYNCHRONOUS, &Foo::bar, &foo); 135 | 136 | //connect by reference 137 | int id2 = signal.connectMemberSlot(BSignals::ExecutorScheme::SYNCHRONOUS, &Foo::bar, foo); 138 | ``` 139 | ####Emit 140 | To emit on a given signal, call emitSignal with the emission parameters. 141 | ``` 142 | signal.emitSignal(arg1, arg2); 143 | ``` 144 | You can also use the () operator overload which invokes the emitSignal function. 145 | ``` 146 | signal(arg1, arg2); 147 | ``` 148 | ####Disconnect 149 | To disconnect a slot, call disconnectSlot with the id acquired on connection. 150 | ``` 151 | //disconnection/connection should not be interleaved with emission 152 | //unless the signal was initialized with thread safety enabled 153 | int id = signal.connectSlot(...); 154 | signal.disconnectSlot(id); 155 | ``` 156 | It is also possible to disconnect all connected slots 157 | ``` 158 | signal.disconnectAllSlots(); 159 | ``` 160 | ##Executors 161 | Executors determine how a connected slot is invoked on emission. There are 5 162 | different executor modes. 163 | 164 | ####Synchronous 165 | - Emission occurs synchronously. 166 | - When emit returns, all connected slots have been invoked and returned. 167 | - Preferred for slots when 168 | - they have short execution time 169 | - quick emission is required 170 | - Necessary to know that the function has returned before proceeding 171 | 172 | ####Deferred Synchronous 173 | - Emission occurs synchronously. 174 | - When emit returns, emission has been enqueued for later execution 175 | - Deferred emissions can be invoked using the invokeDeferred function 176 | - Preferred for slots when 177 | - the time the slots are executed needs to be controlled 178 | - there is a designated event processor or event loop (such as a GUI render loop) 179 | 180 | ####Asynchronous 181 | - Emission occurs asynchronously. 182 | - A detached thread is spawned on emission. 183 | - The thread is destroyed when the connected slot returns. 184 | - Preferred for slots when 185 | - they have very long, unbounded, or infinite execution time 186 | - they are independent 187 | - additional thread overhead is not an issue 188 | - separate thread required for lifetime of invocation 189 | 190 | ####Strand 191 | - Emission occurs asynchronously. 192 | - A dedicated thread is spawned on slot connection to wait for new messages 193 | - Emitted parameters are enqueued on the waiting thread to be processed synchronously 194 | - The underlying queue is a (mostly) lock free multi-producer single consumer queue 195 | - Preferred for slots when 196 | - they have long, bounded, or finite execution time 197 | - emissions occur in blocks 198 | - the additional time overhead of creating/destroying a thread for each slot would not be performant 199 | - emissions need to be processed in order of arrival (FIFO) 200 | 201 | ####Thread Pooled 202 | - Emission occurs asynchronously. 203 | - On connection, if it is the first thread pooled function slotted by any signal, 204 | the thread pool is initialized with 32 threads, all listening for queued emissions. 205 | The number of threads in the pool is not currently run-time configurable but may 206 | be in the future 207 | - Emitted parameters are bound to the mapped function and enqueued on one of the 208 | waiting thread queues 209 | - The underlying structure is an array of multi-producer single consumer queues, 210 | with tasks allocated to each queue using round robin scheduling 211 | - Jobs are stolen from other queues when none are available 212 | - Preferred for slots when 213 | - they have long, bounded, or finite execution time 214 | - the overhead of creating/destroying a thread for each slot would not be performant 215 | - the overhead of a waiting thread for each slot (as in the strand executor scheme) is unnecessary 216 | - connected functions do NOT need to be processed in order of arrival 217 | 218 | ##Limitations 219 | - Cannot return values from emissions - only void functions/lambdas are accepted 220 | - Requires C++14 for variadic argument <-> tuple unpacking 221 | -------------------------------------------------------------------------------- /src/details/BasicTimer.cpp: -------------------------------------------------------------------------------- 1 | #include "BSignals/details/BasicTimer.h" 2 | #include 3 | 4 | using BSignals::details::BasicTimer; 5 | 6 | BasicTimer::BasicTimer() 7 | : running(false) {} 8 | 9 | double BasicTimer::getElapsedSeconds() { 10 | return std::chrono::duration(getElapsedDuration()).count(); 11 | } 12 | 13 | double BasicTimer::getElapsedMilliseconds() { 14 | return std::chrono::duration(getElapsedDuration()).count(); 15 | } 16 | 17 | double BasicTimer::getElapsedMicroseconds() { 18 | return std::chrono::duration(getElapsedDuration()).count(); 19 | } 20 | 21 | double BasicTimer::getElapsedNanoseconds() { 22 | return std::chrono::duration(getElapsedDuration()).count(); 23 | } 24 | 25 | std::chrono::duration BasicTimer::getElapsedDuration() { 26 | if (!running){ 27 | std::chrono::duration elapsed = end-begin; 28 | return elapsed; 29 | } 30 | auto n = std::chrono::high_resolution_clock::now(); 31 | std::chrono::duration elapsed = n-begin; 32 | return elapsed; 33 | } 34 | 35 | bool BasicTimer::isRunning() { 36 | return running; 37 | } 38 | 39 | bool BasicTimer::start() { 40 | if (running) return false; 41 | running = true; 42 | begin = std::chrono::high_resolution_clock::now(); 43 | return true; 44 | } 45 | 46 | bool BasicTimer::stop() { 47 | if (!running) return false; 48 | end = std::chrono::high_resolution_clock::now(); 49 | running = false; 50 | return true; 51 | } 52 | -------------------------------------------------------------------------------- /src/details/Semaphore.cpp: -------------------------------------------------------------------------------- 1 | #include "BSignals/details/Semaphore.h" 2 | 3 | using BSignals::details::Semaphore; 4 | 5 | Semaphore::Semaphore(uint32_t size) 6 | : semCounter(size), initial(size) {} 7 | 8 | Semaphore::~Semaphore() {} 9 | 10 | void Semaphore::acquire() { 11 | std::unique_lock lock(semMutex); 12 | while (semCounter <= 0){ 13 | semCV.wait(lock); 14 | } 15 | --semCounter; 16 | } 17 | 18 | void Semaphore::release() { 19 | ++semCounter; 20 | semCV.notify_one(); 21 | } 22 | 23 | void Semaphore::acquireAll() { 24 | for (uint32_t i=0; i 3 | 4 | using BSignals::details::SharedMutex; 5 | 6 | void SharedMutex::lock() { 7 | m_writers.fetch_add(1, std::memory_order_release); 8 | std::unique_lock lock(m_mutex); 9 | while (m_readers || m_writer){ 10 | m_condVar.wait(lock); 11 | } 12 | m_writer.store(true, std::memory_order_release); 13 | } 14 | 15 | void SharedMutex::unlock() { 16 | m_writer.store(false, std::memory_order_release); 17 | m_writers.fetch_sub(1, std::memory_order_release); 18 | m_condVar.notify_one(); 19 | } 20 | 21 | void SharedMutex::lock_shared(){ 22 | m_readers.fetch_add(1, std::memory_order_release); 23 | if (m_writers.load(std::memory_order_acquire)){ 24 | m_readers.fetch_sub(1, std::memory_order_release); 25 | while (m_writers.load(std::memory_order_acquire)){ 26 | std::this_thread::yield(); 27 | } 28 | m_readers.fetch_add(1, std::memory_order_release); 29 | } 30 | } 31 | 32 | void SharedMutex::unlock_shared() { 33 | m_readers.fetch_sub(1, std::memory_order_release); 34 | if (m_writers.load(std::memory_order_acquire)) m_condVar.notify_one(); 35 | } 36 | -------------------------------------------------------------------------------- /src/details/WheeledThreadPool.cpp: -------------------------------------------------------------------------------- 1 | #include "BSignals/details/WheeledThreadPool.h" 2 | #include "BSignals/details/BasicTimer.h" 3 | #include 4 | 5 | using std::mutex; 6 | using std::lock_guard; 7 | using std::atomic; 8 | using std::vector; 9 | using BSignals::details::Wheel; 10 | using BSignals::details::MPSCQueue; 11 | using BSignals::details::WheeledThreadPool; 12 | using BSignals::details::BasicTimer; 13 | 14 | std::mutex WheeledThreadPool::tpLock; 15 | bool WheeledThreadPool::isStarted = false; 16 | std::chrono::duration WheeledThreadPool::maxWait; 17 | Wheel, 256>, WheeledThreadPool::nThreads> WheeledThreadPool::threadPooledFunctions {}; 18 | std::vector WheeledThreadPool::queueMonitors; 19 | 20 | WheeledThreadPool::_init WheeledThreadPool::_initializer; 21 | 22 | WheeledThreadPool::_init::_init(){ 23 | //make a conservative estimate of when blocking will 24 | //be faster than spinning 25 | BasicTimer bt; 26 | MPSCQueue tq; 27 | tq.enqueue(0); 28 | int x; 29 | bt.start(); 30 | tq.blockingDequeue(x); 31 | bt.stop(); 32 | maxWait = bt.getElapsedDuration()*2; 33 | } 34 | 35 | WheeledThreadPool::_init::~_init() { 36 | std::lock_guard lock(tpLock); 37 | isStarted = false; 38 | for (uint32_t i=0; i task) noexcept{ 47 | threadPooledFunctions.getSpoke().enqueue(task); 48 | //threadPooledFunctions.getSpokeRandom().enqueue(task); 49 | } 50 | 51 | void WheeledThreadPool::startup() { 52 | std::lock_guard lock(tpLock); 53 | if (!isStarted){ 54 | isStarted = true; 55 | for (unsigned int i=0; i WheeledThreadPool::getMaxWait() { 62 | return maxWait; 63 | } 64 | 65 | void WheeledThreadPool::queueListener(uint32_t index) { 66 | auto &spoke = threadPooledFunctions.getSpoke(index); 67 | std::function func; 68 | std::chrono::duration waitTime = std::chrono::nanoseconds(1); 69 | const uint32_t wrap = threadPooledFunctions.size(); 70 | auto wrapIncrementer = [wrap](uint32_t i){return (i+1 == wrap ? 0 : i+1);}; 71 | 72 | while (isStarted){ 73 | if (spoke.dequeue(func)){ 74 | spoke.transferMaxToCache(); 75 | if (func) func(); 76 | waitTime = std::chrono::nanoseconds(1); 77 | } 78 | else{ 79 | bool found = false; 80 | for (uint32_t i=wrapIncrementer(index); i != index; i=wrapIncrementer(i)){ 81 | if (threadPooledFunctions.getSpoke(i).fastDequeue(func)){ 82 | found = true; 83 | break; 84 | } 85 | } 86 | if (found){ 87 | if (func) func(); 88 | waitTime = std::chrono::nanoseconds(1); 89 | } 90 | else{ 91 | std::this_thread::sleep_for(waitTime); 92 | waitTime*=2; 93 | } 94 | } 95 | if (waitTime > maxWait){ 96 | spoke.blockingDequeue(func); 97 | if (func) func(); 98 | waitTime = std::chrono::nanoseconds(1); 99 | } 100 | } 101 | } -------------------------------------------------------------------------------- /test/FunctionTimeRegular.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * File: FunctionTimeRegular.hpp 3 | * Author: Barath Kannan 4 | * Executes a function regularly on a thread 5 | * Created on May 6, 2016, 2:39 PM 6 | */ 7 | 8 | #ifndef BSIGNALS_FUNCTIONTIMEREGULAR_HPP 9 | #define BSIGNALS_FUNCTIONTIMEREGULAR_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | template 19 | class FunctionTimeRegular { 20 | public: 21 | 22 | template 23 | FunctionTimeRegular(std::function&& function, std::chrono::duration<_Rep, _Period>&& interval){ 24 | m_tfunc = function; 25 | m_interval = std::chrono::duration(interval); 26 | mainThread = std::thread(&FunctionTimeRegular::threadLoop, this); 27 | } 28 | 29 | template 30 | FunctionTimeRegular(F&& function, I&& instance, std::chrono::duration<_Rep, _Period>&& interval){ 31 | m_tfunc = std::function(objectBind(function, instance)); 32 | m_interval = std::chrono::duration(interval); 33 | mainThread = std::thread(&FunctionTimeRegular::threadLoop, this); 34 | } 35 | 36 | ~FunctionTimeRegular(){ 37 | stop(); 38 | if (mainThread.joinable()) 39 | mainThread.join(); 40 | } 41 | 42 | void join(){ 43 | mainThread.join(); 44 | } 45 | 46 | void stop(){ 47 | m_keepGoing=false; 48 | m_cv.notify_one(); 49 | } 50 | 51 | void stopAndJoin(){ 52 | stop(); 53 | join(); 54 | } 55 | 56 | private: 57 | //Reference to instance 58 | template 59 | std::function objectBind(F&& function, I&& instance) const { 60 | return[=, &instance](Args... args){ 61 | (instance.*function)(args...); 62 | }; 63 | } 64 | 65 | //Pointer to instance 66 | template 67 | std::function objectBind(F&& function, I* instance) const { 68 | return objectBind(function, *instance); 69 | } 70 | 71 | void threadLoop(){ 72 | auto begin = std::chrono::high_resolution_clock::now(); 73 | std::chrono::duration elapsed = std::chrono::high_resolution_clock::now() - begin; 74 | std::unique_lock lock(m_mutex); 75 | for (std::chrono::duration lastTime=elapsed; m_keepGoing; lastTime += m_interval){ 76 | if (!m_tfunc()) 77 | break; 78 | elapsed = std::chrono::high_resolution_clock::now() - begin; 79 | m_cv.wait_for(lock, m_interval - (elapsed-lastTime)); 80 | } 81 | } 82 | 83 | mutable std::atomic m_keepGoing{true}; 84 | mutable std::mutex m_mutex; 85 | mutable std::condition_variable m_cv; 86 | mutable std::thread mainThread; 87 | mutable std::chrono::duration m_interval; 88 | mutable std::function m_tfunc; 89 | }; 90 | 91 | #endif /* BSIGNALS_FUNCTIONTIMEREGULAR_HPP */ 92 | 93 | -------------------------------------------------------------------------------- /test/SafeQueue.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * File: SafeQueue.hpp 3 | * Author: Barath Kannan 4 | * 5 | * Created on April 21, 2016, 10:28 PM 6 | */ 7 | 8 | #ifndef BSIGNALS_SAFEQUEUE_HPP 9 | #define BSIGNALS_SAFEQUEUE_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace BSignals{ namespace details{ 18 | template 19 | class SafeQueue{ 20 | public: 21 | 22 | //Default constructed object is returned when forced stop is required 23 | //Otherwise, constructor parameters can be provided 24 | template 25 | SafeQueue(Args&& ...args) : shutdownObject(args...), terminateFlag (false), q(), m(), c() {} 26 | 27 | ~SafeQueue(){ 28 | stop(); 29 | } 30 | 31 | void enqueue(const T &t){ 32 | std::unique_lock lock(m); 33 | q.push(t); 34 | lock.unlock(); 35 | c.notify_one(); 36 | } 37 | 38 | T dequeue(void){ 39 | std::unique_lock lock(m); 40 | if (terminateFlag) return shutdownObject; 41 | while (q.empty()){ 42 | c.wait(lock); 43 | if (terminateFlag) return shutdownObject; 44 | } 45 | T val = q.front(); 46 | q.pop(); 47 | return val; 48 | } 49 | 50 | std::vector dequeueAll(){ 51 | std::unique_lock lock(m); 52 | while (q.empty()){ 53 | c.wait(lock); 54 | if (terminateFlag){ 55 | std::vector ret(1); 56 | ret[0] = shutdownObject; 57 | return ret; 58 | } 59 | } 60 | std::vector ret(q.size()); 61 | for (uint32_t i=0; !q.empty(); ++i){ 62 | ret[i] = q.front(); 63 | q.pop(); 64 | } 65 | return ret; 66 | } 67 | 68 | std::pair waitForDequeue(std::chrono::duration timeout){ 69 | std::pair ret; 70 | ret.second = false; 71 | std::unique_lock lock(m); 72 | if (terminateFlag){ 73 | return ret; 74 | } 75 | bool success = (c.wait_for(lock, timeout) == std::cv_status::no_timeout); 76 | if (!success) return ret; 77 | ret.first = q.front(); 78 | q.pop(); 79 | ret.second = true; 80 | return ret; 81 | } 82 | 83 | std::pair nonBlockingDequeue(void){ 84 | std::unique_lock lock(m); 85 | std::pair ret; 86 | if (!q.empty()){ 87 | ret.first = q.front(); 88 | q.pop(); 89 | ret.second = true; 90 | } 91 | else{ 92 | ret.second = false; 93 | } 94 | 95 | return ret; 96 | } 97 | 98 | void clear(){ 99 | std::lock_guard lock(m); 100 | while (!q.empty()){ 101 | q.pop(); 102 | } 103 | } 104 | 105 | void wakeWaiters(){ 106 | c.notify_all(); 107 | } 108 | 109 | void wait(){ 110 | std::unique_lock lock(m); 111 | if (terminateFlag) return; 112 | if (q.empty()){ 113 | c.wait(lock); 114 | } 115 | } 116 | 117 | bool wait(std::chrono::duration timeout){ 118 | auto start = std::chrono::high_resolution_clock::now(); 119 | std::unique_lock lock(m); 120 | if (!q.empty()) return true; 121 | if (terminateFlag) return false; 122 | auto now = std::chrono::high_resolution_clock::now(); 123 | return (c.wait_for(lock, timeout - (now - start)) == std::cv_status::no_timeout); 124 | } 125 | 126 | void stop(){ 127 | terminateFlag = true; 128 | wakeWaiters(); 129 | } 130 | 131 | bool isStopped(){ 132 | return terminateFlag; 133 | } 134 | 135 | unsigned int size(){ 136 | std::lock_guard lock(m); 137 | return q.size(); 138 | } 139 | 140 | bool isEmpty(){ 141 | std::lock_guard lock(m); 142 | return q.empty(); 143 | } 144 | 145 | private: 146 | T shutdownObject; 147 | bool terminateFlag; 148 | std::queue q; 149 | std::mutex m; 150 | std::condition_variable c; 151 | }; 152 | }} 153 | #endif /* BSIGNALS_SAFEQUEUE_HPP */ 154 | 155 | -------------------------------------------------------------------------------- /test/SignalTest.cpp: -------------------------------------------------------------------------------- 1 | #include "SignalTest.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "BSignals/details/BasicTimer.h" 9 | #include "SafeQueue.hpp" 10 | #include "FunctionTimeRegular.hpp" 11 | 12 | using BSignals::details::SafeQueue; 13 | using BSignals::details::BasicTimer; 14 | using std::cout; 15 | using std::endl; 16 | using ::testing::Values; 17 | using std::list; 18 | using std::vector; 19 | using std::thread; 20 | using std::atomic; 21 | using std::fixed; 22 | using BSignals::Signal; 23 | using BSignals::ExecutorScheme; 24 | 25 | std::atomic globalStaticIntX{0}; 26 | 27 | struct BigThing { 28 | char thing[512]; 29 | }; 30 | SafeQueue sq; 31 | 32 | void SignalTest::SetUp() { 33 | globalStaticIntX = 0; 34 | } 35 | 36 | void SignalTest::TearDown() { 37 | 38 | } 39 | 40 | void pushToQueue(BigThing bt) { 41 | sq.enqueue(bt); 42 | } 43 | 44 | void staticSumFunction(int a, int b) { 45 | globalStaticIntX += a + b; 46 | //cout << a << " + " << b << " = " << globalStaticIntX << endl; 47 | } 48 | 49 | TEST_F(SignalTest, MetaTest){ 50 | cout << "Instantiating signal object" << endl; 51 | 52 | Signal testSignal; 53 | cout << "Size of signal: " << sizeof(testSignal) << endl; 54 | BSignals::details::MPSCQueue> mpscQ; 55 | cout << "Size of MPSCQ: " << sizeof(mpscQ) << endl; 56 | 57 | auto dur = BSignals::details::WheeledThreadPool::getMaxWait(); 58 | cout << "Max wait: " << std::chrono::duration(dur).count() << endl; 59 | } 60 | 61 | TEST_F(SignalTest, SynchronousSignal) { 62 | cout << "Instantiating signal object" << endl; 63 | Signal testSignal; 64 | BasicTimer bt; 65 | cout << "Connecting signal" << endl; 66 | bt.start(); 67 | int id = testSignal.connectSlot(ExecutorScheme::SYNCHRONOUS, staticSumFunction); 68 | bt.stop(); 69 | cout << "Time to connect: " << bt.getElapsedMilliseconds() << "ms" << endl; 70 | 71 | cout << "Emitting signal" << endl; 72 | 73 | bt.start(); 74 | testSignal(1, 2); 75 | bt.stop(); 76 | cout << "Time to emit: " << bt.getElapsedMilliseconds() << "ms" << endl; 77 | 78 | ASSERT_EQ(globalStaticIntX, 3); 79 | ASSERT_EQ(0, id); 80 | 81 | testSignal.disconnectSlot(0); 82 | } 83 | 84 | TEST_F(SignalTest, DeferredSynchronousSignal) { 85 | cout << "Instantiating signal object" << endl; 86 | 87 | Signal testSignal; 88 | 89 | BasicTimer bt; 90 | cout << "Connecting signal" << endl; 91 | bt.start(); 92 | testSignal.connectSlot(ExecutorScheme::DEFERRED_SYNCHRONOUS, staticSumFunction); 93 | bt.stop(); 94 | cout << "Time to connect: " << bt.getElapsedMilliseconds() << "ms" << endl; 95 | 96 | cout << "Emitting signal" << endl; 97 | 98 | bt.start(); 99 | testSignal(1, 2); 100 | bt.stop(); 101 | cout << "Time to emit: " << bt.getElapsedMilliseconds() << "ms" << endl; 102 | 103 | ASSERT_NE(globalStaticIntX, 3); 104 | 105 | testSignal.invokeDeferred(); 106 | 107 | ASSERT_EQ(globalStaticIntX, 3); 108 | 109 | testSignal.disconnectSlot(0); 110 | } 111 | 112 | TEST_F(SignalTest, AsynchronousSignal) { 113 | cout << "Instantiating signal object" << endl; 114 | 115 | Signal testSignal; 116 | 117 | BasicTimer bt; 118 | BasicTimer bt2; 119 | cout << "Connecting signal" << endl; 120 | bt.start(); 121 | int id = testSignal.connectSlot(ExecutorScheme::ASYNCHRONOUS, staticSumFunction); 122 | bt.stop(); 123 | cout << "Time to connect: " << bt.getElapsedMilliseconds() << "ms" << endl; 124 | 125 | cout << "Emitting signal" << endl; 126 | 127 | bt.start(); 128 | bt2.start(); 129 | testSignal.emitSignal(1, 2); 130 | bt.stop(); 131 | 132 | while (bt2.getElapsedSeconds() < 0.1) { 133 | if (globalStaticIntX == 3) { 134 | bt2.stop(); 135 | break; 136 | } 137 | } 138 | ASSERT_LT(bt2.getElapsedSeconds(), 0.1); 139 | ASSERT_EQ(globalStaticIntX, 3); 140 | 141 | cout << "Time to emit: " << bt.getElapsedMilliseconds() << "ms" << endl; 142 | cout << "Time to emit and process: " << bt2.getElapsedMilliseconds() << "ms" << endl; 143 | cout << "Net time to process: " << bt2.getElapsedMilliseconds() - bt.getElapsedMilliseconds() << "ms" << endl; 144 | 145 | ASSERT_EQ(0, id); 146 | 147 | testSignal.disconnectSlot(0); 148 | } 149 | 150 | TEST_F(SignalTest, StrandSignal) { 151 | cout << "Instantiating signal object" << endl; 152 | 153 | Signal testSignal; 154 | 155 | BasicTimer bt; 156 | BasicTimer bt2; 157 | cout << "Connecting signal" << endl; 158 | bt.start(); 159 | int id = testSignal.connectSlot(ExecutorScheme::STRAND, staticSumFunction); 160 | bt.stop(); 161 | cout << "Time to connect: " << bt.getElapsedMilliseconds() << "ms" << endl; 162 | 163 | cout << "Emitting signal" << endl; 164 | 165 | bt.start(); 166 | bt2.start(); 167 | testSignal.emitSignal(1, 2); 168 | bt.stop(); 169 | 170 | while (bt2.getElapsedSeconds() < 0.1) { 171 | if (globalStaticIntX == 3) { 172 | bt2.stop(); 173 | break; 174 | } 175 | } 176 | ASSERT_LT(bt2.getElapsedSeconds(), 0.1); 177 | ASSERT_EQ(globalStaticIntX, 3); 178 | 179 | cout << "Time to emit: " << bt.getElapsedMilliseconds() << "ms" << endl; 180 | cout << "Time to emit and process: " << bt2.getElapsedMilliseconds() << "ms" << endl; 181 | cout << "Net time to process: " << bt2.getElapsedMilliseconds() - bt.getElapsedMilliseconds() << "ms" << endl; 182 | 183 | ASSERT_EQ(0, id); 184 | 185 | testSignal.disconnectAllSlots(); 186 | 187 | } 188 | 189 | TEST_F(SignalTest, MultipleConnectionTypes) { 190 | cout << "Testing multiple connection types for single signal" << endl; 191 | Signal testSignal; 192 | 193 | cout << "Connecting signals" << endl; 194 | list ids; 195 | ids.push_back(testSignal.connectSlot(ExecutorScheme::SYNCHRONOUS, pushToQueue)); 196 | ids.push_back(testSignal.connectSlot(ExecutorScheme::ASYNCHRONOUS, pushToQueue)); 197 | ids.push_back(testSignal.connectSlot(ExecutorScheme::STRAND, pushToQueue)); 198 | 199 | cout << "Emitting signal" << endl; 200 | BasicTimer bt; 201 | BasicTimer bt2; 202 | 203 | bt.start(); 204 | bt2.start(); 205 | BigThing bigthing; 206 | for (uint32_t i = 0; i < 10; i++) { 207 | testSignal.emitSignal(bigthing); 208 | } 209 | bt2.stop(); 210 | 211 | cout << "Dequeueing" << endl; 212 | for (int i = 0; i < 30; i++) { 213 | sq.dequeue(); 214 | } 215 | 216 | bt.stop(); 217 | 218 | cout << "Signals emitted" << endl; 219 | cout << "Total time for emission: " << bt2.getElapsedMilliseconds() << "ms" << endl; 220 | cout << "Total time for emission and processing: " << bt.getElapsedMilliseconds() << "ms" << endl; 221 | cout << "Average emission+processing time: " << bt.getElapsedMilliseconds() / 10.0 << "ms" << endl; 222 | ASSERT_LT(bt2.getElapsedSeconds(), 0.1); 223 | ASSERT_LT(bt.getElapsedSeconds(), 0.2); 224 | } 225 | 226 | class TestClass { 227 | public: 228 | 229 | TestClass() { 230 | counter = 0; 231 | internalSignal.connectMemberSlot(ExecutorScheme::SYNCHRONOUS, &TestClass::incrementCounter, this); 232 | } 233 | 234 | ~TestClass() { 235 | } 236 | 237 | void dostuff(int a) { 238 | cout << "Incrementing by " << a << endl; 239 | counter++; 240 | cout << "Result: " << counter << endl; 241 | } 242 | 243 | void dostuffconst(int a) const { 244 | cout << "Incrementing by " << a << endl; 245 | counter++; 246 | cout << "Result: " << counter << endl; 247 | } 248 | 249 | void emitIncrement() { 250 | cout << "Emitting increment signal from within class" << endl; 251 | internalSignal.emitSignal(1); 252 | cout << "Result: " << counter << endl; 253 | } 254 | 255 | void incrementCounter(uint32_t amount) { 256 | counter += amount; 257 | } 258 | 259 | uint32_t getCounter() { 260 | return counter; 261 | } 262 | 263 | uint32_t getCounter() const { 264 | return counter; 265 | } 266 | 267 | mutable atomic counter; 268 | Signal internalSignal; 269 | }; 270 | 271 | TEST_F(SignalTest, MemberFunction) { 272 | TestClass tc; 273 | Signal testSignal; 274 | 275 | testSignal.connectMemberSlot(ExecutorScheme::SYNCHRONOUS, &TestClass::dostuff, tc); 276 | testSignal.connectMemberSlot(ExecutorScheme::SYNCHRONOUS, &TestClass::dostuffconst, tc); 277 | 278 | testSignal.emitSignal(1); 279 | 280 | ASSERT_EQ(tc.getCounter(), 2u); 281 | 282 | tc.emitIncrement(); 283 | 284 | ASSERT_EQ(tc.getCounter(), 3u); 285 | 286 | testSignal.connectMemberSlot(ExecutorScheme::SYNCHRONOUS, &TestClass::dostuff, &tc); 287 | 288 | testSignal.emitSignal(1); 289 | ASSERT_EQ(tc.getCounter(), 6u); 290 | 291 | Signal testSignal2; 292 | testSignal2.connectMemberSlot(ExecutorScheme::SYNCHRONOUS, &TestClass::dostuffconst, tc); 293 | 294 | testSignal2.emitSignal(1); 295 | 296 | ASSERT_EQ(tc.getCounter(), 7u); 297 | 298 | const TestClass tc2; 299 | 300 | testSignal2.connectMemberSlot(ExecutorScheme::SYNCHRONOUS, &TestClass::dostuffconst, tc2); 301 | testSignal2.connectMemberSlot(ExecutorScheme::SYNCHRONOUS, &TestClass::dostuffconst, &tc2); 302 | testSignal2.emitSignal(1); 303 | ASSERT_EQ(tc2.getCounter(), 2u); 304 | } 305 | 306 | TEST_F(SignalTest, MultiEmit){ 307 | cout << "Instantiating signal object" << endl; 308 | 309 | Signal testSignal; 310 | 311 | BasicTimer bt; 312 | BasicTimer bt2; 313 | cout << "Connecting signal" << endl; 314 | bt.start(); 315 | int id = testSignal.connectSlot(ExecutorScheme::STRAND, staticSumFunction); 316 | bt.stop(); 317 | cout << "Time to connect: " << bt.getElapsedMilliseconds() << "ms" << endl; 318 | 319 | cout << "Emitting signal" << endl; 320 | 321 | bt.start(); 322 | list threads; 323 | const uint32_t nThreads = 64; 324 | std::atomic threadsRemaining{nThreads}; 325 | for (uint32_t i=0; i 12 | #include "BSignals/Signal.hpp" 13 | 14 | class SignalTest : public testing::Test{ 15 | public: 16 | virtual void SetUp(); 17 | virtual void TearDown(); 18 | 19 | }; 20 | 21 | #endif /* BSIGNALS_SIGNALTEST_H */ 22 | -------------------------------------------------------------------------------- /test/SignalTest_Parametrized.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: SignalTest_Parametrized.h 3 | * Author: Barath Kannan 4 | * 5 | * Created on 25 August 2016, 8:28 AM 6 | */ 7 | 8 | #ifndef SIGNALTEST_PARAMETRIZED_H 9 | #define SIGNALTEST_PARAMETRIZED_H 10 | 11 | #include "SignalTest.h" 12 | #include "BSignals/details/BasicTimer.h" 13 | #include 14 | 15 | struct SignalTestParameters{ 16 | uint32_t nConnections; 17 | uint32_t nEmissions; 18 | uint32_t nOperations; 19 | uint32_t nEmitters; 20 | bool threadSafe; 21 | BSignals::ExecutorScheme scheme; 22 | }; 23 | 24 | class SignalTestParametrized : public SignalTest, 25 | public testing::WithParamInterface< ::testing::tuple >{ 26 | public: 27 | virtual void SetUp(); 28 | virtual void TearDown(); 29 | protected: 30 | SignalTestParameters params; 31 | BSignals::details::BasicTimer bt, bt2; 32 | std::atomic counter{0}; 33 | std::atomic actual{0}; 34 | std::atomic completedFunctions{0}; 35 | typedef uint64_t sigType; 36 | }; 37 | 38 | #endif /* SIGNALTEST_PARAMETRIZED_H */ 39 | 40 | --------------------------------------------------------------------------------