├── .hgignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake ├── MSVCRuntime.cmake └── configure.cmake ├── include └── god_adapter │ ├── async.h │ ├── batch.h │ ├── decl.h │ ├── detail │ └── rotate.h │ ├── god_adapter.h │ ├── holder.h │ ├── invariant.h │ ├── lazy.h │ └── shared.h └── tests ├── CMakeLists.txt ├── async.cpp ├── batch.cpp ├── integral.cpp ├── invariant.cpp ├── lazy.cpp ├── shared.cpp ├── ut.h └── ut_main.cpp /.hgignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | .git* 3 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Grigory Demchenko (aka gridem) 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | cmake_minimum_required(VERSION 2.8) 16 | 17 | project(god_adapter CXX) 18 | 19 | option(BUILD_TESTS "Build unit tests" ON) 20 | 21 | file(GLOB_RECURSE god_adapter_hdrs include/*) 22 | 23 | add_library(god_adapter INTERFACE) 24 | target_include_directories(god_adapter INTERFACE include) 25 | target_sources(god_adapter INTERFACE ${god_adapter_hdrs}) 26 | 27 | if(BUILD_TESTS) 28 | add_subdirectory(tests) 29 | endif() 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # God Adapter 2 | 3 | ## Description 4 | 5 | Universal adapter to transform methods of any class. 6 | 7 | For detailed information please read the following article: 8 | 9 | 1. [Replicated Object. Part 2: God Adapter](http://gridem.blogspot.com/2015/11/replicated-object-part-2-god-adapter.html) 10 | 11 | ## Build Requirements 12 | 13 | * Supported compilers (must support c++14): 14 | * GCC 15 | * Clang 16 | * MSVC (2015) 17 | * Libraries: BOOST, version >= 1.56 18 | -------------------------------------------------------------------------------- /cmake/MSVCRuntime.cmake: -------------------------------------------------------------------------------- 1 | function(configure_msvc_runtime) 2 | if(MSVC) 3 | # Default to statically-linked runtime. 4 | if("${MSVC_RUNTIME}" STREQUAL "") 5 | set(MSVC_RUNTIME "static") 6 | endif() 7 | 8 | # Set compiler options. 9 | set(variables 10 | CMAKE_C_FLAGS 11 | CMAKE_C_FLAGS_DEBUG 12 | CMAKE_C_FLAGS_MINSIZEREL 13 | CMAKE_C_FLAGS_RELEASE 14 | CMAKE_C_FLAGS_RELWITHDEBINFO 15 | CMAKE_CXX_FLAGS 16 | CMAKE_CXX_FLAGS_DEBUG 17 | CMAKE_CXX_FLAGS_MINSIZEREL 18 | CMAKE_CXX_FLAGS_RELEASE 19 | CMAKE_CXX_FLAGS_RELWITHDEBINFO) 20 | 21 | if(${MSVC_RUNTIME} STREQUAL "static") 22 | message(STATUS "MSVC: using statically-linked runtime (/MT and /MTd).") 23 | foreach(variable ${variables}) 24 | if(${variable} MATCHES "/MD") 25 | string(REGEX REPLACE "/MD" "/MT" ${variable} "${${variable}}") 26 | endif() 27 | endforeach() 28 | else() 29 | message(STATUS "MSVC: using dynamically-linked runtime (/MD and /MDd).") 30 | foreach(variable ${variables}) 31 | if(${variable} MATCHES "/MT") 32 | string(REGEX REPLACE "/MT" "/MD" ${variable} "${${variable}}") 33 | endif() 34 | endforeach() 35 | endif() 36 | 37 | foreach(variable ${variables}) 38 | if(${variable} MATCHES "/Ob0") 39 | string(REGEX REPLACE "/Ob0" "/Ob2" ${variable} "${${variable}}") 40 | endif() 41 | endforeach() 42 | 43 | foreach(variable ${variables}) 44 | set(${variable} "${${variable}}" CACHE STRING "MSVC_${variable}" FORCE) 45 | endforeach() 46 | endif() 47 | endfunction(configure_msvc_runtime) 48 | -------------------------------------------------------------------------------- /cmake/configure.cmake: -------------------------------------------------------------------------------- 1 | option(STATIC_ALL "Use static libraries" ON) 2 | 3 | if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") 4 | set(GCC_LIKE_COMPILER ON) 5 | endif() 6 | 7 | if(NOT MSVC AND NOT GCC_LIKE_COMPILER) 8 | message(FATAL_ERROR "Supports only gcc, clang or msvc compilers") 9 | endif() 10 | 11 | if(STATIC_ALL) 12 | set(Boost_USE_STATIC_LIBS ON) 13 | set(Boost_USE_STATIC_RUNTIME ON) 14 | if(MSVC) 15 | set(MSVC_RUNTIME static) 16 | endif() 17 | if(GCC_LIKE_COMPILER) 18 | set(CMAKE_EXE_LINKER_FLAGS "-static -Wl,--whole-archive -lpthread -Wl,--no-whole-archive") 19 | endif() 20 | else() 21 | set(Boost_USE_STATIC_LIBS OFF) 22 | set(Boost_USE_STATIC_RUNTIME OFF) 23 | if(MSVC) 24 | set(MSVC_RUNTIME dynamic) 25 | endif() 26 | if(GCC_LIKE_COMPILER) 27 | set(CMAKE_EXE_LINKER_FLAGS) 28 | endif() 29 | endif() 30 | 31 | if(MSVC) 32 | include(../cmake/MSVCRuntime.cmake) 33 | configure_msvc_runtime() 34 | endif() 35 | 36 | if(GCC_LIKE_COMPILER) 37 | add_definitions(-std=c++14 -pthread) 38 | endif() 39 | 40 | include(CMakeParseArguments) 41 | 42 | function(use_boost_libraries USE_BOOST_TARGET) 43 | cmake_parse_arguments(USE_BOOST "" "" LIBS ${ARGN}) 44 | 45 | set(Boost_USE_MULTITHREADED ON) 46 | find_package(Boost 1.56 REQUIRED COMPONENTS ${USE_BOOST_LIBS}) 47 | target_include_directories(${USE_BOOST_TARGET} PRIVATE ${Boost_INCLUDE_DIR}) 48 | target_link_libraries(${USE_BOOST_TARGET} ${Boost_LIBRARIES}) 49 | endfunction() 50 | -------------------------------------------------------------------------------- /include/god_adapter/async.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "decl.h" 20 | #include "detail/rotate.h" 21 | 22 | template 23 | struct BaseCallback2Future : T_base 24 | { 25 | FWD_CTOR_TBASE(BaseCallback2Future) 26 | 27 | protected: 28 | template 29 | auto call(F f, V&&... v) 30 | { 31 | typename T_future::Promise promise; 32 | f(static_cast(*this), std::forward(v)..., [promise](auto&& val) mutable { 33 | promise.put(std::move(val)); 34 | }); 35 | return promise.future(); 36 | } 37 | }; 38 | 39 | template 40 | struct BaseFuture2Callback : T_base 41 | { 42 | FWD_CTOR_TBASE(BaseFuture2Callback) 43 | 44 | protected: 45 | struct Action 46 | { 47 | template 48 | static void apply(T_callback&& cb, F&& f, T&& t, V&&... v) 49 | { 50 | f(std::forward(t), std::forward(v)...).then(std::move(cb)); 51 | } 52 | }; 53 | 54 | template 55 | auto call(F&& f, V&&... v) 56 | { 57 | detail::Rotate::apply( 58 | std::forward(v)..., 59 | std::forward(f), 60 | *this); 61 | } 62 | }; 63 | 64 | template 65 | using AdaptedCallback = Adapter>; 66 | 67 | template 68 | using AdaptedFuture = Adapter>; 69 | 70 | -------------------------------------------------------------------------------- /include/god_adapter/batch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "decl.h" 25 | 26 | template 27 | struct BaseBatch : T_base 28 | { 29 | FWD_CTOR_TBASE(BaseBatch) 30 | 31 | void execute() 32 | { 33 | for (auto&& action: actions_) 34 | { 35 | action(); 36 | } 37 | actions_.clear(); 38 | } 39 | 40 | protected: 41 | using Action = std::function; 42 | 43 | template 44 | auto call(F f, V&&... v) 45 | { 46 | actions_.push_back([this, f, v...]() mutable { 47 | f(*this, std::move(v)...); 48 | }); 49 | } 50 | 51 | private: 52 | std::vector actions_; 53 | }; 54 | 55 | template 56 | using AdaptedBatch = Adapter>; 57 | 58 | template 59 | auto invokeWrappedAny(F&& f) -> typename std::enable_if< 60 | std::is_same::value, boost::any>::type 61 | { 62 | f(); 63 | return {}; 64 | } 65 | 66 | template 67 | auto invokeWrappedAny(F&& f) -> typename std::enable_if< 68 | !std::is_same::value, boost::any>::type 69 | { 70 | return f(); 71 | } 72 | 73 | template 74 | struct BaseBatchWithResult : T_base 75 | { 76 | FWD_CTOR_TBASE(BaseBatchWithResult) 77 | 78 | std::vector execute() 79 | { 80 | std::vector results; 81 | for (auto&& action: actions_) 82 | { 83 | results.push_back(action()); 84 | } 85 | actions_.clear(); 86 | return results; 87 | } 88 | 89 | protected: 90 | using Action = std::function; 91 | 92 | template 93 | auto call(F f, V&&... v) 94 | { 95 | actions_.push_back([this, f, v...]() -> boost::any { 96 | try 97 | { 98 | return invokeWrappedAny([&] { 99 | return f(*this, std::move(v)...); 100 | }); 101 | } 102 | catch (...) 103 | { 104 | return std::current_exception(); 105 | } 106 | }); 107 | } 108 | 109 | private: 110 | std::vector actions_; 111 | }; 112 | 113 | template 114 | using AdaptedBatchWithResult = Adapter>; 115 | 116 | -------------------------------------------------------------------------------- /include/god_adapter/decl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #define FWD_CTOR(D_type, D_base) \ 24 | template D_type(V&&... v) : D_base{std::forward(v)...} {} 25 | 26 | #define FWD_CTOR_TBASE(D_type) FWD_CTOR(D_type, T_base) 27 | #define FWD_CTOR_ADAPTER() FWD_CTOR_TBASE(Adapter) 28 | 29 | // decltype(v) instead of V is a workaround for VS compiler 30 | #define DECL_FN_ADAPTER(D_name) \ 31 | template \ 32 | auto D_name(V&&... v) \ 33 | { \ 34 | return T_base::call([](auto& t, auto&&... x) { \ 35 | return t.D_name(std::forward(x)...); \ 36 | }, std::forward(v)...); \ 37 | } 38 | 39 | #define DECL_FN_ADAPTER_ITERATION(D_r, D_data, D_elem) DECL_FN_ADAPTER(D_elem) 40 | 41 | #define DECL_FN_NAMES(...) \ 42 | FWD_CTOR_ADAPTER() \ 43 | BOOST_PP_LIST_FOR_EACH(DECL_FN_ADAPTER_ITERATION, , BOOST_PP_TUPLE_TO_LIST((__VA_ARGS__))) 44 | 45 | #define DECL_ADAPTER(D_type, ...) \ 46 | template \ 47 | struct Adapter : T_base \ 48 | { \ 49 | DECL_FN_NAMES(__VA_ARGS__) \ 50 | }; 51 | 52 | template 53 | struct Adapter : T_base 54 | { 55 | DECL_FN_NAMES(read, write, put, get, on, vote, commit) 56 | }; 57 | -------------------------------------------------------------------------------- /include/god_adapter/detail/rotate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | namespace detail { 20 | 21 | template 22 | struct Rotate; 23 | 24 | template 25 | struct Rotate 26 | { 27 | static void apply(T&& t, V&&... v) 28 | { 29 | Rotate::apply( 30 | std::forward(v)..., 31 | std::forward(t)); 32 | } 33 | }; 34 | 35 | template 36 | struct Rotate<0, T_action, T, V...> 37 | { 38 | static void apply(T&& t, V&&... v) 39 | { 40 | T_action::apply( 41 | std::forward(t), 42 | std::forward(v)...); 43 | } 44 | }; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /include/god_adapter/god_adapter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "holder.h" 20 | #include "shared.h" 21 | #include "async.h" 22 | #include "lazy.h" 23 | #include "batch.h" 24 | #include "invariant.h" 25 | -------------------------------------------------------------------------------- /include/god_adapter/holder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "decl.h" 20 | 21 | template 22 | struct BaseValue : T_base 23 | { 24 | FWD_CTOR_TBASE(BaseValue) 25 | protected: 26 | template 27 | auto call(F f, V&&... v) 28 | { 29 | return f(*this, std::forward(v)...); 30 | } 31 | }; 32 | 33 | template 34 | struct BaseRef 35 | { 36 | BaseRef(T& t) : ref_{t} {} 37 | protected: 38 | template 39 | auto call(F f, V&&... v) 40 | { 41 | return f(ref_, std::forward(v)...); 42 | } 43 | private: 44 | T& ref_; 45 | }; 46 | -------------------------------------------------------------------------------- /include/god_adapter/invariant.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "decl.h" 20 | 21 | // Dlang-like class invariant checks (https://dlang.org/spec/contracts.html#Invariants) 22 | 23 | template 24 | struct Finalizer 25 | { 26 | template 27 | explicit Finalizer(U&& u) 28 | : finally_(std::forward(u)) 29 | { 30 | } 31 | 32 | ~Finalizer() 33 | { 34 | finally_(); 35 | } 36 | 37 | private: 38 | F finally_; 39 | }; 40 | 41 | template 42 | auto finally(F&& f) 43 | { 44 | return Finalizer>{std::forward(f)}; 45 | } 46 | 47 | template 48 | struct BaseInvariantChecker : T_base 49 | { 50 | BaseInvariantChecker(BaseInvariantChecker&& other) 51 | : T_base(std::move(other)) 52 | { 53 | T_base::invariant(); 54 | other.invariant(); 55 | } 56 | 57 | template 58 | BaseInvariantChecker(V&&... v) 59 | : T_base(std::forward(v)...) 60 | { 61 | T_base::invariant(); 62 | } 63 | 64 | ~BaseInvariantChecker() 65 | { 66 | T_base::invariant(); 67 | } 68 | 69 | protected: 70 | template 71 | auto call(F f, V&&... v) 72 | { 73 | T_base::invariant(); 74 | auto _ = finally([this] { 75 | T_base::invariant(); 76 | }); 77 | return f(*this, std::forward(v)...); 78 | } 79 | }; 80 | 81 | template 82 | using AdaptedChecked = Adapter>; 83 | -------------------------------------------------------------------------------- /include/god_adapter/lazy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | 21 | #include "decl.h" 22 | 23 | template 24 | struct BaseLazy 25 | { 26 | template 27 | BaseLazy(V&&... v) 28 | // doesn't compile under MSVC 2015 29 | //: state_{[v...] {return T{std::move(v)...}; }} 30 | { 31 | state_ = Creator([v...] { 32 | return T{std::move(v)...}; 33 | }); 34 | } 35 | 36 | protected: 37 | using Creator = std::function; 38 | 39 | template 40 | auto call(F f, V&&... v) 41 | { 42 | auto* t = boost::get(&state_); 43 | if (t == nullptr) 44 | { 45 | state_ = boost::get(state_)(); 46 | t = boost::get(&state_); 47 | } 48 | return f(*t, std::forward(v)...); 49 | } 50 | 51 | private: 52 | // creator must be first because T may not contain default ctor 53 | boost::variant state_; 54 | }; 55 | 56 | template 57 | using AdaptedLazy = Adapter>; 58 | 59 | -------------------------------------------------------------------------------- /include/god_adapter/shared.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | #include 21 | 22 | #include "decl.h" 23 | 24 | template 25 | struct BaseLocker : T_base 26 | { 27 | FWD_CTOR_TBASE(BaseLocker) 28 | protected: 29 | template 30 | auto call(F f, V&&... v) 31 | { 32 | using Lock = std::lock_guard; 33 | Lock _{lock_}; 34 | return f(static_cast(*this), std::forward(v)...); 35 | } 36 | 37 | private: 38 | T_locker lock_; 39 | }; 40 | 41 | template 42 | struct BaseShared 43 | { 44 | template 45 | friend struct BaseShared; 46 | 47 | template 48 | BaseShared(Adapter&& a) : shared_{std::move(a.shared_)} {} 49 | 50 | template 51 | BaseShared(const Adapter& a) : shared_{a.shared_} {} 52 | 53 | template 54 | BaseShared(Adapter& a) : shared_{a.shared_} {} 55 | 56 | template 57 | BaseShared(V&&... v) : shared_{std::make_shared(std::forward(v)...)} {} 58 | 59 | protected: 60 | template 61 | auto call(F f, V&&... v) 62 | { 63 | return f(*shared_, std::forward(v)...); 64 | } 65 | private: 66 | std::shared_ptr shared_; 67 | }; 68 | 69 | template 70 | using AdaptedLocked = Adapter>; 71 | 72 | template 73 | using AdaptedShared = Adapter>; 74 | 75 | template 76 | using AdaptedSharedLocked = AdaptedShared>; 77 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | enable_testing() 2 | 3 | include(../cmake/configure.cmake) 4 | 5 | file(GLOB ut_srcs *.cpp *.h) 6 | 7 | add_executable(tests ${ut_srcs}) 8 | target_link_libraries(tests god_adapter) 9 | use_boost_libraries(tests LIBS unit_test_framework) 10 | add_test(tests tests) 11 | -------------------------------------------------------------------------------- /tests/async.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "ut.h" 18 | 19 | const char* const c_async = "async"; 20 | const char* const c_complete = "complete"; 21 | const char* const c_callback = "callback"; 22 | const char* const c_then = "then"; 23 | const char* const c_put = "put"; 24 | const char* const c_async1 = "async 1"; 25 | const char* const c_async2 = "async 2"; 26 | 27 | using Handler = std::function; 28 | 29 | template 30 | struct FutureTest 31 | { 32 | using F = std::function; 33 | 34 | FutureTest(const std::shared_ptr& f) : f_{f} {} 35 | 36 | void then(F f) 37 | { 38 | op(c_then); 39 | *f_ = f; 40 | } 41 | 42 | struct Promise 43 | { 44 | Promise() : f_{std::make_shared()} {} 45 | 46 | FutureTest future() 47 | { 48 | return f_; 49 | } 50 | 51 | void put(const T& v) 52 | { 53 | op(c_put); 54 | (*f_)(v); 55 | } 56 | 57 | private: 58 | std::shared_ptr f_; 59 | }; 60 | 61 | private: 62 | std::shared_ptr f_; 63 | }; 64 | 65 | struct ImplCallback 66 | { 67 | using F = std::function; 68 | 69 | void async(F cb) 70 | { 71 | op(c_async); 72 | cb_ = cb; 73 | } 74 | 75 | void complete(int v) 76 | { 77 | op(c_complete); 78 | cb_(v); 79 | } 80 | 81 | private: 82 | F cb_; 83 | }; 84 | 85 | struct Impl; 86 | DECL_ADAPTER(Impl, async) 87 | 88 | struct ImplFuture 89 | { 90 | FutureTest async(int v) 91 | { 92 | op(c_async); 93 | v_ = v; 94 | return p.future(); 95 | } 96 | 97 | FutureTest async(int v1, int v2) 98 | { 99 | op(c_async); 100 | v_ = v1 + v2; 101 | return p.future(); 102 | } 103 | 104 | void complete() 105 | { 106 | op(c_complete); 107 | p.put(v_); 108 | } 109 | 110 | private: 111 | int v_ = 0; 112 | FutureTest::Promise p; 113 | }; 114 | 115 | struct ManualFutureAdapter 116 | { 117 | ImplCallback impl_; 118 | 119 | FutureTest async() 120 | { 121 | FutureTest::Promise p; 122 | impl_.async([p](int v) mutable { 123 | p.put(v); 124 | }); 125 | return p.future(); 126 | } 127 | }; 128 | 129 | struct ManualCallbackAdapter 130 | { 131 | ImplFuture impl_; 132 | 133 | void async(int v, std::function cb) 134 | { 135 | impl_.async(v).then(cb); 136 | } 137 | }; 138 | 139 | struct ComplexCallbacks 140 | { 141 | using F1 = std::function; 142 | using F2 = std::function; 143 | 144 | void async1(int v, F1 cb) 145 | { 146 | op(c_async1); 147 | f1_ = [v, cb] { cb(v); }; 148 | } 149 | 150 | void async2(const std::string& s, F2 cb) 151 | { 152 | op(c_async2); 153 | f2_ = [s, cb] { cb(s); }; 154 | } 155 | 156 | void complete1() 157 | { 158 | op(c_complete); 159 | f1_(); 160 | } 161 | 162 | void complete2() 163 | { 164 | op(c_complete); 165 | f2_(); 166 | } 167 | 168 | private: 169 | Handler f1_; 170 | Handler f2_; 171 | }; 172 | 173 | struct Complex1 {}; 174 | DECL_ADAPTER(Complex1, async1) 175 | struct Complex2 {}; 176 | DECL_ADAPTER(Complex2, async2) 177 | 178 | BOOST_FIXTURE_TEST_SUITE(async, OpsFixture) 179 | 180 | BOOST_AUTO_TEST_CASE(Async) 181 | { 182 | ImplCallback i; 183 | i.async([](int v) { 184 | BOOST_CHECK_EQUAL(v, 3); 185 | op(c_callback); 186 | }); 187 | i.complete(3); 188 | CHECK_OPS(c_async, c_complete, c_callback); 189 | } 190 | 191 | BOOST_AUTO_TEST_CASE(ManualFuture) 192 | { 193 | ManualFutureAdapter f; 194 | f.async().then([](int v) { 195 | BOOST_CHECK_EQUAL(v, 2); 196 | op(c_callback); 197 | }); 198 | CHECK_OPS(c_async, c_then); 199 | f.impl_.complete(2); 200 | CHECK_OPS(c_async, c_then, c_complete, c_put, c_callback); 201 | } 202 | 203 | BOOST_AUTO_TEST_CASE(ManualCallback) 204 | { 205 | ManualCallbackAdapter f; 206 | f.async(5, [](int v) { 207 | BOOST_CHECK_EQUAL(v, 5); 208 | op(c_callback); 209 | }); 210 | CHECK_OPS(c_async, c_then); 211 | f.impl_.complete(); 212 | CHECK_OPS(c_async, c_then, c_complete, c_put, c_callback); 213 | } 214 | 215 | BOOST_AUTO_TEST_CASE(AdapterFuture) 216 | { 217 | AdaptedCallback, ImplCallback> f; 218 | f.async().then([](int v) { 219 | BOOST_CHECK_EQUAL(v, 2); 220 | op(c_callback); 221 | }); 222 | CHECK_OPS(c_async, c_then); 223 | f.complete(2); 224 | CHECK_OPS(c_async, c_then, c_complete, c_put, c_callback); 225 | } 226 | 227 | BOOST_AUTO_TEST_CASE(AdapterCallback) 228 | { 229 | AdaptedFuture f; 230 | f.async(3, [](int v) { 231 | BOOST_CHECK_EQUAL(v, 3); 232 | op(c_callback); 233 | }); 234 | CHECK_OPS(c_async, c_then); 235 | f.complete(); 236 | CHECK_OPS(c_async, c_then, c_complete, c_put, c_callback); 237 | } 238 | 239 | BOOST_AUTO_TEST_CASE(AdapterCallback2) 240 | { 241 | AdaptedFuture f; 242 | f.async(4, 5, [](int v) { 243 | BOOST_CHECK_EQUAL(v, 9); 244 | op(c_callback); 245 | }); 246 | CHECK_OPS(c_async, c_then); 247 | f.complete(); 248 | CHECK_OPS(c_async, c_then, c_complete, c_put, c_callback); 249 | } 250 | 251 | BOOST_AUTO_TEST_CASE(Rotate) 252 | { 253 | struct A 254 | { 255 | static void apply(int t1, int t2, int t3, int t4, int t5, int t6) 256 | { 257 | BOOST_CHECK_EQUAL(t1, 5); 258 | BOOST_CHECK_EQUAL(t2, 6); 259 | BOOST_CHECK_EQUAL(t3, 1); 260 | BOOST_CHECK_EQUAL(t4, 2); 261 | BOOST_CHECK_EQUAL(t5, 3); 262 | BOOST_CHECK_EQUAL(t6, 4); 263 | } 264 | }; 265 | 266 | detail::Rotate<4, A, int, int, int, int, int, int>::apply(1, 2, 3, 4, 5, 6); 267 | } 268 | 269 | BOOST_AUTO_TEST_CASE(ComplexAdapter) 270 | { 271 | static const char* const hello = "hello"; 272 | 273 | AdaptedCallback, AdaptedCallback, ComplexCallbacks>> c; 274 | auto fut1 = c.async1(42); 275 | CHECK_OPS(c_async1); 276 | fut1.then([](int v) { 277 | BOOST_CHECK_EQUAL(v, 42); 278 | op(c_callback); 279 | }); 280 | CHECK_OPS(c_async1, c_then); 281 | auto fut2 = c.async2(hello); 282 | CHECK_OPS(c_async1, c_then, c_async2); 283 | fut2.then([](const std::string& s) { 284 | BOOST_CHECK_EQUAL(s, hello); 285 | op(c_callback); 286 | }); 287 | CHECK_OPS(c_async1, c_then, c_async2, c_then); 288 | c.complete1(); 289 | CHECK_OPS(c_async1, c_then, c_async2, c_then, c_complete, c_put, c_callback); 290 | c.complete2(); 291 | CHECK_OPS(c_async1, c_then, c_async2, c_then, c_complete, c_put, c_callback, c_complete, c_put, c_callback); 292 | } 293 | 294 | BOOST_AUTO_TEST_SUITE_END() 295 | -------------------------------------------------------------------------------- /tests/batch.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "ut.h" 18 | 19 | const char* const c_get = "get"; 20 | const char* const c_set = "set"; 21 | 22 | struct Data 23 | { 24 | int get() const 25 | { 26 | op(c_get); 27 | return value_; 28 | } 29 | 30 | void set(int value) 31 | { 32 | op(c_set); 33 | value_ = value; 34 | } 35 | 36 | private: 37 | int value_ = 0; 38 | }; 39 | 40 | DECL_ADAPTER(Data, get, set) 41 | 42 | struct DataExc 43 | { 44 | int get() const 45 | { 46 | op(c_get); 47 | throw 1; 48 | } 49 | 50 | void set(int value) 51 | { 52 | op(c_set); 53 | throw 2; 54 | } 55 | 56 | private: 57 | int value_ = 0; 58 | }; 59 | 60 | DECL_ADAPTER(DataExc, get, set) 61 | 62 | BOOST_FIXTURE_TEST_SUITE(batch, OpsFixture) 63 | 64 | BOOST_AUTO_TEST_CASE(Normal) 65 | { 66 | Data d; 67 | CHECK_OPS(); 68 | d.get(); 69 | CHECK_OPS(c_get); 70 | d.set(1); 71 | d.set(2); 72 | CHECK_OPS(c_get, c_set, c_set); 73 | } 74 | 75 | BOOST_AUTO_TEST_CASE(Batch) 76 | { 77 | AdaptedBatch d; 78 | CHECK_OPS(); 79 | d.get(); 80 | d.set(1); 81 | d.set(2); 82 | CHECK_OPS(); 83 | d.execute(); 84 | CHECK_OPS(c_get, c_set, c_set); 85 | } 86 | 87 | BOOST_AUTO_TEST_CASE(BatchWithResult) 88 | { 89 | AdaptedBatchWithResult d; 90 | CHECK_OPS(); 91 | d.set(1); 92 | d.get(); 93 | d.set(2); 94 | d.get(); 95 | CHECK_OPS(); 96 | auto results = d.execute(); 97 | CHECK_OPS(c_set, c_get, c_set, c_get); 98 | BOOST_CHECK_EQUAL(results.size(), 4); 99 | BOOST_CHECK(results[0].empty()); 100 | BOOST_CHECK_EQUAL(boost::any_cast(results[1]), 1); 101 | BOOST_CHECK(results[2].empty()); 102 | BOOST_CHECK_EQUAL(boost::any_cast(results[3]), 2); 103 | } 104 | 105 | BOOST_AUTO_TEST_CASE(BatchWithExceptions) 106 | { 107 | AdaptedBatchWithResult d; 108 | CHECK_OPS(); 109 | d.set(1); 110 | d.get(); 111 | CHECK_OPS(); 112 | auto results = d.execute(); 113 | CHECK_OPS(c_set, c_get); 114 | BOOST_CHECK_EQUAL(results.size(), 2); 115 | auto checkException = [](auto&& val) { 116 | return [val = std::move(val)](auto&& exVal) { 117 | return val == exVal; 118 | }; 119 | }; 120 | 121 | BOOST_CHECK_EXCEPTION(std::rethrow_exception(boost::any_cast( 122 | results[0])), int, checkException(2)); 123 | BOOST_CHECK_EXCEPTION(std::rethrow_exception(boost::any_cast( 124 | results[1])), int, checkException(1)); 125 | } 126 | 127 | BOOST_AUTO_TEST_SUITE_END() 128 | -------------------------------------------------------------------------------- /tests/integral.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "ut.h" 18 | 19 | const char* const c_ctor = "ctor"; 20 | const char* const c_1 = "1"; 21 | const char* const c_2 = "2"; 22 | const char* const c_lock = "lock"; 23 | const char* const c_unlock = "unlock"; 24 | 25 | using Buffer = std::string; 26 | 27 | struct Disk 28 | { 29 | Disk() 30 | { 31 | op(c_ctor); 32 | } 33 | 34 | void write(const Buffer& buffer) 35 | { 36 | op(buffer.c_str()); 37 | } 38 | }; 39 | 40 | DECL_ADAPTER(Disk, write) 41 | 42 | struct DiskExecute; 43 | DECL_ADAPTER(DiskExecute, write, execute) 44 | 45 | struct TestMutex 46 | { 47 | void lock() 48 | { 49 | op(c_lock); 50 | } 51 | 52 | void unlock() 53 | { 54 | op(c_unlock); 55 | } 56 | }; 57 | 58 | BOOST_FIXTURE_TEST_SUITE(integral, OpsFixture) 59 | 60 | BOOST_AUTO_TEST_CASE(Batch) 61 | { 62 | AdaptedBatch disk; 63 | CHECK_OPS(c_ctor); 64 | disk.write(c_1); 65 | disk.write(c_2); 66 | CHECK_OPS(c_ctor); 67 | disk.execute(); 68 | CHECK_OPS(c_ctor, c_1, c_2); 69 | } 70 | 71 | BOOST_AUTO_TEST_CASE(Integral) 72 | { 73 | AdaptedLazy, TestMutex>>> disk; 74 | CHECK_OPS(); 75 | disk.write(c_1); 76 | CHECK_OPS(c_ctor, c_lock, c_unlock); 77 | disk.write(c_2); 78 | CHECK_OPS(c_ctor, c_lock, c_unlock, c_lock, c_unlock); 79 | disk.execute(); 80 | CHECK_OPS(c_ctor, c_lock, c_unlock, c_lock, c_unlock, c_lock, c_1, c_2, c_unlock); 81 | } 82 | 83 | BOOST_AUTO_TEST_SUITE_END() 84 | -------------------------------------------------------------------------------- /tests/invariant.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "ut.h" 18 | 19 | const char* const c_invariant = "invariant"; 20 | 21 | const char* const c_ctor = "ctor"; 22 | const char* const c_copyCtor = "copy ctor"; 23 | const char* const c_mtor = "mtor"; 24 | const char* const c_dtor = "dtor"; 25 | 26 | const char* const c_method = "method"; 27 | 28 | struct Logic 29 | { 30 | Logic() 31 | { 32 | op(c_ctor); 33 | } 34 | 35 | Logic(Logic&&) 36 | { 37 | op(c_mtor); 38 | } 39 | 40 | Logic(const Logic&) 41 | { 42 | op(c_copyCtor); 43 | } 44 | 45 | ~Logic() 46 | { 47 | op(c_dtor); 48 | } 49 | 50 | public: 51 | void method() 52 | { 53 | op(c_method); 54 | } 55 | 56 | protected: 57 | void invariant() 58 | { 59 | op(c_invariant); 60 | } 61 | }; 62 | 63 | DECL_ADAPTER(Logic, method) 64 | 65 | BOOST_FIXTURE_TEST_SUITE(invariant, OpsFixture) 66 | 67 | BOOST_AUTO_TEST_CASE(Method) 68 | { 69 | { 70 | AdaptedChecked logic; 71 | CHECK_OPS(c_ctor, c_invariant); 72 | 73 | logic.method(); 74 | CHECK_OPS(c_ctor, c_invariant, c_invariant, c_method, c_invariant); 75 | } 76 | 77 | CHECK_OPS(c_ctor, c_invariant, c_invariant, c_method, c_invariant, c_invariant, c_dtor); 78 | } 79 | 80 | BOOST_AUTO_TEST_CASE(MoveCtor) 81 | { 82 | { 83 | AdaptedChecked logic1; 84 | CHECK_OPS(c_ctor, c_invariant); 85 | 86 | AdaptedChecked logic2 = std::move(logic1); 87 | CHECK_OPS(c_ctor, c_invariant, c_mtor, c_invariant, c_invariant); 88 | } 89 | 90 | CHECK_OPS(c_ctor, c_invariant, c_mtor, c_invariant, c_invariant, c_invariant, c_dtor, c_invariant, c_dtor); 91 | } 92 | 93 | BOOST_AUTO_TEST_CASE(CopyCtor) 94 | { 95 | { 96 | AdaptedChecked logic1; 97 | CHECK_OPS(c_ctor, c_invariant); 98 | 99 | AdaptedChecked logic2 = logic1; 100 | CHECK_OPS(c_ctor, c_invariant, c_copyCtor, c_invariant); 101 | } 102 | 103 | CHECK_OPS(c_ctor, c_invariant, c_copyCtor, c_invariant, c_invariant, c_dtor, c_invariant, c_dtor); 104 | } 105 | 106 | BOOST_AUTO_TEST_SUITE_END() 107 | -------------------------------------------------------------------------------- /tests/lazy.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "ut.h" 18 | 19 | const char* const c_action = "action"; 20 | const char* const c_ctor = "ctor"; 21 | const char* const c_ctorInt = "ctor int"; 22 | const char* const c_ctorString = "ctor string"; 23 | 24 | struct Obj 25 | { 26 | Obj() 27 | { 28 | op(c_ctor); 29 | } 30 | 31 | Obj(int v) 32 | { 33 | BOOST_CHECK_EQUAL(v, 2); 34 | op(c_ctorInt); 35 | } 36 | 37 | Obj(const std::string& s) 38 | { 39 | BOOST_CHECK_EQUAL(s, "hello"); 40 | op(c_ctorString); 41 | } 42 | 43 | void action() 44 | { 45 | op(c_action); 46 | } 47 | }; 48 | 49 | DECL_ADAPTER(Obj, action) 50 | 51 | BOOST_FIXTURE_TEST_SUITE(lazy, OpsFixture) 52 | 53 | BOOST_AUTO_TEST_CASE(Normal) 54 | { 55 | Obj o; 56 | CHECK_OPS(c_ctor); 57 | o.action(); 58 | CHECK_OPS(c_ctor, c_action); 59 | o.action(); 60 | CHECK_OPS(c_ctor, c_action, c_action); 61 | } 62 | 63 | BOOST_AUTO_TEST_CASE(Lazy) 64 | { 65 | AdaptedLazy o; 66 | CHECK_OPS(); 67 | o.action(); 68 | CHECK_OPS(c_ctor, c_action); 69 | o.action(); 70 | CHECK_OPS(c_ctor, c_action, c_action); 71 | } 72 | 73 | BOOST_AUTO_TEST_CASE(LazyWithInt) 74 | { 75 | AdaptedLazy o{2}; 76 | CHECK_OPS(); 77 | o.action(); 78 | CHECK_OPS(c_ctorInt, c_action); 79 | o.action(); 80 | CHECK_OPS(c_ctorInt, c_action, c_action); 81 | } 82 | 83 | BOOST_AUTO_TEST_CASE(LazyWithString) 84 | { 85 | const char* const hello = "hello"; 86 | AdaptedLazy o{hello}; 87 | CHECK_OPS(); 88 | o.action(); 89 | CHECK_OPS(c_ctorString, c_action); 90 | o.action(); 91 | CHECK_OPS(c_ctorString, c_action, c_action); 92 | } 93 | 94 | BOOST_AUTO_TEST_SUITE_END() 95 | -------------------------------------------------------------------------------- /tests/shared.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "ut.h" 18 | 19 | const char* const c_lock = "lock"; 20 | const char* const c_unlock = "unlock"; 21 | const char* const c_action = "action"; 22 | const char* const c_copyCtor = "copy ctor"; 23 | const char* const c_dtorDerived = "dtor derived"; 24 | 25 | struct TestMutex 26 | { 27 | void lock() 28 | { 29 | op(c_lock); 30 | } 31 | 32 | void unlock() 33 | { 34 | op(c_unlock); 35 | } 36 | }; 37 | 38 | struct Counter 39 | { 40 | Counter() = default; 41 | 42 | Counter(const Counter&) 43 | { 44 | op(c_copyCtor); 45 | } 46 | 47 | void inc() 48 | { 49 | op(c_action); 50 | ++ counter; 51 | } 52 | 53 | int counter = 0; 54 | }; 55 | 56 | struct CounterDerived : Counter 57 | { 58 | ~CounterDerived() 59 | { 60 | op(c_dtorDerived); 61 | } 62 | }; 63 | 64 | DECL_ADAPTER(Counter, inc) 65 | 66 | BOOST_FIXTURE_TEST_SUITE(shared, OpsFixture) 67 | 68 | BOOST_AUTO_TEST_CASE(AdapterLock) 69 | { 70 | using MutexCounter = AdaptedLocked; 71 | 72 | MutexCounter counter; 73 | BOOST_CHECK_EQUAL(counter.counter, 0); 74 | counter.inc(); 75 | CHECK_OPS(c_lock, c_action, c_unlock); 76 | BOOST_CHECK_EQUAL(counter.counter, 1); 77 | auto counter2 = counter; 78 | CHECK_OPS(c_lock, c_action, c_unlock, c_copyCtor); 79 | } 80 | 81 | BOOST_AUTO_TEST_CASE(AdapterShared) 82 | { 83 | using SharedCounter = AdaptedShared; 84 | SharedCounter counter; 85 | counter.inc(); 86 | CHECK_OPS(c_action); 87 | auto counter2 = counter; 88 | CHECK_OPS(c_action); 89 | } 90 | 91 | BOOST_AUTO_TEST_CASE(AdapterSharedMutex) 92 | { 93 | using MutexSharedCounter = AdaptedSharedLocked; 94 | 95 | MutexSharedCounter counter; 96 | CHECK_OPS(); 97 | counter.inc(); 98 | CHECK_OPS(c_lock, c_action, c_unlock); 99 | } 100 | 101 | BOOST_AUTO_TEST_CASE(AdapterSharedDerived) 102 | { 103 | { 104 | AdaptedShared c; 105 | AdaptedShared c2 = c; 106 | c2 = c; 107 | } 108 | CHECK_OPS(); 109 | { 110 | AdaptedShared c = AdaptedShared{}; 111 | } 112 | CHECK_OPS(); 113 | { 114 | AdaptedShared c = AdaptedShared{}; 115 | CHECK_OPS(); 116 | } 117 | CHECK_OPS(c_dtorDerived); 118 | } 119 | 120 | BOOST_AUTO_TEST_SUITE_END() 121 | -------------------------------------------------------------------------------- /tests/ut.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #define CHECK_OPS(...) \ 21 | BOOST_CHECK_EQUAL(ops(), (Operations{__VA_ARGS__})); 22 | 23 | template 24 | T& single() 25 | { 26 | static T t; 27 | return t; 28 | } 29 | 30 | using Operations = std::vector; 31 | 32 | inline Operations& ops() 33 | { 34 | return single(); 35 | } 36 | 37 | inline void op(const std::string& o) 38 | { 39 | ops().push_back(o); 40 | } 41 | 42 | struct OpsFixture 43 | { 44 | ~OpsFixture() 45 | { 46 | ops().clear(); 47 | } 48 | }; 49 | 50 | namespace std { 51 | 52 | template 53 | ostream& operator<<(ostream& o, const vector& t) 54 | { 55 | bool first = true; 56 | for (auto&& v: t) 57 | { 58 | if (first) 59 | first = false; 60 | else 61 | o << ", "; 62 | o << v; 63 | } 64 | return o; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /tests/ut_main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Grigory Demchenko (aka gridem) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #define BOOST_TEST_MODULE Adapter 18 | #include 19 | --------------------------------------------------------------------------------